Prettified Code!

This commit is contained in:
darrell-thobe-sp
2024-04-18 10:31:05 +00:00
committed by GitHub Action
parent f5b6aaf14f
commit 2cd5ccfc81
223 changed files with 40526 additions and 28073 deletions

View File

@@ -1,14 +1,11 @@
# Contribute to developer.sailpoint.com
The SailPoint Developer Relations Team is always actively working to improve https://developer.sailpoint.com to make the site as useful as possible to the SailPoint Developer Community.
This means adding and maintaining new resources for the community, like new tools and educational content, along with accurate, complete, and current guides and information.
The most valuable resource of all, however, is the community itself!
We greatly appreciate any input, feedback, and direct contributions you can provide to the community, big or small.
And we want to make the process of contributing to this project as easy and transparent as possible.
The SailPoint Developer Relations Team is always actively working to improve https://developer.sailpoint.com to make the site as useful as possible to the SailPoint Developer Community. This means adding and maintaining new resources for the community, like new tools and educational content, along with accurate, complete, and current guides and information. The most valuable resource of all, however, is the community itself! We greatly appreciate any input, feedback, and direct contributions you can provide to the community, big or small. And we want to make the process of contributing to this project as easy and transparent as possible.
This document will detail the different ways that you can contribute to the community.
These are the main ways that you can contribute:
- [Report issues](#report-issues)
- [Request new features](#request-new-features)
- [Submit a fix](#submit-a-fix)
@@ -38,65 +35,55 @@ We use [GitHub Issues](https://docs.github.com/en/issues/tracking-your-work-with
## Report issues
You may encounter bugs and incorrect or outdated information when you explore the site.
We appreciate your help in identifying bugs of all sizes, from broken links or typos to major issues preventing you from using a resource.
You may encounter bugs and incorrect or outdated information when you explore the site. We appreciate your help in identifying bugs of all sizes, from broken links or typos to major issues preventing you from using a resource.
We use GitHub issues to track bugs publicly. If you see an issue with the site, please [report it here](https://github.com/sailpoint-oss/developer.sailpoint.com/issues/new?assignees=&labels=&template=bug-report.md&title=%5BBug%5D+Your+Bug+Report+Here).
We love thorough bug reports.
The more details you include, the faster we can troubleshoot and fix the issue.
Great bug reports include these details:
We love thorough bug reports. The more details you include, the faster we can troubleshoot and fix the issue. Great bug reports include these details:
1. A summary of the issue
2. The steps we can take to reproduce the issue
- Be as specific as you can when you describe these steps.
- Give us sample code if you can.
- Be as specific as you can when you describe these steps.
- Give us sample code if you can.
3. What you expect to happen
4. What actually happens
5. Screenshots
6. The operating system you were using when you encountered the issue
7. The browser you were using when you encountered the issue
8. Notes
- If you have an idea, tell us why you think the issue may be occurring, or what you think we should do to resolve it.
- Whatever you tried that didn't work.
- Anything else you think might be useful to us.
- If you have an idea, tell us why you think the issue may be occurring, or what you think we should do to resolve it.
- Whatever you tried that didn't work.
- Anything else you think might be useful to us.
## Request new features
Many of our most valuable resources originate in ideas suggested by the community!
You may have an idea that will improve the site.
We would love to hear it and possibly implement it!
Many of our most valuable resources originate in ideas suggested by the community! You may have an idea that will improve the site. We would love to hear it and possibly implement it!
We use GitHub issues to track feature requests. Please use [this template](https://github.com/sailpoint-oss/developer.sailpoint.com/issues/new?assignees=&labels=&template=feature-request.md&title=%5BFeature%5D+Your+Feature+Request+Here) when you request a new feature.
We love thorough feature requests.
The more details you include, the faster we can implement your request.
Great feature requests include these details:
We love thorough feature requests. The more details you include, the faster we can implement your request. Great feature requests include these details:
1. Tell us whether this feature is related to a problem.
- If it is, describe the problem.
- If it is, describe the problem.
2. Describe your desired solution.
3. Describe alternative solutions you may use yourself or other solutions you may have considered.
4. Notes
- If possible, include how you think this solution would benefit others.
- Anything else you think might be useful to us.
- If possible, include how you think this solution would benefit others.
- Anything else you think might be useful to us.
## Submit a fix
One of the main benefits of making our project open source is that it makes it possible for the community to contribute directly.
We will always respond as quickly as we can to any issues you report, but if you know how to fix an issue, the fastest way to get it fixed is to submit a pull request and make the fix yourself!
If you can do this, it's tremendously helpful to us in our efforts to improve the community, and, if you're interested, you will receive ambassador points for your fix.
Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
One of the main benefits of making our project open source is that it makes it possible for the community to contribute directly. We will always respond as quickly as we can to any issues you report, but if you know how to fix an issue, the fastest way to get it fixed is to submit a pull request and make the fix yourself! If you can do this, it's tremendously helpful to us in our efforts to improve the community, and, if you're interested, you will receive ambassador points for your fix. Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
To submit a fix, follow these steps:
1. Fork the repository and copy the `main` branch.
2. Pull the latest code and ensure that it's running properly.
3. Create a new branch from main.
- Follow this naming convention for your branch: `fix/your-fix-name`
- Follow this naming convention for your branch: `fix/your-fix-name`
4. Create a pull request from your branch to our origin repository's `main` branch!
Once you create the pull request, the SailPoint Developer Relations Team will be tagged.
Someone will then review the pull request and merge it in!
Once you create the pull request, the SailPoint Developer Relations Team will be tagged. Someone will then review the pull request and merge it in!
:::note
@@ -106,21 +93,17 @@ You cannot directly make changes to the API specifications. These files are regu
## Submit a new feature
We will always respond to your feature requests and implement them as soon as we can.
However, if you have an idea for a new feature and know how to implement it yourself, the fastest way to add the feature is to submit a pull request and add the feature yourself!
If you can do this, we greatly appreciate it, and other community members will benefit from your contribution!
And if you're interested, you will receive ambassador points for your feature contribution.
Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
We will always respond to your feature requests and implement them as soon as we can. However, if you have an idea for a new feature and know how to implement it yourself, the fastest way to add the feature is to submit a pull request and add the feature yourself! If you can do this, we greatly appreciate it, and other community members will benefit from your contribution! And if you're interested, you will receive ambassador points for your feature contribution. Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
To submit a new feature, follow these steps:
1. Fork the repository and copy the `main` branch.
2. Pull the latest code and ensure that it's running properly.
3. Create a new branch from main.
- Follow this naming convention for your branch: `feature/your-feature-name`
- Follow this naming convention for your branch: `feature/your-feature-name`
4. Create a pull request from your branch to our origin repository's `main` branch!
Once you create the pull request, the SailPoint Developer Relations Team will be tagged.
Someone will then review the pull request and merge it in!
Once you create the pull request, the SailPoint Developer Relations Team will be tagged. Someone will then review the pull request and merge it in!
:::note
@@ -130,19 +113,12 @@ You cannot directly make changes to the API specifications. These files are regu
## Report general issues
It's possible that none of the options listed here will properly address your issue.
If you have a general issue, you can submit a general issue by using GitHub's [issues](https://github.com/sailpoint-oss/developer.sailpoint.com/issues).
Add as much detail as you can to your issue, and we will address it as quickly as we can.
It's possible that none of the options listed here will properly address your issue. If you have a general issue, you can submit a general issue by using GitHub's [issues](https://github.com/sailpoint-oss/developer.sailpoint.com/issues). Add as much detail as you can to your issue, and we will address it as quickly as we can.
## Discuss on the forum
What makes the SailPoint Developer Community great is its brilliant, knowledgeable members!
If you have a question, problem, or idea, one of the best ways to get answers or resolutions is to go to the [Developer Community Forum](https://developer.sailpoint.com/discuss) to discuss them directly with the community on the forum.
The SailPoint Developer Relations Team, the community ambassadors, and other members will be there to discuss them with you.
And once you're there, you can help others on the forum too!
If you're interested, you will receive ambassador points for the issues you help others resolve on the forum.Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
What makes the SailPoint Developer Community great is its brilliant, knowledgeable members! If you have a question, problem, or idea, one of the best ways to get answers or resolutions is to go to the [Developer Community Forum](https://developer.sailpoint.com/discuss) to discuss them directly with the community on the forum. The SailPoint Developer Relations Team, the community ambassadors, and other members will be there to discuss them with you. And once you're there, you can help others on the forum too! If you're interested, you will receive ambassador points for the issues you help others resolve on the forum.Check out the [ambassador program](https://developer.sailpoint.com/discuss/t/getting-started-as-a-developer-community-ambassador/11665) to learn more.
## MIT Software License
This project uses the [MIT License](http://choosealicense.com/licenses/mit/).
Whenever you submit code changes, your submissions are held under the same MIT license that covers the project.
This project uses the [MIT License](http://choosealicense.com/licenses/mit/). Whenever you submit code changes, your submissions are held under the same MIT license that covers the project.

View File

@@ -184,11 +184,7 @@
"hierarchy.lvl0",
"hierarchy.lvl1"
],
"searchableAttributes": [
"tags",
"hierarchy.lvl0",
"hierarchy.lvl1"
]
"searchableAttributes": ["tags", "hierarchy.lvl0", "hierarchy.lvl1"]
},
"conversation_id": ["1090805758"],
"nb_hits": 8687

View File

@@ -2,7 +2,6 @@ import md5 from 'crypto-js/md5';
export const URL = 'https://developerdays.sailpoint.com';
export async function getFAQ() {
try {
const response = await fetch(URL + '/faq');

View File

@@ -149,7 +149,8 @@
.stageButton:disabled {
background: #ffffff;
box-shadow: inset -5.0934px -5.0934px 15.2802px rgba(255, 255, 255, 0.5),
box-shadow:
inset -5.0934px -5.0934px 15.2802px rgba(255, 255, 255, 0.5),
inset 5.0934px 5.0934px 15.2802px rgba(136, 160, 183, 0.25);
border-radius: 20.3736px;
}

View File

@@ -11,7 +11,7 @@ export default function ConferenceHero() {
<div className={styles.center}>
<div className={styles.mainCard}>
<div>
<div className={styles.conferenceText}>Developer Days</div>
<div className={styles.conferenceText}>Developer Days</div>
<div className={styles.comingSoonText}>March 7th-9th, 2023</div>
<div className={styles.descriptionText}>
The conference for developers on SailPoint platforms.

View File

@@ -15,25 +15,25 @@
}
.conferenceText {
margin-top: 70px;
font-size: 55px;
color: var(--dev-text-color-cobalt);
font-family: input-mono;
margin-top: 70px;
font-size: 55px;
color: var(--dev-text-color-cobalt);
font-family: input-mono;
}
.comingSoonText {
color: var(--dev-text-color-cobalt);
font-size: 20px;
font-family: input-mono;
letter-spacing: 5.5px;
margin-top: -17px;
color: var(--dev-text-color-cobalt);
font-size: 20px;
font-family: input-mono;
letter-spacing: 5.5px;
margin-top: -17px;
}
.descriptionText {
margin-top: 27px;
color: var(--ifm-color-primary);
font-size: 36px;
font-family: input-mono;
margin-top: 27px;
color: var(--ifm-color-primary);
font-size: 36px;
font-family: input-mono;
}
.extensible {

View File

@@ -23,8 +23,16 @@ export default function ConferenceTheme() {
</div>
<div className={styles.center}>
<div className={styles.gridContainer}>
<ThemeCard title={"Developer Days is a hands-on conference, you will build something in almost every session"} image={"/conf/workshops.png"}></ThemeCard>
<ThemeCard title={"Developer Days will be all-virtual, open to everyone, and <b>at no cost<b>"} image={"/conf/virtual.png"}></ThemeCard>
<ThemeCard
title={
'Developer Days is a hands-on conference, you will build something in almost every session'
}
image={'/conf/workshops.png'}></ThemeCard>
<ThemeCard
title={
'Developer Days will be all-virtual, open to everyone, and <b>at no cost<b>'
}
image={'/conf/virtual.png'}></ThemeCard>
</div>
</div>
</div>

View File

@@ -1,13 +1,12 @@
.gridContainer {
display: grid;
place-content: center;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 40px;
margin-left: 20px;
margin-right: 40px;
text-align: center;
}
display: grid;
place-content: center;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-gap: 40px;
margin-left: 20px;
margin-right: 40px;
text-align: center;
}
.center {
margin: 20px auto;

View File

@@ -148,7 +148,8 @@
.stageButton:disabled {
background: #ffffff;
box-shadow: inset -5.0934px -5.0934px 15.2802px rgba(255, 255, 255, 0.5),
box-shadow:
inset -5.0934px -5.0934px 15.2802px rgba(255, 255, 255, 0.5),
inset 5.0934px 5.0934px 15.2802px rgba(136, 160, 183, 0.25);
border-radius: 20.3736px;
}

View File

@@ -1,10 +1,7 @@
import React from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
import React from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
import Link from '@docusaurus/Link';
export default function Video() {
return (
<div>
</div>
);
return <div></div>;
}

View File

@@ -1,30 +1,29 @@
{
"name": "delete-test-01",
"description": "delete-test-01-description",
"version": "0.0.1",
"private": true,
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.188.0",
"@aws-sdk/lib-dynamodb": "^3.188.0"
},
"devDependencies": {
"aws-sdk-client-mock": "^2.0.0",
"jest": "^29.2.1"
},
"scripts": {
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js"
},
"jest": {
"testMatch": [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)",
"**/__tests__/**/*.mjs?(x)",
"**/?(*.)+(spec|test).mjs?(x)"
],
"moduleFileExtensions": [
"mjs",
"js"
]
}
"name": "delete-test-01",
"description": "delete-test-01-description",
"version": "0.0.1",
"private": true,
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.188.0",
"@aws-sdk/lib-dynamodb": "^3.188.0"
},
"devDependencies": {
"aws-sdk-client-mock": "^2.0.0",
"jest": "^29.2.1"
},
"scripts": {
"test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js"
},
"jest": {
"testMatch": [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[jt]s?(x)",
"**/__tests__/**/*.mjs?(x)",
"**/?(*.)+(spec|test).mjs?(x)"
],
"moduleFileExtensions": [
"mjs",
"js"
]
}
}

View File

@@ -1,46 +1,47 @@
exports.authHandler = async (event) => {
const token = event.headers.authorization;
const token = event.headers.authorization;
const expectedUsername = process.env.AUTH_USERNAME;
const expectedPassword = process.env.AUTH_PASSWORD;
const expectedUsername = process.env.AUTH_USERNAME;
const expectedPassword = process.env.AUTH_PASSWORD;
try {
const { username, password } = decodeAuthToken(token);
if (username === expectedUsername && password === expectedPassword) {
return generatePolicy('user', 'Allow', event.routeArn);
} else {
throw new Error('Unauthorized');
}
} catch (err) {
console.log(err.message);
return generatePolicy('user', 'Deny', event.routeArn);
try {
const {username, password} = decodeAuthToken(token);
if (username === expectedUsername && password === expectedPassword) {
return generatePolicy('user', 'Allow', event.routeArn);
} else {
throw new Error('Unauthorized');
}
} catch (err) {
console.log(err.message);
return generatePolicy('user', 'Deny', event.routeArn);
}
};
function decodeAuthToken(token) {
if (!token || !token.startsWith('Basic ')) {
throw new Error('Missing or invalid Authorization header');
}
if (!token || !token.startsWith('Basic ')) {
throw new Error('Missing or invalid Authorization header');
}
const base64Credentials = token.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = credentials.split(':');
return { username, password };
const base64Credentials = token.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString(
'ascii',
);
const [username, password] = credentials.split(':');
return {username, password};
}
function generatePolicy(principalId, effect, resource) {
return {
principalId,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: resource
}
]
}
};
return {
principalId,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: resource,
},
],
},
};
}

View File

@@ -15,7 +15,7 @@ tags: ['API Specifications']
The Identity Security Cloud (ISC) APIs provide developers with a way to interact with the ISC platform and extend it. Developers can leverage these APIs to customize their platform experiences and build new solutions and integrations that meet their needs.
The API specifications contain detailed information of how to send requests to each API endpoint, as well as example requests and responses. They also include essential information about how to use the APIs and guides you can follow to get started.
The API specifications contain detailed information of how to send requests to each API endpoint, as well as example requests and responses. They also include essential information about how to use the APIs and guides you can follow to get started.
```mdx-code-block
import DocCardList from '@theme/DocCardList';

View File

@@ -15,18 +15,11 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
## Overview
With SailPoint's Identity Security Cloud (ISC) APIs, you can extend your ISC platform far beyond its current capabilities.
With SailPoint's Identity Security Cloud (ISC) APIs, you can extend your ISC platform far beyond its current capabilities. To be able to do so, you must first authenticate to the ISC APIs. Authentication is the act of validating a user's identity, generally by passing some kind of credentials. A fast, simple way to authenticate to the APIs is to generate a [personal access token](#generate-a-personal-access-token) and pass that token.
To be able to do so, you must first authenticate to the ISC APIs.
Authentication is the act of validating a user's identity, generally by passing some kind of credentials.
A fast, simple way to authenticate to the APIs is to generate a [personal access token](#generate-a-personal-access-token) and pass that token.
If the PAT is valid, the API responds with a JSON Web Token (JWT) `access_token` that you can provide to authorize your API requests. Authorization is the act of validating the user's permission to access a given resource. A successful API request must include the `access_token` in the `Authorization` request header.
If the PAT is valid, the API responds with a JSON Web Token (JWT) `access_token` that you can provide to authorize your API requests.
Authorization is the act of validating the user's permission to access a given resource.
A successful API request must include the `access_token` in the `Authorization` request header.
This JWT `access_token` grants access matching that of the user who generated the PAT.
For example, if the user who generated the PAT is an admin, the returned JWT `access_token` would grant admin access to the APIs.
This JWT `access_token` grants access matching that of the user who generated the PAT. For example, if the user who generated the PAT is an admin, the returned JWT `access_token` would grant admin access to the APIs.
This diagram shows the flow of this authentication/authorization process:
@@ -50,11 +43,11 @@ sequenceDiagram
</div>
The flow involves these four key steps:
1. **Access Token Request**: The HTTP client (a script, application, Postman, cURL, etc.) makes a request to ISC to get a JWT `access_token`.
2. **Access Token Response**: If the request is valid, ISC responds to the HTTP client with a JWT `access_token`.
3. **API Request**: The HTTP client makes a request to an ISC endpoint with the header, `Authorization: Bearer {access_token}`.
4. **API Response**: If both the request itself and the JWT `access_token` in its header are valid, ISC responds to the client.
If you encounter unexpected errors, refer to the [Troubleshooting](#troubleshooting) section of this document.
4. **API Response**: If both the request itself and the JWT `access_token` in its header are valid, ISC responds to the client. If you encounter unexpected errors, refer to the [Troubleshooting](#troubleshooting) section of this document.
The idea is that once you have authenticated to the ISC APIs and you have received an `access_token`, you can use that `access_token` to provide authorization for your API requests.
@@ -64,8 +57,8 @@ This document includes all the information you need to know to engage in this au
Read this guide to learn how to authenticate to SailPoint's ISC APIs.
To authenticate to the ISC APIs, you must be able to connect to your tenant to send the access token request.
To do so, you need to do the following:
To authenticate to the ISC APIs, you must be able to connect to your tenant to send the access token request. To do so, you need to do the following:
1. [Find your tenant's OAuth details](#find-your-tenant's-oauth-details)
2. [Generate personal access token](#generate-personal-access-token)
3. [Choose authorization grant flow](#choose-authorization-grant-flow)
@@ -73,15 +66,13 @@ To do so, you need to do the following:
### Find your tenant's OAuth details
Your tenant's OAuth details refer to the details you need to know to connect it to the APIs.
You need to know your tenant's name, its `authorizeEndpoint` URL, and its `tokenEndpoint` URL.
Your tenant's OAuth details refer to the details you need to know to connect it to the APIs. You need to know your tenant's name, its `authorizeEndpoint` URL, and its `tokenEndpoint` URL.
Your ISC instance is likely using the domain name supplied by SailPoint (`{tenant}.api.identitynow.com`), in which case, the tenant name is in the URL.
This is assumed to be the case in this guide.
However, if your ISC instance is using a vanity URL, you must enter this URL into your browser to get your OAuth info:
`https://{tenant}.api.identitynow.com/oauth/info`
Your ISC instance is likely using the domain name supplied by SailPoint (`{tenant}.api.identitynow.com`), in which case, the tenant name is in the URL. This is assumed to be the case in this guide.
However, if your ISC instance is using a vanity URL, you must enter this URL into your browser to get your OAuth info: `https://{tenant}.api.identitynow.com/oauth/info`
If you have admin access but don't know your tenant name, you can learn it by following these steps:
1. Log into your ISC instance.
2. Select the 'Dashboard' dropdown.
3. Select 'Overview'.
@@ -105,21 +96,17 @@ You can use the `authorizeEndpoint` and `tokenEndpoint` URLs from this example t
### Generate a personal access token
A personal access token (PAT) is a method of authenticating to an API as a user without providing a username and password.
PATs are primarily used in scripts or programs that lack an easy way to implement an OAuth2 flow but need to call API endpoints that require user context.
PATs are also convenient for use in tools like [Postman](https://www.postman.com/) when you are exploring and testing the APIs.
A personal access token (PAT) is a method of authenticating to an API as a user without providing a username and password. PATs are primarily used in scripts or programs that lack an easy way to implement an OAuth2 flow but need to call API endpoints that require user context. PATs are also convenient for use in tools like [Postman](https://www.postman.com/) when you are exploring and testing the APIs.
Any ISC user can generate a PAT.
To do so, follow these steps:
1. Select **Preferences** from the drop-down menu under your username, then **Personal Access Tokens** on the left.
You can also go directly to the page by using this URL (replace `{tenant}` with your Identity Security Cloud tenant): `https://{tenant}.identitynow.com/ui/d/user-preferences/personal-access-tokens`
Any ISC user can generate a PAT. To do so, follow these steps:
1. Select **Preferences** from the drop-down menu under your username, then **Personal Access Tokens** on the left. You can also go directly to the page by using this URL (replace `{tenant}` with your Identity Security Cloud tenant): `https://{tenant}.identitynow.com/ui/d/user-preferences/personal-access-tokens`
2. Click **New Token** and enter a meaningful description to help differentiate the token from others.
:::caution
The **New Token** button will be disabled when you reach the limit of 10 personal access tokens per user.
To avoid reaching this limit, it is recommended that you delete any tokens that are no longer necessary.
The **New Token** button will be disabled when you reach the limit of 10 personal access tokens per user. To avoid reaching this limit, it is recommended that you delete any tokens that are no longer necessary.
:::
@@ -135,21 +122,17 @@ After you create the token, the value of the `Client ID` will be visible in the
To generate a personal access token from the API, use the [create personal access token endpoint](/docs/api/beta/create-personal-access-token).
Once you have created the PAT and you know its `Client ID` and `Client Secret`, you have everything you need to follow the [Client Credentials Grant Flow](#request-access-token-with-client-credentials-grant-flow) and use the PAT to generate an `access_token`.
You will need this `access_token` to authenticate your requests to the APIs.
Once you have created the PAT and you know its `Client ID` and `Client Secret`, you have everything you need to follow the [Client Credentials Grant Flow](#request-access-token-with-client-credentials-grant-flow) and use the PAT to generate an `access_token`. You will need this `access_token` to authenticate your requests to the APIs.
### Choose authorization grant flow
There are several different authorization flows that OAuth 2.0 supports, and each has a grant-type defining its different use cases.
You must choose the one that best serves your purposes.
This document covers these three common flows:
There are several different authorization flows that OAuth 2.0 supports, and each has a grant-type defining its different use cases. You must choose the one that best serves your purposes. This document covers these three common flows:
1. [**Client Credentials**](https://oauth.net/2/grant-types/client-credentials/) - Clients use this grant type to obtain a JWT `access_token` without user involvement such as scripts, programs or system to system integration.
2. [**Authorization Code**](https://oauth.net/2/grant-types/authorization-code/) - Clients use this grant type to exchange an authorization code for an `access_token`. Authorization codes are mainly used by web applications because there is a login into ISC with a subsequent redirect back to the web application/client.
3. [**Refresh Token**](https://oauth.net/2/grant-types/refresh-token/) - Clients use this grant type to exchange a refresh token for a new `access_token` when the existing `access_token` has expired. This allows clients to continue using the APIs without having to re-authenticate as frequently. This grant type is commonly used together with `Authorization Code` to prevent a user from having to log in several times per day.
One way to determine which authorization flow you need to use is to look at the specification for the endpoint you want to use.
The endpoint will have the supported OAuth flows listed under the 'Authorization' dropdown, like the [List Access Profiles endpoint](https://developer.sailpoint.com/docs/api/beta/list-access-profiles):
One way to determine which authorization flow you need to use is to look at the specification for the endpoint you want to use. The endpoint will have the supported OAuth flows listed under the 'Authorization' dropdown, like the [List Access Profiles endpoint](https://developer.sailpoint.com/docs/api/beta/list-access-profiles):
![Authorization Dropdown](./img/authorization/authorization-dropdown.png)
@@ -221,9 +204,7 @@ curl --location 'https://{tenant}.api.identitynow.com/oauth/token' \
--form 'client_secret="{clientSecret}"'
```
2. ISC validates the token request and responds.
If the request is successful, the response contains a JWT access token.
For more information about the JWT access token in the response, refer to [#OAuth-token-response](#oauth-token-response).
2. ISC validates the token request and responds. If the request is successful, the response contains a JWT access token. For more information about the JWT access token in the response, refer to [#OAuth-token-response](#oauth-token-response).
Once you have the JWT access token, you can pass the token as a basic "Authorization" header in your requests using the OAuth endpoints.
@@ -233,11 +214,9 @@ To learn more about the OAuth client credentials grant flow, refer [here](https:
Further Reading: [https://oauth.net/2/grant-types/authorization-code/](https://oauth.net/2/grant-types/authorization-code/)
Clients use this grant type to exchange an authorization code for an `access_token`.
This is mainly used for web apps because there is a login into ISC with a subsequent redirect back to the web app/client.
Clients use this grant type to exchange an authorization code for an `access_token`. This is mainly used for web apps because there is a login into ISC with a subsequent redirect back to the web app/client.
The OAuth 2.0 client you are using must have `AUTHORIZATION_CODE` as one of its grant types.
The redirect URLs must also match the list in the client as well:
The OAuth 2.0 client you are using must have `AUTHORIZATION_CODE` as one of its grant types. The redirect URLs must also match the list in the client as well:
```json
{
@@ -310,8 +289,7 @@ The token endpoint URL is `{tenant}.api.identitynow.com`, and the authorize URL
:::
7. ISC validates the token request and submits a response. If the request is successful, the response contains a JWT `access_token`.
For more information about the JWT access token in the response, refer to [#OAuth-token-response](#oauth-token-response).
7. ISC validates the token request and submits a response. If the request is successful, the response contains a JWT `access_token`. For more information about the JWT access token in the response, refer to [#OAuth-token-response](#oauth-token-response).
These are the query parameters in the OAuth 2.0 token request for the authorization code grant:
@@ -415,9 +393,7 @@ A successful request using any of the grant flows to `https://{tenant}.api.ident
}
```
You can use the JWT `access_token` to authorize REST API calls through the ISC API gateway.
To use the `access_token`, simply include it in the `Authorization` header as a `Bearer` token.
This is an example V3 API request that has the access token in the header:
You can use the JWT `access_token` to authorize REST API calls through the ISC API gateway. To use the `access_token`, simply include it in the `Authorization` header as a `Bearer` token. This is an example V3 API request that has the access token in the header:
```bash
curl -X GET \
@@ -427,16 +403,12 @@ curl -X GET \
```
Some of the other values can also be useful to know:
- The `expires_in` value describes the lifetime, in seconds, of the `access_token`.
For example, the value 749 means that the `access_token` will expire 12.5 minutes from the time the response was generated.
The exact expiration date is also contained within the `access_token`.
You can view this expiration time by decoding the JWT `access_token` using a tool like [jwt.io](https://jwt.io/).
- The `refresh token` exists for use in the refresh token grant flow to replace the `access_token` when it expires.
However, the `refresh_token` will only be present if the API client has the `REFRESH_TOKEN` grant flow.
- The `expires_in` value describes the lifetime, in seconds, of the `access_token`. For example, the value 749 means that the `access_token` will expire 12.5 minutes from the time the response was generated. The exact expiration date is also contained within the `access_token`. You can view this expiration time by decoding the JWT `access_token` using a tool like [jwt.io](https://jwt.io/).
- The `user_id` and `identity_id` define the identity context of the person who authenticated.
However, these values aren't set for the client credentials grant type because it doesn't have a user context.
- The `refresh token` exists for use in the refresh token grant flow to replace the `access_token` when it expires. However, the `refresh_token` will only be present if the API client has the `REFRESH_TOKEN` grant flow.
- The `user_id` and `identity_id` define the identity context of the person who authenticated. However, these values aren't set for the client credentials grant type because it doesn't have a user context.
With the JWT `access_token`, you can now successfully send authenticated ISC API requests. To learn more about authorization and the scopes you can apply to further control access to the APIs, refer to [Authorization](/docs/api/authorization).
@@ -445,15 +417,12 @@ With the JWT `access_token`, you can now successfully send authenticated ISC API
This section of the document includes additional information about the authentication/authorization process, including some different use cases for the different authorization grant flows.
### OAuth 2.0
The SailPoint authentication/authorization model is fully [OAuth 2.0](https://oauth.net/2/) compliant.
[OAuth 2.0](https://oauth.net/2/) is an industry-standard protocol for authorization.
It provides a variety of authorization flows for web applications, desktop applications, mobile phones, and devices.
This specification and its extensions are developed within the [IETF OAuth Working Group](https://www.ietf.org/mailman/listinfo/oauth).
The SailPoint authentication/authorization model is fully [OAuth 2.0](https://oauth.net/2/) compliant. [OAuth 2.0](https://oauth.net/2/) is an industry-standard protocol for authorization. It provides a variety of authorization flows for web applications, desktop applications, mobile phones, and devices. This specification and its extensions are developed within the [IETF OAuth Working Group](https://www.ietf.org/mailman/listinfo/oauth).
### JSON Web Token
The issued JWT `access_token` leverages the [JSON Web Token (JWT)](https://jwt.io/) standard.
JWT is an industry-standard protocol for creating access tokens which assert various claims about the resource who has authenticated.
The tokens have a specific structure consisting of a header, payload, and signature.
The issued JWT `access_token` leverages the [JSON Web Token (JWT)](https://jwt.io/) standard. JWT is an industry-standard protocol for creating access tokens which assert various claims about the resource who has authenticated. The tokens have a specific structure consisting of a header, payload, and signature.
A raw JWT might look like this:
@@ -520,30 +489,30 @@ This section describes some different use cases and which grant flow you would w
For daily work or short, quick administrative actions, you can just use a PAT. This makes the process easier because you don't really need to worry about grant types - you can easily generate a PAT in the user interface (UI).
Follow these steps to do so:
1. Log in to ISC.
2. Go to 'Preferences', then 'Personal Access Tokens', and [generate a PAT](#generate-a-personal-access-token).
3. The PAT's `client_id` and `client_secret` provide the necessary authentication to send API requests, without any grant flow.
#### Postman
[Postman](https://www.postman.com/) is a popular HTTP client you can use to design, build, test, and iterate your APIs. Postman users and teams can create public workspaces they can use to make it easy to access their API collections and environments and get started. SailPoint maintains a [public workspace for the Identity Security Cloud API collections](https://www.postman.com/sailpoint/workspace/identitynow). You can use this workspace to access all the ISC API collections and stay up to date.
If you're using Postman, you have some different ways to set up your authorization.
You can just leverage the accessToken as mentioned above, or you can configure Postman to use OAuth 2.0 directly.
For more information about how to do so, refer [here](https://learning.postman.com/docs/sending-requests/authorization/).
If you're using Postman, you have some different ways to set up your authorization. You can just leverage the accessToken as mentioned above, or you can configure Postman to use OAuth 2.0 directly. For more information about how to do so, refer [here](https://learning.postman.com/docs/sending-requests/authorization/).
#### Web applications
If you are making a web application, the best grant flow to use is the [Authorization Code grant flow](#request-access-token-with-authorization-grant-flow). This will allow users to be directed to ISC to login and then redirected back to the web application through a URL redirect. This also works well with Single Sign-on (SSO), strong authentication, and pass-through authentication mechanisms.
SailPoint doesn't recommend using a password grant flow for web applications because doing so would involve entering ISC credentials in the web application.
This flow also doesn't allow you to work with SSO, strong authentication, or pass-through authentication.
SailPoint doesn't recommend using a password grant flow for web applications because doing so would involve entering ISC credentials in the web application. This flow also doesn't allow you to work with SSO, strong authentication, or pass-through authentication.
#### Scripts, programs or system to system integration
If you are writing scripts, programs or system integrations that leverage the ISC APIs, the OAuth 2.0 grant you should use typically depends on what you're doing and the user context you need to operate under.
Because scripts, code, and programs lack an interactive web-interface, it is difficult, but not impossible, to implement a working authorization code grant flow. System to system integrations may require an elevated level of access and utilize a service account to make API calls beyond the privileges of the authenticated user.
Most scripts, programs, and many integrations use the [Client Credentials grant flow](#request-access-token-with-client-credentials-grant-flow).
Using a PAT allows your API calls to work within a user context making client credentials ideal.
Most scripts, programs, and many integrations use the [Client Credentials grant flow](#request-access-token-with-client-credentials-grant-flow). Using a PAT allows your API calls to work within a user context making client credentials ideal.
## Troubleshooting
@@ -572,8 +541,7 @@ You can also get a **403 Forbidden** response error when you call an API that ex
### Verify OAuth client
1. Verify that the OAuth 2.0 client is not a legacy OAuth client. Legacy OAuth clients will not work. This can become very apparent when you look at the client ID - OAuth 2.0 client IDs have dashes.
Here are two examples that illustrate the difference:
1. Verify that the OAuth 2.0 client is not a legacy OAuth client. Legacy OAuth clients will not work. This can become very apparent when you look at the client ID - OAuth 2.0 client IDs have dashes. Here are two examples that illustrate the difference:
Legacy Client ID: `G6xLlBBOKIcOAQuK`
@@ -611,10 +579,8 @@ You can also view all of the active clients in the UI by going to `https://{tena
}
```
4. If you're using an [Authorization Code](#authorization-code-grant-flow) grant flow, verify that the redirect URL(s) for your application match the `redirectUris` value in the client.
You can check this by calling the [List OAuth Clients endpoint](/docs/api/beta/list-oauth-clients).
4. If you're using an [Authorization Code](#authorization-code-grant-flow) grant flow, verify that the redirect URL(s) for your application match the `redirectUris` value in the client. You can check this by calling the [List OAuth Clients endpoint](/docs/api/beta/list-oauth-clients).
### Verify OAuth calls
Verify that the OAuth call flow is going to the right URLs, with the correct query parameters and data values.
A common source of errors is using the wrong host for authorization and token API calls.
The token endpoint URL is `{tenant}.api.identitynow.com`, while the authorize URL is `{tenant}.identitynow.com`.
Verify that the OAuth call flow is going to the right URLs, with the correct query parameters and data values. A common source of errors is using the wrong host for authorization and token API calls. The token endpoint URL is `{tenant}.api.identitynow.com`, while the authorize URL is `{tenant}.identitynow.com`.

View File

@@ -5,10 +5,10 @@ pagination_label: Authorization
sidebar_label: Authorization
sidebar_position: 3
sidebar_class_name: authorization
keywords: ['authorization','scope','permission']
keywords: ['authorization', 'scope', 'permission']
description: Authorize your ISC API requests.
slug: /api/authorization
tags: ['Authorization','Scopes','Permissions']
tags: ['Authorization', 'Scopes', 'Permissions']
---
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
@@ -41,7 +41,7 @@ sequenceDiagram
## User Level Permissions
When managing a user's access to the API, you must first assign the target user an appropriate [user level](https://documentation.sailpoint.com/saas/help/common/users/user_level_matrix.html). It is important to choose the correct user level as it will place a boundary on which APIs a user can call, which also affects the areas and functions of the UI they have access to. For example, if a user is in charge of creating reports for auditing requirements, consider granting them the "Report Admin" user level.
When managing a user's access to the API, you must first assign the target user an appropriate [user level](https://documentation.sailpoint.com/saas/help/common/users/user_level_matrix.html). It is important to choose the correct user level as it will place a boundary on which APIs a user can call, which also affects the areas and functions of the UI they have access to. For example, if a user is in charge of creating reports for auditing requirements, consider granting them the "Report Admin" user level.
User levels are typically granted through the UI, [following the procedures from this document](https://documentation.sailpoint.com/saas/help/common/users/grant_remove_user_levels.html).
@@ -51,26 +51,26 @@ There is an [API that can set an identity's user level](https://developer.sailpo
:::
User levels act as the first line of defense by applying a rigid boundary around the APIs that a user can call. The next section introduces scopes, which allow users to apply granular controls on the APIs an access token can call.
User levels act as the first line of defense by applying a rigid boundary around the APIs that a user can call. The next section introduces scopes, which allow users to apply granular controls on the APIs an access token can call.
## Scopes
Scopes are granular permissions you can add to personal access tokens (PATs) to create tokens with the least privilege necessary to fulfill their functions. User levels place a broad border around the APIs a token has access to, while scopes can further limit the set of endpoints a token can call. Scopes allow an API user to have multiple tokens with different privileges that support unique use cases and software applications. Using scopes is beneficial to security - if a bad actor compromises any one of the tokens, the bad actor can only perform the limited set of operations defined by the token's scopes, significantly reducing the potential damage that can be done. Therefore, it is recommended that all users apply scopes to each PAT they create in order to reduce the impact of stolen credentials.
Scopes are granular permissions you can add to personal access tokens (PATs) to create tokens with the least privilege necessary to fulfill their functions. User levels place a broad border around the APIs a token has access to, while scopes can further limit the set of endpoints a token can call. Scopes allow an API user to have multiple tokens with different privileges that support unique use cases and software applications. Using scopes is beneficial to security - if a bad actor compromises any one of the tokens, the bad actor can only perform the limited set of operations defined by the token's scopes, significantly reducing the potential damage that can be done. Therefore, it is recommended that all users apply scopes to each PAT they create in order to reduce the impact of stolen credentials.
Scopes contain one or more rights, which are low level permissions that grant access to individual endpoints. This means that a single scope, like `idn:access-request:manage`, can grant access to multiple API endpoints. To determine which scopes a PAT needs, you must first identify which endpoints the PAT needs to invoke. Each endpoint's API specification indicates which scope is necessary to call the endpoint. You can use this approach to curate a list of scopes that must be applied to the credential to call the necessary endpoints. [Learn more about how to find an API's required scopes here](#identifying-necessary-authorization-for-an-endpoint).
Scopes contain one or more rights, which are low level permissions that grant access to individual endpoints. This means that a single scope, like `idn:access-request:manage`, can grant access to multiple API endpoints. To determine which scopes a PAT needs, you must first identify which endpoints the PAT needs to invoke. Each endpoint's API specification indicates which scope is necessary to call the endpoint. You can use this approach to curate a list of scopes that must be applied to the credential to call the necessary endpoints. [Learn more about how to find an API's required scopes here](#identifying-necessary-authorization-for-an-endpoint).
By default, each PAT has the scope `sp:scopes:default`, which is the least privileged scope. It only grants access to endpoints that require no authorization at all, such as [List Public Identities](https://developer.sailpoint.com/idn/api/v3/get-public-identities). Access to the endpoint may still be determined by the user's [user level](https://documentation.sailpoint.com/saas/help/common/users/user_level_matrix.html).
Alternatively, `sp:scopes:all` grants access to all the rights appropriate for the [user level](https://documentation.sailpoint.com/saas/help/common/users/user_level_matrix.html). For example, a user with the **Admin** user level has access to all APIs, so `sp:scopes:all` grants **Admin** users access to all APIs. A user with the **Cert Admin** user level, however, has access to only a subset of APIs necessary to perform their role, most notably the certification APIs, so `sp:scopes:all` grants **Cert Admin** users access to only that subset of APIs.
Scopes are additive, which means the final right set is the intersection of all the rights granted by the scopes assigned to a PAT, excluding any rights that fall outside of the user level. Each scope added to an PAT builds up the credential's permission set, incrementally increasing access to the API. If a PAT has `sp:scopes:all` granted, then any additional scope is ignored because `sp:scopes:all` already contains the complete set of rights available to the user level.
Scopes are additive, which means the final right set is the intersection of all the rights granted by the scopes assigned to a PAT, excluding any rights that fall outside of the user level. Each scope added to an PAT builds up the credential's permission set, incrementally increasing access to the API. If a PAT has `sp:scopes:all` granted, then any additional scope is ignored because `sp:scopes:all` already contains the complete set of rights available to the user level.
:::tip
If the API requirements for the personal access token exceed the scopes allowed by the user's assigned user level, then the following options may be considered.
- Re-evaluate the user's responsibilities compared to their user level. It is possible that their user level is no longer appropriate for the functions they need to perform, and a more permissive user level may be necessary.
- If the required access is a one-off need for a specific use case, then consider generating a PAT with the required scopes from a different user and sharing the credentials. This could be a dedicated service account designated for one-off applications. The downside of this approach is that it becomes more difficult to attribute an API call to a specific user, as the user now has a PAT that is not tied to their user account.
- Re-evaluate the user's responsibilities compared to their user level. It is possible that their user level is no longer appropriate for the functions they need to perform, and a more permissive user level may be necessary.
- If the required access is a one-off need for a specific use case, then consider generating a PAT with the required scopes from a different user and sharing the credentials. This could be a dedicated service account designated for one-off applications. The downside of this approach is that it becomes more difficult to attribute an API call to a specific user, as the user now has a PAT that is not tied to their user account.
:::
@@ -84,7 +84,7 @@ Each endpoint document specifies how to authorize with the endpoint in the **Aut
- **flow**: One or more OAuth flows supported by the endpoint. A token only needs to be generated by one flow to be valid. Refer to [Authentication Details](./authentication.md#authentication-details) for more information about the available flows.
- **scopes**: A list of scopes necessary to access the endpoint. A token only needs one of the scopes to authorize with the endpoint. When possible, choose the least privileged scope. Scopes ending in `read` can only retrieve data. Scopes ending in `manage` can retrieve, modify, and delete data.
You may also notice that many API descriptions will indicate the user level(s) required to call the API endpoint. In the screenshot above, the list access profiles endpoint requires the user to have one of the following user levels: ORG_ADMIN, ROLE_ADMIN, ROLE_SUBADMIN, SOURCE_ADMIN, or SOURCE_SUBADMIN. This means the PAT must have one of those user level **in addition to** the `sp:scopes:all` or `idn:access-profile:read` scope in order to call the endpoint.
You may also notice that many API descriptions will indicate the user level(s) required to call the API endpoint. In the screenshot above, the list access profiles endpoint requires the user to have one of the following user levels: ORG_ADMIN, ROLE_ADMIN, ROLE_SUBADMIN, SOURCE_ADMIN, or SOURCE_SUBADMIN. This means the PAT must have one of those user level **in addition to** the `sp:scopes:all` or `idn:access-profile:read` scope in order to call the endpoint.
:::info
@@ -106,11 +106,8 @@ Request Body
```json
{
"name": "Access Request and NELM Management",
"scope": [
"idn:access-request:manage",
"idn:nelm:manage"
]
"name": "Access Request and NELM Management",
"scope": ["idn:access-request:manage", "idn:nelm:manage"]
}
```
@@ -118,24 +115,21 @@ This request produces the following response, indicating that the scopes were su
```json
{
"id": "86286c0c456e4b03a8ccb1f892dd456d",
"name": "Access Request and NELM Management",
"secret": "********",
"scope": [
"idn:access-request:manage",
"idn:nelm:manage"
],
"created": "2023-01-04T18:58:17.486584Z",
"owner": {
"name": "jane.doe",
"id": "2c9180ab7624cbd7017642d8c8c81a73",
"type": "IDENTITY"
}
"id": "86286c0c456e4b03a8ccb1f892dd456d",
"name": "Access Request and NELM Management",
"secret": "********",
"scope": ["idn:access-request:manage", "idn:nelm:manage"],
"created": "2023-01-04T18:58:17.486584Z",
"owner": {
"name": "jane.doe",
"id": "2c9180ab7624cbd7017642d8c8c81a73",
"type": "IDENTITY"
}
}
```
:::caution
If you attempt to add a scope that is outside the permissions of the [target user's level](#user-level-permissions), the request will still succeed and include the invalid scope in the credentials. However, any token generated with these credentials will **not** include the rights of the invalid scope. This is not an issue when you apply scopes with the UI - the UI only shows scopes available to the current user.
If you attempt to add a scope that is outside the permissions of the [target user's level](#user-level-permissions), the request will still succeed and include the invalid scope in the credentials. However, any token generated with these credentials will **not** include the rights of the invalid scope. This is not an issue when you apply scopes with the UI - the UI only shows scopes available to the current user.
:::

View File

@@ -13,7 +13,7 @@ tags: ['Getting Started']
## Overview
This guide is intended to help you quickly make your first API call to SailPoint Identity Security Cloud and assumes an intermediate level of understanding of APIs. For beginners to APIs, we recommend you watch this presentation that covers the fundamentals of APIs with visual demonstrations of how to make an API call in SailPoint.
This guide is intended to help you quickly make your first API call to SailPoint Identity Security Cloud and assumes an intermediate level of understanding of APIs. For beginners to APIs, we recommend you watch this presentation that covers the fundamentals of APIs with visual demonstrations of how to make an API call in SailPoint.
<div class="text--center">
<iframe width="560" height="315" src="https://www.youtube.com/embed/YFRz8AcdWXg?si=9AvO6gMT1oCqYXAj" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

View File

@@ -11,8 +11,6 @@ slug: /api/nerm/authentication
tags: ['Authentication']
---
## Overview
NERM uses bearer tokens to allow customers to authenticate to NERM API endpoints. These tokens can be generated by following the instructions [here](https://documentation.sailpoint.com/ne-admin/help/setup/api.html).
@@ -20,5 +18,3 @@ NERM uses bearer tokens to allow customers to authenticate to NERM API endpoints
## Example
To use your bearer token simply provide it in the header with the request like so: `Authorization: Bearer <token>`

View File

@@ -25,7 +25,7 @@ Use the following optional query parameters to achieve pagination:
| --- | --- | --- | --- |
| `limit` | Integer specifying the maximum number of records to return in a single API call. If it is not specified, a default limit is used. | `100` | Maxiumum of 500 for `api/profiles` |
| `offset` | Integer specifying the offset of the first result from the beginning of the collection. The **offset** value is record-based, not page-based, and the index starts at 0. For example, **offset=0** and **limit=20** returns records 0-19, but **offset=1** and **limit=20** returns records 1-20. | `0` | Between 0 and the last record index. |
| `order` | String specifying the ascending order in which the results should be returned, for example, **order=login** would return the users results in an ascending alphanumeric order| - | Limited to specific parameters |
| `order` | String specifying the ascending order in which the results should be returned, for example, **order=login** would return the users results in an ascending alphanumeric order | - | Limited to specific parameters |
Examples:
@@ -39,11 +39,12 @@ Metadata can be added to a result to allow for progromatic approaches to fetchin
| Name | Description | Default |
| --- | --- | --- |
| `metadata` | Boolean that specifies wether or not to return a **_metadata** key with pagination information | false |
| `metadata` | Boolean that specifies wether or not to return a **\_metadata** key with pagination information | false |
Example:
- GET `/api/users?metadata=true`
```
{
...
@@ -61,6 +62,7 @@ Example:
Resource attributes can be added to parameters to perform a basic match filter. Refer to each documented endpoints **Query Parameters** to identify what can be used.
Example:
- GET `/api/users?email=jim@acmeco.com`
## Advanced Profile Filtering
@@ -115,12 +117,12 @@ There are 3 types of **condition_rules_attributes**
This rule searches for profiles based on the status.
| Key | Type | Description |
|----------|------|-----------------------|
| --- | --- | --- |
| id | string | If you are updating an existing rule, include the ID of that rule, if you do not include an ID it will create a new condition rule |
| type | string **required** | The value must be 'ProfileStatusRule' |
| comparison_operator | string **required** | This is how the comparison is made for the attribute values. <br></br>Available basic operators: <ul><li>== (equals)</li><li>!= (not equal)</li></ul> |
| value | string **required** | This is the value used for comparison.0 <br></br>Available Values: <ul><li>Active</li><li>Inactive</li><li>Leave of absence</li><li>Terminated</li></ul> |
| _destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
| \_destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
Example:
@@ -143,12 +145,12 @@ Example:
This rule searches for profiles based on the id of the profile type.
| Key | Type | Description |
|----------|------|-----------------------|
| --- | --- | --- |
| id | string | If you are updating an existing rule, include the ID of that rule, if you do not include an ID it will create a new condition rule |
| type | string **required** | The value must be 'ProfileTypeRule' |
| comparison_operator | string **required** | This is how the comparison is made for the attribute values. Available basic operators: <ul><li>== (equals)</li><li>!= (not equal)</li></ul> |
| value | string **required** | This is the value used for comparison. This should be the ID of the profile type |
| _destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
| \_destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
Example:
@@ -171,14 +173,14 @@ Example:
This rule searches for profiles based on an attribute that profile has.
| Key | Type | Description |
|----------|------|-----------------------|
| --- | --- | --- |
| id | string | If you are updating an existing rule, include the ID of that rule, if you do not include an ID it will create a new condition rule |
| type | string **required** | The value must be 'ProfileAttributeRule' |
| object_type | string **required** | The values must equal 'NeAttribute' |
| condition_object_id | string **required** | this is the id of the attribute you are searching against |
| comparison_operator | string **required** | This is how the comparison is made for the attribute values. <br></br>Available basic operators: <ul><li>== (equals)</li><li>!= (not equal)</li><li>> (greater than)</li><li>< (less than)</li><li>start_with? (starts with)</li><li>end_with? (ends with)</li><li>include? (includes)</li></ul> Available date operators: <ul><li>before (before specific date)</li><li>after (after specific date)</li><li>> (more than X days before/after today)</li><li>< (less than X days before/after today)</li><li>== (equal to X days before/after today)</li></ul> |
| value | string **required** | This is the value used for comparison. <br></br>Value formatting: <ul><li>profile select attribute: ID of profile</li><li>profile search attribute: ID of profile</li><li>user select attribute: ID of user</li><li>user search attribute: ID of user</li><li>date attribute (before, after): correct date format for attribute</li><li>date attribute (>, <, ==): "X before" or "X after" where X is the number of days</li></ul> |
| _destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
| \_destroy | boolean | Supplying this option with "true" will cause the condition to be destroyed |
Example:

View File

@@ -42,116 +42,102 @@ In this example, the API returns a source, "ubuntu", along with all its details.
<summary>Example Source Details</summary>
```json
{
"description": "ubuntu",
"owner": {
"type": "IDENTITY",
"id": "2c91808475b4334b0175e1e005006401",
"name": "SailPoint Services"
"description": "ubuntu",
"owner": {
"type": "IDENTITY",
"id": "2c91808475b4334b0175e1e005006401",
"name": "SailPoint Services"
},
"cluster": null,
"accountCorrelationConfig": null,
"accountCorrelationRule": null,
"managerCorrelationMapping": null,
"managerCorrelationRule": null,
"beforeProvisioningRule": null,
"schemas": [
{
"type": "CONNECTOR_SCHEMA",
"id": "2c91808c771b686101772a91dbd877ab",
"name": "account"
},
"cluster": null,
"accountCorrelationConfig": null,
"accountCorrelationRule": null,
"managerCorrelationMapping": null,
"managerCorrelationRule": null,
"beforeProvisioningRule": null,
"schemas": [
{
"type": "CONNECTOR_SCHEMA",
"id": "2c91808c771b686101772a91dbd877ab",
"name": "account"
},
{
"type": "CONNECTOR_SCHEMA",
"id": "2c91808c771b686101772a91dbd877ac",
"name": "group"
}
],
"passwordPolicies": null,
"features": [
"NO_RANDOM_ACCESS",
"DISCOVER_SCHEMA",
"DIRECT_PERMISSIONS"
],
"type": "DelimitedFile",
"connector": "delimited-file-angularsc",
"connectorClass": "sailpoint.connector.DelimitedFileConnector",
"connectorAttributes": {
"mergeColumns": [
"groups"
],
"group.mergeRows": true,
"group.delimiter": ",",
"mergeRows": true,
"group.filetransport": "local",
"partitionMode": "disabled",
"connectionType": "file",
"group.host": "local",
"group.indexColumn": "id",
"file": "/tmp/source-account-2c91808c771b686101772a91dbd877aa3299228430527475607.csv",
"delimiter": ",",
"deltaAggregation": null,
"host": "local",
"cloudExternalId": "23012",
"group.indexColumns": [
"id"
],
"cloudIdentityProfileName": null,
"group.mergeColumns": [
"entitlements",
"groups",
"permissions"
],
"hasHeader": true,
"filterEmptyRecords": true,
"oauth_body_attrs_to_exclude": "client_secret,client_id",
"filetransport": "local",
"idnPreviousCorrelationConfig": null,
"deleteThresholdPercentage": 10,
"group.filterEmptyRecords": true,
"group.hasHeader": true,
"group.partitionMode": "disabled",
"cloudAuthoritativeSourcePrecedence": null,
"formPath": null,
"group.columnNames": [
"id",
"name",
"displayName",
"created",
"description",
"modified",
"entitlements",
"groups",
"permissions"
],
"templateApplication": "DelimitedFile Template",
"group.file": "/var/lib/identityiq_workspace/27c92c24-8681-4574-9453-5c56370b3fc9-groups.csv",
"indexColumn": "id",
"healthy": false,
"cloudDisplayName": "Ubuntu",
"connectorName": "Delimited File",
"beforeProvisioningRule": null,
"cloudOriginalApplicationType": "Delimited File",
"since": "2021-01-22T14:48:58.072Z",
"status": "SOURCE_STATE_ERROR_ACCOUNT_FILE_IMPORT"
},
"deleteThreshold": 10,
"authoritative": false,
"healthy": false,
"status": "SOURCE_STATE_ERROR_ACCOUNT_FILE_IMPORT",
"since": "2021-01-22T14:48:58.072Z",
"connectorId": "delimited-file",
"connectorName": "Delimited File",
{
"type": "CONNECTOR_SCHEMA",
"id": "2c91808c771b686101772a91dbd877ac",
"name": "group"
}
],
"passwordPolicies": null,
"features": ["NO_RANDOM_ACCESS", "DISCOVER_SCHEMA", "DIRECT_PERMISSIONS"],
"type": "DelimitedFile",
"connector": "delimited-file-angularsc",
"connectorClass": "sailpoint.connector.DelimitedFileConnector",
"connectorAttributes": {
"mergeColumns": ["groups"],
"group.mergeRows": true,
"group.delimiter": ",",
"mergeRows": true,
"group.filetransport": "local",
"partitionMode": "disabled",
"connectionType": "file",
"connectorImplementationId": "delimited-file",
"managementWorkgroup": null,
"id": "2c91808c771b686101772a91dbd877aa",
"name": "Ubuntu",
"created": "2021-01-22T14:48:58.072Z",
"modified": "2023-06-30T13:39:07.456Z"
"group.host": "local",
"group.indexColumn": "id",
"file": "/tmp/source-account-2c91808c771b686101772a91dbd877aa3299228430527475607.csv",
"delimiter": ",",
"deltaAggregation": null,
"host": "local",
"cloudExternalId": "23012",
"group.indexColumns": ["id"],
"cloudIdentityProfileName": null,
"group.mergeColumns": ["entitlements", "groups", "permissions"],
"hasHeader": true,
"filterEmptyRecords": true,
"oauth_body_attrs_to_exclude": "client_secret,client_id",
"filetransport": "local",
"idnPreviousCorrelationConfig": null,
"deleteThresholdPercentage": 10,
"group.filterEmptyRecords": true,
"group.hasHeader": true,
"group.partitionMode": "disabled",
"cloudAuthoritativeSourcePrecedence": null,
"formPath": null,
"group.columnNames": [
"id",
"name",
"displayName",
"created",
"description",
"modified",
"entitlements",
"groups",
"permissions"
],
"templateApplication": "DelimitedFile Template",
"group.file": "/var/lib/identityiq_workspace/27c92c24-8681-4574-9453-5c56370b3fc9-groups.csv",
"indexColumn": "id",
"healthy": false,
"cloudDisplayName": "Ubuntu",
"connectorName": "Delimited File",
"beforeProvisioningRule": null,
"cloudOriginalApplicationType": "Delimited File",
"since": "2021-01-22T14:48:58.072Z",
"status": "SOURCE_STATE_ERROR_ACCOUNT_FILE_IMPORT"
},
"deleteThreshold": 10,
"authoritative": false,
"healthy": false,
"status": "SOURCE_STATE_ERROR_ACCOUNT_FILE_IMPORT",
"since": "2021-01-22T14:48:58.072Z",
"connectorId": "delimited-file",
"connectorName": "Delimited File",
"connectionType": "file",
"connectorImplementationId": "delimited-file",
"managementWorkgroup": null,
"id": "2c91808c771b686101772a91dbd877aa",
"name": "Ubuntu",
"created": "2021-01-22T14:48:58.072Z",
"modified": "2023-06-30T13:39:07.456Z"
}
```
</details>
@@ -176,7 +162,6 @@ PATCH https://{tenant}.api.identitynow.com/v3/sources/:id
"value": "new description"
}
]
```
This example request uses a "replace" operation to replace the source's existing description with a new value, "new description". This example shows the parts involved in sending a PATCH request. You must specify an operation to apply to the target resource, a path to apply the operation to, and the change you want to make, often in the form of a value or a "from" location for "copy" and "move" operations.
@@ -200,7 +185,6 @@ PATCH https://{tenant}.api.identitynow.com/v3/sources/:id
```
```json
[
{
"op": "replace",
@@ -213,7 +197,6 @@ PATCH https://{tenant}.api.identitynow.com/v3/sources/:id
"value": "!( id.contains( \"m\" ) ) || !( id.contains( \"d\" ) )"
}
]
```
This example request uses a "replace" to update the source's description and an "add" to add a filter string to the source's connector.
@@ -246,8 +229,7 @@ This example uses the [Patch Source Schema](https://developer.sailpoint.com/docs
{
"op": "add",
"path": "/attributes/-",
"value":
{
"value": {
"name": "office",
"type": "STRING",
"schema": null,
@@ -271,19 +253,19 @@ The "remove" operation removes a value from the target location. The target loca
This example uses the [Patch Source](https://developer.sailpoint.com/docs/api/v3/update-source) endpoint to remove an existing filter string from a source's connector:
```json
[
[
{
"op": "remove",
"path": "/connectorAttributes/filterString"
}
]
```
]
```
In this example, the PATCH request is removing a connector's string filter. If there is no string filter to remove, the request will fail and you will receive an error.
In this example, the PATCH request is removing a connector's string filter. If there is no string filter to remove, the request will fail and you will receive an error.
Because there is only one value for the path, the request removes that value.
Because there is only one value for the path, the request removes that value.
If there is an array of values, you must specify the position within the array to remove that value.
If there is an array of values, you must specify the position within the array to remove that value.
This example uses the [Patch Source](https://developer.sailpoint.com/docs/api/v3/update-source) endpoint to remove the first feature from a source's list of features.
@@ -311,13 +293,7 @@ This example uses the [Patch Source](https://developer.sailpoint.com/docs/api/v3
{
"op": "replace",
"path": "/features",
"value":
[
"PASSWORD",
"PROVISIONING",
"ENABLE",
"AUTHENTICATE"
]
"value": ["PASSWORD", "PROVISIONING", "ENABLE", "AUTHENTICATE"]
}
]
```
@@ -381,13 +357,7 @@ This example uses the [Patch Source](https://developer.sailpoint.com/docs/api/v3
{
"op": "test",
"path": "/features",
"value":
[
"PASSWORD",
"PROVISIONING",
"ENABLE",
"AUTHENTICATE"
]
"value": ["PASSWORD", "PROVISIONING", "ENABLE", "AUTHENTICATE"]
}
]
```
@@ -582,12 +552,7 @@ PATCH https://{tenant}.api.identitynow.com/v3/sources/:id
{
"op": "replace",
"path": "/features",
"value": [
"PASSWORD",
"PROVISIONING",
"ENABLE",
"AUTHENTICATE"
]
"value": ["PASSWORD", "PROVISIONING", "ENABLE", "AUTHENTICATE"]
}
]
```
@@ -633,18 +598,16 @@ PATCH https://{tenant}.api.identitynow.com//v3/sources/:sourceId/schemas/:schema
```
```json
[
[
{
"op": "move",
"from": "/attributes/0",
"path": "/attributes/-"
}
]
}
]
```
```
Instead of having to specify the value yourself, which could be an extensive array of information, you can use the "move" operation to move everything from one path to another.
Instead of having to specify the value yourself, which could be an extensive array of information, you can use the "move" operation to move everything from one path to another.
## Apply the PATCH request header
@@ -660,6 +623,6 @@ When the request is successful, the API will return the updated resource.
## Get started
Now you can use PATCH requests partially update resources. For more information about PATCH requests, refer to this [documentation](https://datatracker.ietf.org/doc/html/rfc6902). For more information about the Identity Security Cloud PATCH endpoints and which paths can be changed for each one, refer to their API specifications.
Now you can use PATCH requests partially update resources. For more information about PATCH requests, refer to this [documentation](https://datatracker.ietf.org/doc/html/rfc6902). For more information about the Identity Security Cloud PATCH endpoints and which paths can be changed for each one, refer to their API specifications.
Use this guide to get started, and if you have questions, don't hesitate to reach out on the SailPoint Developer Community forum at https://developer.sailpoint.com/discuss!

View File

@@ -10,7 +10,6 @@ description: Run ISC APIs in Postman.
tags: ['postman']
---
import GitHubPublicFileComponent from '@site/src/components/GitHubLink';
[Postman](https://www.postman.com/) is a platform you can use to design, build, test, and iterate your APIs. Postman users and teams can create public workspaces they can use to make it easy to access their API collections and environments and get started. SailPoint maintains a [public workspace for the Identity Security Cloud API collections](https://www.postman.com/sailpoint/workspace/identitynow). You can use this workspace to access all the ISC API collections and stay up to date.
@@ -19,10 +18,8 @@ import GitHubPublicFileComponent from '@site/src/components/GitHubLink';
Each ISC API version is broken out into a separate collection within the workspace. The following table lists the available ISC API collections. To import a collection into your workspace, select the 'Run in Postman' button for your desired version. Doing so forks the collection into your workspace.
| API | Postman Collection |
|------|----------------------------|
| --- | --- |
| V3 API | [![Run in Postman](./img/button.svg)](https://god.gw.postman.com/run-collection/23226990-3721beea-5615-44b4-9459-e858a0ca7aed?action=collection%2Ffork&collection-url=entityId%3D23226990-3721beea-5615-44b4-9459-e858a0ca7aed%26entityType%3Dcollection%26workspaceId%3D80af54be-a333-4712-af5e-41aa9eccbdd0) |
| Beta API | [![Run in Postman](./img/button.svg)](https://god.gw.postman.com/run-collection/23226990-3b87172a-cd55-40a2-9ace-1560a1158a4e?action=collection%2Ffork&collection-url=entityId%3D23226990-3b87172a-cd55-40a2-9ace-1560a1158a4e%26entityType%3Dcollection%26workspaceId%3D80af54be-a333-4712-af5e-41aa9eccbdd0) |
| NERM API | [![Run in Postman](./img/button.svg)](https://god.gw.postman.com/run-collection/23226990-20d718e3-b9b3-43ad-850c-637b00864ae2?action=collection%2Ffork&collection-url=entityId%3D23226990-20d718e3-b9b3-43ad-850c-637b00864ae2%26entityType%3Dcollection%26workspaceId%3D80af54be-a333-4712-af5e-41aa9eccbdd0) |
@@ -41,12 +38,12 @@ SailPoint is often making improvements to the ISC API collections. To keep your
The SailPoint workspace provides an environment, a set of variables you can use in your requests, that you can fork and pull changes from to stay up to date the same way you can with collections. To import the environment into your workspace, select 'Run in Postman'.
| Environment | [![Run in Postman](./img/button.svg)](https://www.postman.com/sailpoint/workspace/identitynow/environment/23226990-ed571d4f-37a3-4a2c-9105-5d8d8cce1d20/fork) |
|------|----------------------------|
| --- | --- |
To send API requests in Postman, you must authenticate to the APIs. To authenticate to the APIs, you must specify these variables in your Postman environment:
| Environment Variable | Required | Description |
| ----------- | ----------- | ----------- |
| --- | --- | --- |
| tenant | Yes | Your ISC tenant, typically your company's name |
| clientId | Yes | The client ID for the API client or personal access token |
| clientSecret | Yes | The client secret for the API client or personal access token |

View File

@@ -40,11 +40,11 @@ The `searchAfter` capability provides the ability to page on sorted field values
**Required Properties for Paginating Search Results**
|**Property**|Description|
| **Property** | Description |
| --- | --- |
|**query**|The Query JSON object. Refer to the following Query JSON Object table for details.|
|**sort**|The array list of the fields to sort by. This is required if you are using the `searchAfter` approach. You can use `-fieldName` for descending searches (optional).|
|**searchAfter**|You can use this instead of offset to get past the 10,000 paging result record limit, passing the last value(s) of your sort fields from the previous result set into the next result set until you get the total number of results or the end of results (optional).|
| **query** | The Query JSON object. Refer to the following Query JSON Object table for details. |
| **sort** | The array list of the fields to sort by. This is required if you are using the `searchAfter` approach. You can use `-fieldName` for descending searches (optional). |
| **searchAfter** | You can use this instead of offset to get past the 10,000 paging result record limit, passing the last value(s) of your sort fields from the previous result set into the next result set until you get the total number of results or the end of results (optional). |
### Example of Paginating Search Results
@@ -54,15 +54,11 @@ Here is an example of a search API call with `searchAfter` paging. The first que
```json
{
"indices": [
"identities"
],
"query": {
"query": "*"
},
"sort": [
"id"
]
"indices": ["identities"],
"query": {
"query": "*"
},
"sort": ["id"]
}
```
@@ -72,16 +68,12 @@ This query will return 100 records. To get the next 100 records, find the last r
```json
{
"indices": [
"identities"
],
"query": {
"query": "*"
},
"sort": [
"id"
],
"searchAfter": ["2c9180835d38ca0c015d606b50851b1e"]
"indices": ["identities"],
"query": {
"query": "*"
},
"sort": ["id"],
"searchAfter": ["2c9180835d38ca0c015d606b50851b1e"]
}
```

View File

@@ -37,4 +37,3 @@ Below is a list of commands and their usages:
- Delete a connector: `sail conn delete -c [connectorID | connectorAlias]`
- **Linking**
- Link a customizer to your source instance: `sail conn customizers link -i [sourceInstanceID] -c [customizerID]`

View File

@@ -9,10 +9,10 @@ slug: /connectivity/saas-connectivity/commands/account-enable
tags: ['Connectivity', 'Connector Command']
---
| Input/Output | Data Type |
| :-------------- | :---------------------: |
| Input - Enable | StdAccountEnableInput |
| Output - Enable | StdAccountEnableOutput |
| Input/Output | Data Type |
| :-------------- | :--------------------: |
| Input - Enable | StdAccountEnableInput |
| Output - Enable | StdAccountEnableOutput |
### Example StdAccountEnableInput

View File

@@ -180,7 +180,7 @@ The result of the account list command is not an array of objects but several in
If your source can keep track of changes to the data in some way, then delta aggregation can be performed on a source. In order to implement, there are a few things that need to be configured
1. In your connector-spec.json file, the feature needs to be enabled by adding the following key: ```"supportsStatefulCommands": true,``` and in the sourceConfig section, a checkbox needs to be added to enable state with the key ```spConnEnableStatefulCommands```:
1. In your connector-spec.json file, the feature needs to be enabled by adding the following key: `"supportsStatefulCommands": true,` and in the sourceConfig section, a checkbox needs to be added to enable state with the key `spConnEnableStatefulCommands`:
```javascript
"supportsStatefulCommands": true,
@@ -193,7 +193,7 @@ If your source can keep track of changes to the data in some way, then delta agg
}
```
2. In the ```stdAccountList``` command, when you are done sending accounts, you need to also send the state to ISC so it knows where to start the next time it sends a list request:
2. In the `stdAccountList` command, when you are done sending accounts, you need to also send the state to ISC so it knows where to start the next time it sends a list request:
```javascript
const state = {"data": Date.now().toString()}
@@ -205,11 +205,11 @@ In the above example, I am capturing the date, but you can use any value you wan
:::caution Important
The state that you send using the ```saveState``` command MUST be a json object, and it is recommend to only save strings to ensure proper serialization/deserialization of the data. You cannot send a simple string or number or it will not properly save the state.
The state that you send using the `saveState` command MUST be a json object, and it is recommend to only save strings to ensure proper serialization/deserialization of the data. You cannot send a simple string or number or it will not properly save the state.
:::
3. In the ```stdAccountList``` command, you need to properly handle the state object. Something like below checks the stateful boolean as well as the state object and fetches accounts accordingly:
3. In the `stdAccountList` command, you need to properly handle the state object. Something like below checks the stateful boolean as well as the state object and fetches accounts accordingly:
```javascript
.stdAccountList(async (context: Context, input: StdAccountListInput, res: Response<StdAccountListOutput>) => {

View File

@@ -105,4 +105,4 @@ Note: Testing the account update command for removing entitlements using this me
## Handling an account that is not found
If an account can't be found in the source system, ISC can recreate the account by using the ```ConnectorErrorType.NotFound``` error type. For details and implementation, refer to [Error Handling](../in-depth/error-handling.md#not-found-error-type).
If an account can't be found in the source system, ISC can recreate the account by using the `ConnectorErrorType.NotFound` error type. For details and implementation, refer to [Error Handling](../in-depth/error-handling.md#not-found-error-type).

View File

@@ -9,8 +9,8 @@ slug: /connectivity/saas-connectivity/commands/change-password
tags: ['Connectivity', 'Connector Command']
---
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdChangePasswordInput |
| Output | StdChangePasswordOutput |
@@ -29,7 +29,8 @@ tags: ['Connectivity', 'Connector Command']
### Example StdChangePasswordOutput
```javascript
{}
{
}
```
## Description

View File

@@ -104,6 +104,7 @@ private buildStandardObject(): StdEntitlementReadOutput | StdEntitlementListOutp
}
}
```
:::caution Important
ISC will throw a connection timeout error if your connector doesn't respond within 3 minutes, and there are memory limitations involved with aggregating data. To prevent large memory utilization or timeout errors, you should set up your connectors to send data to ISC as it's retrieved from your source system. For more details and an example, refer to [Connector Timeouts](../in-depth/connector-timeouts.md).
@@ -120,7 +121,7 @@ ISC supports [delta aggregation](#delta-aggregation-state). If your source has a
If your source can keep track of changes to the data in some way, then delta aggregation can be performed on a source. In order to implement, there are a few things that need to be configured
1. In your connector-spec.json file, the feature needs to be enabled by adding the following key: ```"supportsStatefulCommands": true,``` and in the sourceConfig section, a checkbox needs to be added to enable state with the key ```spConnEnableStatefulCommands```:
1. In your connector-spec.json file, the feature needs to be enabled by adding the following key: `"supportsStatefulCommands": true,` and in the sourceConfig section, a checkbox needs to be added to enable state with the key `spConnEnableStatefulCommands`:
```javascript
"supportsStatefulCommands": true,
@@ -133,7 +134,7 @@ If your source can keep track of changes to the data in some way, then delta agg
}
```
2. In the ```stdEntitlementList``` command, when you are done sending entitlments, you need to also send the state to ISC so it knows where to start the next time it sends a list request:
2. In the `stdEntitlementList` command, when you are done sending entitlments, you need to also send the state to ISC so it knows where to start the next time it sends a list request:
```javascript
const state = {"data": Date.now().toString()}
@@ -145,11 +146,11 @@ In the above example, I am capturing the date, but you can use any value you wan
:::caution Important
The state that you send using the ```saveState``` command MUST be a json object, and it is recommend to only save strings to ensure proper serialization/deserialization of the data. You cannot send a simple string or number or it will not properly save the state.
The state that you send using the `saveState` command MUST be a json object, and it is recommend to only save strings to ensure proper serialization/deserialization of the data. You cannot send a simple string or number or it will not properly save the state.
:::
3. In the ```stdEntitlementList``` command, you need to properly handle the state object. Something like below checks the stateful boolean as well as the state object and fetches accounts accordingly:
3. In the `stdEntitlementList` command, you need to properly handle the state object. Something like below checks the stateful boolean as well as the state object and fetches accounts accordingly:
```javascript
.stdEntitlementList(async (context: Context, input: StdEntitlementListInput, res: Response<StdEntitlementListOutput>) => {

View File

@@ -9,7 +9,7 @@ slug: /connectivity/saas-connectivity/commands/source-data-discover
tags: ['Connectivity', 'Connector Command']
---
| Input/Output | Data Type |
| Input/Output | Data Type |
| :----------- | :-------------------------: |
| Input | StdSourceDataDiscoverInput |
| Output | StdSourceDataDiscoverOutput |
@@ -29,17 +29,17 @@ tags: ['Connectivity', 'Connector Command']
```javascript
[
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id'
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name'
}
]
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id',
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name',
},
];
```
## Description

View File

@@ -9,8 +9,8 @@ slug: /connectivity/saas-connectivity/commands/source-data-read
tags: ['Connectivity', 'Connector Command']
---
| Input/Output | Data Type |
| :----------- | :-------------------------: |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdSourceDataReadInput |
| Output | StdSourceDataReadOutput |
@@ -30,24 +30,24 @@ tags: ['Connectivity', 'Connector Command']
```javascript
[
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id'
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name'
}
]
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id',
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name',
},
];
```
## Description
Use the source data read command to query a source in Identity Security Cloud and return a set of data. This data is typically used to populate a dropdown menu for selection purposes. This functionality is typically useful for Identity Security Cloud forms, but it can be used for any type of implementation that requires you to get other information from a source, information that is not normally retrieved from identites or entitlements.
This is a simple example of the source data read command. It is implemented to retrieve the base ID name. The `sourceDataKey` is required, the ```source data read``` command should return it.
This is a simple example of the source data read command. It is implemented to retrieve the base ID name. The `sourceDataKey` is required, the `source data read` command should return it.
```javascript
.stdSourceDataRead(async (context: Context, input: StdSourceDataReadInput, res: Response<StdSourceDataReadOutput>) => {

View File

@@ -18,7 +18,7 @@ The connector config object holds all the config values that are set in the SaaS
The config object is fetched during initialization of the connector
```typescript
const config: Config = await readConfig()
const config: Config = await readConfig();
```
### Example Config Object
@@ -27,36 +27,36 @@ Below is an example object model that can be used to type your config. Any value
```typescript
export interface Config {
beforeProvisioningRule: any
cloudCacheUpdate: number
cloudDisplayName: string
cloudExternalId: string
connectionType: string
connectorName: string
deleteThresholdPercentage: number
deltaAggregation: DeltaAggregation
deltaAggregationEnabled: boolean
formPath: any
hasFullAggregationCompleted: boolean
healthCheckTimeout: number
healthy: boolean
idnProxyType: string
managementWorkgroup: any
managerCorrelationFilter: any
since: string
"slpt-source-diagnostics": string
sourceConnected: boolean
sourceDescription: string
spConnEnableStatefulCommands: boolean
spConnectorInstanceId: string
spConnectorSpecId: string
status: string
supportsDeltaAgg: boolean
templateApplication: string
}
beforeProvisioningRule: any;
cloudCacheUpdate: number;
cloudDisplayName: string;
cloudExternalId: string;
connectionType: string;
connectorName: string;
deleteThresholdPercentage: number;
deltaAggregation: DeltaAggregation;
deltaAggregationEnabled: boolean;
formPath: any;
hasFullAggregationCompleted: boolean;
healthCheckTimeout: number;
healthy: boolean;
idnProxyType: string;
managementWorkgroup: any;
managerCorrelationFilter: any;
since: string;
'slpt-source-diagnostics': string;
sourceConnected: boolean;
sourceDescription: string;
spConnEnableStatefulCommands: boolean;
spConnectorInstanceId: string;
spConnectorSpecId: string;
status: string;
supportsDeltaAgg: boolean;
templateApplication: string;
}
export interface DeltaAggregation {
"std:account:list": any
"std:entitlement:list": any
}
export interface DeltaAggregation {
'std:account:list': any;
'std:entitlement:list': any;
}
```

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-create](../../commands/account-create) command.
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input | StdAccountCreateInput |
@@ -60,6 +59,7 @@ Use these commands to intercept the [account-create](../../commands/account-crea
}
}
```
## Implementation
### Before account-create command
@@ -72,6 +72,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-create command
@@ -84,4 +85,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -37,6 +37,7 @@ Use these commands to intercept the [account-delete](../../commands/account-dele
{
}
```
## Implementation
### Before account-delete command
@@ -49,6 +50,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-delete command
@@ -61,4 +63,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,11 +13,10 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-disable](../../commands/account-disable) command.
| Input/Output | Data Type |
| :-------------- | :---------------------: |
| Input | StdAccountDisableInput |
| Output | StdAccountDisableOutput |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdAccountDisableInput |
| Output | StdAccountDisableOutput |
### Example StdAccountDisableInput
@@ -53,6 +52,7 @@ Use these commands to intercept the [account-disable](../../commands/account-dis
}
}
```
## Implementation
### Before account-disable command
@@ -65,6 +65,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-disable command
@@ -77,4 +78,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,11 +13,10 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-enable](../../commands/account-enable) command.
| Input/Output | Data Type |
| :-------------- | :---------------------: |
| Input | StdAccountEnableInput |
| Output | StdAccountEnableOutput |
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input | StdAccountEnableInput |
| Output | StdAccountEnableOutput |
### Example StdAccountEnableInput
@@ -53,6 +52,7 @@ Use these commands to intercept the [account-enable](../../commands/account-enab
}
}
```
## Implementation
### Before account-enable command
@@ -65,6 +65,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-enable command
@@ -77,4 +78,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,10 +13,9 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-list](../../commands/account-list) command.
| Input/Output | Data Type |
| :----------- | :------------------: |
| Input | StdAccountListInput |
| Input/Output | Data Type |
| :----------- | :-----------------: |
| Input | StdAccountListInput |
### Example StdAccountListInput
@@ -24,6 +23,7 @@ Use these commands to intercept the [account-list](../../commands/account-list)
"state": {"date": "1686341338871"},
"stateful": true
```
## Implementation
### Before account-list command
@@ -36,6 +36,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-list command

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-read](../../commands/account-read) command.
| Input/Output | Data Type |
| :----------- | :------------------: |
| Input | StdAccountReadInput |
@@ -53,8 +52,8 @@ Use these commands to intercept the [account-read](../../commands/account-read)
}
}
```
## Implementation
## Implementation
### Before account-read command
@@ -66,6 +65,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-read command
@@ -78,4 +78,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-unlock](../../commands/account-unlock) command.
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input | StdAccountUnlockInput |
@@ -53,6 +52,7 @@ Use these commands to intercept the [account-unlock](../../commands/account-unlo
}
}
```
## Implementation
### Before account-unlock command
@@ -65,6 +65,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-unlock command
@@ -77,4 +78,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [account-update](../../commands/account-update) command.
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input | StdAccountUpdateInput |
@@ -62,8 +61,8 @@ Use these commands to intercept the [account-update](../../commands/account-upda
}
}
```
## Implementation
## Implementation
### Before account-update command
@@ -75,6 +74,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After account-update command
@@ -87,4 +87,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,9 +13,8 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [change-password](../../commands/change-password) command.
| Input/Output | Data Type |
| :----------- | :--------------------: |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdChangePasswordInput |
| Output | StdChangePasswordOutput |
@@ -34,10 +33,11 @@ Use these commands to intercept the [change-password](../../commands/change-pass
### Example StdChangePasswordOutput
```javascript
{}
{
}
```
## Implementation
## Implementation
### Before change-password command
@@ -49,6 +49,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After change-password command
@@ -61,4 +62,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,10 +13,9 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [entitlement-list](../../commands/entitlement-list) command.
| Input/Output | Data Type |
| :----------- | :----------------------: |
| Input | StdEntitlementListInput |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdEntitlementListInput |
### Example StdEntitlementListInput
@@ -38,6 +37,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After entitlement-list command

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [entitlement-read](../../commands/entitlement-read) command.
| Input/Output | Data Type |
| :----------- | :----------------------: |
| Input | StdEntitlementReadInput |
@@ -50,6 +49,7 @@ Use these commands to intercept the [entitlement-read](../../commands/entitlemen
}
}
```
## Implementation
### Before entitlement-read command
@@ -62,6 +62,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After entitlement-read command
@@ -74,4 +75,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,8 +13,7 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [source-data-discover](../../commands/source-data-discover) command.
| Input/Output | Data Type |
| Input/Output | Data Type |
| :----------- | :-------------------------: |
| Input | StdSourceDataDiscoverInput |
| Output | StdSourceDataDiscoverOutput |
@@ -34,18 +33,19 @@ Use these commands to intercept the [source-data-discover](../../commands/source
```javascript
[
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id'
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name'
}
]
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id',
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name',
},
];
```
## Implementation
### Before source-data-discover command
@@ -58,6 +58,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After source-data-discover command
@@ -70,4 +71,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,9 +13,8 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [source-data-read](../../commands/source-data-read) command.
| Input/Output | Data Type |
| :----------- | :-------------------------: |
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | StdSourceDataReadInput |
| Output | StdSourceDataReadOutput |
@@ -35,18 +34,19 @@ Use these commands to intercept the [source-data-read](../../commands/source-dat
```javascript
[
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id'
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name'
}
]
{
key: 'id',
label: 'Id',
subLabel: 'Airtable Base Id',
},
{
key: 'name',
label: 'Name',
subLabel: 'Airtable Source Table Name',
},
];
```
## Implementation
### Before source-data-read command
@@ -59,6 +59,7 @@ Use this logic to implement the command:
return input
})
```
The `input` object can be mutated and returned, but the same data type must still be returned.
### After source-data-read command
@@ -71,4 +72,5 @@ Use this logic to implement the command:
return output
})
```
The `output` object can be mutated and returned, but the same data type must still be returned.

View File

@@ -13,7 +13,6 @@ tags: ['Connectivity', 'Connector Command']
Use these commands to intercept the [Test-Connection](../../commands/test-connection) command.
| Input/Output | Data Type |
| :----------- | :---------------------: |
| Input | undefined |
@@ -25,6 +24,7 @@ Use these commands to intercept the [Test-Connection](../../commands/test-connec
{
}
```
## Implementation
### Before test-connection command
@@ -36,6 +36,7 @@ Use this logic to implement the command:
logger.info('Running before test connection')
})
```
There is no input, so you cannot mutate any data. However, you can make web request calls or perform any type of logging or logic before calling the connector.
### After test-connection command
@@ -48,4 +49,5 @@ Use this logic to implement the command:
return output
})
```
The output datatype is always an empty object handed down from the connector.

View File

@@ -33,7 +33,7 @@ sail conn customizers init my-customizer-project
The CLI init command creates a new folder with your project name in the location where you run the command.
Change the directory to the project folder and run ```npm install`` to install the dependencies.
Change the directory to the project folder and run ``npm install` to install the dependencies.
### Source files

View File

@@ -19,7 +19,7 @@ SaaS Connectivity Customizers are cloud-based connector customizers that make cu
SaaS Connectivity Customizers work by sitting in between Identity Security Cloud and the connector. They intercept calls from Identity Security Cloud to the connector and calls from the connector to Identity Security Cloud. When the customizer intercepts a call, it can call custom code to mutate the data in any way necessary to change the connector behavior.
This chart shows an example of this interception process - the ```stdAccountRead``` command is implemented with the customizer in place:
This chart shows an example of this interception process - the `stdAccountRead` command is implemented with the customizer in place:
<div align="center">

View File

@@ -22,6 +22,7 @@ Use this command to find sources:
```bash
sail conn instances list
```
This similar looking list of instances will be returned:
```bash
@@ -41,6 +42,7 @@ Use this command to find customizers:
```bash
sail conn customizers list
```
This similar looking list of customizers will be returned:
```bash
@@ -58,7 +60,9 @@ To link a source to a customizer, find the source ID in the instance list and a
```bash
sail conn customizers link -i edfc9bfb-b55c-482f-b1aa-b4d51caf7558 -c 7b968fab-0f40-49f0-b13b-8bf529fc0b82
```
The output will indicate that the customizer has succesfully linked to the connector instance:
```bash
+--------------------------------------+----------------------+--------------------------------------+
| ID | NAME | CUSTOMIZER ID |

View File

@@ -55,4 +55,5 @@ To upload the customizer to Identity Security Cloud, use the upload command:
```bash
sail conn customizers upload -c 7b968fab-0f40-49f0-b13b-8bf529fc0b82 -f .\dist\my-connector-customizer-0.1.0.zip
```
Now the customizer is ready to be used!

View File

@@ -3,18 +3,19 @@ id: connector-spec-card
title: Card
pagination_label: Card
sidebar_label: Card
keywords: ['connectivity', 'connectors','connector-spec', 'card']
keywords: ['connectivity', 'connectors', 'connector-spec', 'card']
description: Details on using the card item
slug: /connectivity/saas-connectivity/connector-spec/card
tags: ['Connectivity', 'Connector Spec']
---
## How to use the card type in the connector spec
You can use the `card` type to specify cards that allow users to add/copy/delete and enter a subMenu to make changes to more card details.
When you create a card, you must specify the fields the cardSubMenu will use to generate the title and subtitle, as shown in the following example.
In this example, clicking the ```Add table``` button opens a dialog, and the values entered for the ```Table Information``` and ```Airtable Id``` will populate the cards ```title``` and ```subtitle```.
In this example, clicking the `Add table` button opens a dialog, and the values entered for the `Table Information` and `Airtable Id` will populate the cards `title` and `subtitle`.
### Example card item type
@@ -71,7 +72,7 @@ In this example, clicking the ```Add table``` button opens a dialog, and the val
]
}
```
![card input type](../img/card.png)
![card menu input type](../img/cardMenu.png)

View File

@@ -3,7 +3,8 @@ id: connector-spec-initial-value
title: Initial Value
pagination_label: Initial Value
sidebar_label: Initial Value
keywords: ['connectivity', 'connectors','connector-spec', 'sourceConfigInitialValues']
keywords:
['connectivity', 'connectors', 'connector-spec', 'sourceConfigInitialValues']
description: How to use the sourceConfigInitialValues field
slug: /connectivity/saas-connectivity/connector-spec/initial-value
tags: ['Connectivity', 'Connector Spec']

View File

@@ -3,13 +3,14 @@ id: connector-spec-key-value
title: Key Value
pagination_label: Key Value
sidebar_label: Key Value
keywords: ['connectivity', 'connectors','connector-spec', 'keyValue']
keywords: ['connectivity', 'connectors', 'connector-spec', 'keyValue']
description: Details on using the key value item
slug: /connectivity/saas-connectivity/connector-spec/key-value
tags: ['Connectivity', 'Connector Spec']
---
## How to use the key value type in the connector spec
You can use the `keyValue` type to allow users to enter multiple key value items in a single entry box.
This is an example implementation:
@@ -37,4 +38,5 @@ This is an example implementation:
}
}
```
![list input type](../img/keyValue.png)

View File

@@ -3,13 +3,14 @@ id: connector-spec-list
title: List
pagination_label: List
sidebar_label: List
keywords: ['connectivity', 'connectors','connector-spec', 'list']
keywords: ['connectivity', 'connectors', 'connector-spec', 'list']
description: Details on using the list item
slug: /connectivity/saas-connectivity/connector-spec/list
tags: ['Connectivity', 'Connector Spec']
---
## How to use the list type in the connector spec
You can use the `list` type to allow users to enter multiple items in a single entry box.
This is an example implementation:
@@ -24,4 +25,5 @@ This is an example implementation:
"helpKey": "Add a list of entitlements to expose via your source"
}
```
![list input type](../img/list.png)

View File

@@ -3,13 +3,14 @@ id: connector-spec-radio
title: Radio
pagination_label: Radio
sidebar_label: Radio
keywords: ['connectivity', 'connectors','connector-spec', 'radio']
keywords: ['connectivity', 'connectors', 'connector-spec', 'radio']
description: Details on using the Radio item
slug: /connectivity/saas-connectivity/connector-spec/radio
tags: ['Connectivity', 'Connector Spec']
---
## How to use the radio type in the connector spec
You can use the `Rrdio` type to create radio buttons for users to interact with to select from a predefined set of values.
This is an example implementation:
@@ -34,6 +35,7 @@ This is an example implementation:
]
}
```
![radio input type](../img/radio.png)
You can also create dependencies on other fields so they are hidden until the selection is made. This same type of dependency can be built into any field and linked by using the parentKey/parentValue fields.

View File

@@ -3,13 +3,14 @@ id: connector-spec-select
title: Select
pagination_label: Select
sidebar_label: Select
keywords: ['connectivity', 'connectors','connector-spec', 'select']
keywords: ['connectivity', 'connectors', 'connector-spec', 'select']
description: Details on using the select item
slug: /connectivity/saas-connectivity/connector-spec/select
tags: ['Connectivity', 'Connector Spec']
---
## How to use the Select type in the connector spec
You can use the Select type to create a dropdown for users to interact with to select from a predefined set of values.
This is an example implementation:
@@ -34,6 +35,7 @@ This is an example implementation:
]
}
```
![select input type](../img/select.png)
You can also create dependencies on other fields so they are hidden until the selection is made. This same type of dependency can be built into any field and linked by using the parentKey/parentValue fields.

View File

@@ -33,6 +33,7 @@ Available Commands:
source-data-read Invoke a std:source-data:read command
test-connection Invoke a std:test-connection command
```
To understand the required parameters to invoke a command from the CLI, you can use the help command to get a list of required parameters. For example, to read an account using the CLI, first call `sail conn invoke account-read -h`. The CLI will respond with the required input:
```bash
@@ -52,14 +53,15 @@ Global Flags:
-c, --id string Connector ID or Alias
-v, --version string Optional. Run against a specific version if provided. Otherwise run against the latest tag.
```
In this case, you need to provide the connector ID, the config path that contains the necessary configuration for the connector, and the ID for the account.
The config file will look something like this:
```json
{
"apiKey": "<API_KEY>",
"airtableBase": "<BASE_ID>"
"apiKey": "<API_KEY>",
"airtableBase": "<BASE_ID>"
}
```
@@ -83,6 +85,7 @@ You can use the Postman collection as a way to build the JSON object needed to i
}
}
```
Running the `raw` command is similar to running the other commands, except now you pass the JSON file created earlier with the `-f` flag:
```

View File

@@ -45,7 +45,7 @@ export class AirtableClient {
## Not Found Error Type
The connector SDK offers a special error type of "Not Found". This error signals to ISC that the specific account is not in the source system. If the account should be in the source system, ISC will then call the connector ```std:account:create``` command to create the account.
The connector SDK offers a special error type of "Not Found". This error signals to ISC that the specific account is not in the source system. If the account should be in the source system, ISC will then call the connector `std:account:create` command to create the account.
Here is an example:
@@ -120,19 +120,25 @@ export class AirtableClient {
## Recommended custom exceptions and examples of when to use them
#### InvalidConfigurationException
- Use this exception during any operation if the connector requires a certain configuration to connect to the managed-system, but the configuration is either faulty or not provided. This could happen before sending a request to the managed system.
#### InsufficientPermissionException
- Use this exception during any operation if the connector gets a known managed system exception indicating a lack of permission.
#### InvalidRequestException
- Use this exception during any operation if the connector is creating messages to be sent to the managed system but is failing to create a message. This could happen before sending a request to the managed system.
#### ObjectAlreadyExistsException
- Use this exception during the provisioning operation of the type create(only) if the connector is trying to create an entity that already exists on the managed system.
#### InvalidResponseException
- Use this exception during aggregation or in the getObject when the connector is unable to parse data received from managed system. This could happen if something fails when converting a managed system response to a ResourceObject.
#### TimeoutException
- This is intended for cases in which the connector receives timeout related error/exceptions from the managed system.

View File

@@ -20,9 +20,10 @@ Connectors are the bridges between the SailPoint Identity Security Cloud (ISC) S
## Why We Are Introducing SaaS Connectivity
The primary driver for indroducing the SaaS Connectivity framework is to allow a way to connect to other cloud based sources in a truly SaaS architecture, without the need to rely on a VA. There are also other benefits that come with the SaaS Connectivity framework:
- Ability to develop, debug and test custom connectors locally without any dependencies on Identity Security Cloud
- Features to customize the user interface when configuring the connector that are specific to the source
- Support for more modern languages and frameworks
- Ability to develop, debug and test custom connectors locally without any dependencies on Identity Security Cloud
- Features to customize the user interface when configuring the connector that are specific to the source
- Support for more modern languages and frameworks
## Architecture of SaaS Connectivity
@@ -42,4 +43,4 @@ With both SaaS connectivity and traditional VA connectivity in place, you can ha
Any direct connectors that specify a virtual appliance (VA) use [Zero Knowledge Encryption](https://community.sailpoint.com/t5/Lighthouse/Protecting-Sensitive-Data-with-Zero-Knowledge-Encryption/ta-p/79657?attachment-id=452) schemes with an RSA 2048-bit asymmetric key pair: there is a private key on the VA for decryption and a public key in the cloud (as part of the VA cluster) for encryption.
SaaS connectors cannot operate the same way because they do not communicate through VA clusters. Despite this, SaaS connectors can still leverage the asymmetric key pair scheme — the key pair simply resides in the cloud instead of on the VA. The key pair is only accessible to the Connectivity service and is managed to SailPoint standards for credential storage. Whenever you are storing secret data, use the ```secret``` or ```secrettextarea``` field types.
SaaS connectors cannot operate the same way because they do not communicate through VA clusters. Despite this, SaaS connectors can still leverage the asymmetric key pair scheme — the key pair simply resides in the cloud instead of on the VA. The key pair is only accessible to the Connectivity service and is managed to SailPoint standards for credential storage. Whenever you are storing secret data, use the `secret` or `secrettextarea` field types.

View File

@@ -14,5 +14,5 @@ tags: ['Connectivity', 'Postman']
Use the following Postman Collection file to run tests for each of the commands locally.
| API | Postman Collection |
|------|----------------------------|
| --- | --- |
| SaaS Connectivity | [![Run in Postman](./img/button.svg)](https://god.gw.postman.com/run-collection/23226990-a0b5c429-d8dd-4fe2-a4a2-eb7ff85322ef?action=collection%2Ffork&collection-url=entityId%3D23226990-a0b5c429-d8dd-4fe2-a4a2-eb7ff85322ef%26entityType%3Dcollection%26workspaceId%3D80af54be-a333-4712-af5e-41aa9eccbdd0) |

View File

@@ -41,7 +41,7 @@ sail conn init my-first-project
The CLI init command creates a new folder with your project name in the location where you run the command.
Change the directory to the project folder and run ```npm install to install`` the dependencies.
Change the directory to the project folder and run ``npm install to install` the dependencies.
### Source Files

View File

@@ -102,8 +102,7 @@ $ sail conn tags list -c example-connector
:::caution Important
Make sure that you implement a form of version control or regular backup process for your connectors.
You cannot recover the source code from ISC because it gets sent to ISC as a compiled and minified JavaScript (JS) bundle that cannot be easily expanded into its original source code structure.
Make sure that you implement a form of version control or regular backup process for your connectors. You cannot recover the source code from ISC because it gets sent to ISC as a compiled and minified JavaScript (JS) bundle that cannot be easily expanded into its original source code structure.
:::

View File

@@ -10,14 +10,15 @@ description: Helpful videos on using SaaS connectivity
slug: /connectivity/saas-connectivity/videos
tags: ['Connectivity']
---
import Video from '@site/src/components/Video';
## Videos
During our 2023 Developer Days Conference, we created several connectivity videos. These videos can help you as you start building connectors:
- [Roadmap and Introduction](https://www.youtube.com/watch?v=12pfpLBNCvM)
- [Building a Complete Connector Walkthrough](https://www.youtube.com/watch?v=wHHje_ItTKQ)
- [SDKs in practice](https://www.youtube.com/watch?v=uvnlSUVsF8M)
- [Roadmap and Introduction](https://www.youtube.com/watch?v=12pfpLBNCvM)
- [Building a Complete Connector Walkthrough](https://www.youtube.com/watch?v=wHHje_ItTKQ)
- [SDKs in practice](https://www.youtube.com/watch?v=uvnlSUVsF8M)
<Video source="https://www.youtube.com/embed/wHHje_ItTKQ"></Video>

View File

@@ -12,6 +12,7 @@ tags: ['extensibility']
---
## Overview
The Identity Security Cloud (ISC) platform is designed for extensibility, which means that it's designed to allow the addition of new capabilities or functionalities. In addition to the APIs, SailPoint provides a number of extensibility options you can use to build custom solutions and integrations that meet your organization's needs.
```mdx-code-block
@@ -22,6 +23,7 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
## Discuss
The most valuable resource for ISC developers is the SailPoint Developer Community itself, where ISC users and experts all over the world come together to ask questions and provide solutions.
To learn more about ISC extensibility and discuss the different extensibility options with SailPoint Developer Community members, go to the [SailPoint Developer Community Forum](https://developer.sailpoint.com/discuss/c/isc/6).

View File

@@ -1,5 +1,5 @@
{
"customProps": {
"description": "Export and import tenant configurations."
}
"customProps": {
"description": "Export and import tenant configurations."
}
}

View File

@@ -1,5 +1,5 @@
{
"customProps": {
"description": "Actions triggered by specific events."
}
"customProps": {
"description": "Actions triggered by specific events."
}
}

View File

@@ -4,7 +4,16 @@ title: Access Request Submitted
pagination_label: Access Request Submitted
sidebar_label: Access Request Submitted
sidebar_class_name: accessRequestSubmitted
keywords: ['event', 'trigger', 'access', 'request', 'submitted', 'preapproval', 'available']
keywords:
[
'event',
'trigger',
'access',
'request',
'submitted',
'preapproval',
'available',
]
description: Fires after an access request is submitted.
slug: /extensibility/event-triggers/triggers/access-request-submitted
tags: ['Event Triggers', 'Available Event Triggers', 'Request Response']

View File

@@ -12,8 +12,7 @@ tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
## Event Context
This event is triggered when a certification is signed-off and moves to End status.
This is not to be confused with Campaign End/Expiration.
This event is triggered when a certification is signed-off and moves to End status. This is not to be confused with Campaign End/Expiration.
This is an example input from this trigger:

View File

@@ -14,7 +14,7 @@ tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
:::info Important Setup Steps
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
1. Invoke the [update native change detection configuration](https://developer.sailpoint.com/docs/api/beta/put-native-change-detection-config) for each source you want to receive events for NCD.
2. Configure the NCD options on the source in the source configuration UI.
@@ -38,7 +38,7 @@ flowchart TD
</div>
This event trigger can be used to immediately notify interested parties and remediate accounts that are created directly on the source. Some examples of how this trigger can be used are as follows:
This event trigger can be used to immediately notify interested parties and remediate accounts that are created directly on the source. Some examples of how this trigger can be used are as follows:
- Notify the identity's manager and the source owner of the new account
- Create a micro-certification for the identity to review their new account access
@@ -48,139 +48,131 @@ This is an example input from this trigger:
```json
{
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"name": "peter.williams",
"alias": "peter.williams",
"id": "e43ba47b265b4baf943efe3aaef886c8",
"type": "IDENTITY",
"email": "peter.williams@sample_email.com"
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"singleValueAttributeChanges": [
{
"newValue": "Peter Williams",
"name": "cn",
"oldValue": null
},
{
"newValue": "Peter Williams",
"name": "displayName",
"oldValue": null
},
{
"newValue": "CN=Peter Williams,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com",
"name": "distinguishedName",
"oldValue": null
},
{
"newValue": "Peter",
"name": "givenName",
"oldValue": null
}
],
"entitlementChanges": [
{
"removed": [],
"added": [
{
"owner": {
"id": "2c91808978eb9fab0178fb8ca9280919",
"name": "Gregory Brooks",
"type": "IDENTITY"
},
"name": "ProductionManagement",
"id": "2c91808778eb9fa30178fb9482f00c60",
"value": "CN=ProductionManagement,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "Employees",
"id": "2c91808378eb9fa30178fb94818e0af8",
"value": "CN=Employees,OU=BirthRight,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "WindowsAdministration",
"id": "2c91808378eb9fa30178fb9481c30b02",
"value": "CN=WindowsAdministration,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"attributeName": "memberOf"
}
],
"eventType": "ACCOUNT_CREATED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
"name": "peter.williams",
"alias": "peter.williams",
"id": "e43ba47b265b4baf943efe3aaef886c8",
"type": "IDENTITY",
"email": "peter.williams@sample_email.com"
},
"singleValueAttributeChanges": [
{
"newValue": "Peter Williams",
"name": "cn",
"oldValue": null
},
"accountChangeTypes": [
"ATTRIBUTES_CHANGED",
"ENTITLEMENTS_ADDED"
],
"multiValueAttributeChanges": [
{
"removedValues": [],
"addedValues": [
"top",
"person",
"organizationalPerson",
"user"
],
"name": "objectClass"
},
{
"removedValues": [],
"addedValues": [
"Normal User Account",
"Password Cannot Expire",
"User Account is Disabled"
],
"name": "accountFlags"
}
],
"account": {
"name": "peter.williams",
"id": "b3b17b0072f04da39b41e8802aaff01b",
"type": "ACCOUNT",
"uuid": "{615ebfa6-3d21-484e-9e67-01bd4e20c3da}",
"correlated": true,
"nativeIdentity": "CN=Peter Williams,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
{
"newValue": "Peter Williams",
"name": "displayName",
"oldValue": null
},
{
"newValue": "CN=Peter Williams,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com",
"name": "distinguishedName",
"oldValue": null
},
{
"newValue": "Peter",
"name": "givenName",
"oldValue": null
}
],
"entitlementChanges": [
{
"removed": [],
"added": [
{
"owner": {
"id": "2c91808978eb9fab0178fb8ca9280919",
"name": "Gregory Brooks",
"type": "IDENTITY"
},
"name": "ProductionManagement",
"id": "2c91808778eb9fa30178fb9482f00c60",
"value": "CN=ProductionManagement,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "Employees",
"id": "2c91808378eb9fa30178fb94818e0af8",
"value": "CN=Employees,OU=BirthRight,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "WindowsAdministration",
"id": "2c91808378eb9fa30178fb9481c30b02",
"value": "CN=WindowsAdministration,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"attributeName": "memberOf"
}
],
"eventType": "ACCOUNT_CREATED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
},
"accountChangeTypes": ["ATTRIBUTES_CHANGED", "ENTITLEMENTS_ADDED"],
"multiValueAttributeChanges": [
{
"removedValues": [],
"addedValues": ["top", "person", "organizationalPerson", "user"],
"name": "objectClass"
},
{
"removedValues": [],
"addedValues": [
"Normal User Account",
"Password Cannot Expire",
"User Account is Disabled"
],
"name": "accountFlags"
}
],
"account": {
"name": "peter.williams",
"id": "b3b17b0072f04da39b41e8802aaff01b",
"type": "ACCOUNT",
"uuid": "{615ebfa6-3d21-484e-9e67-01bd4e20c3da}",
"correlated": true,
"nativeIdentity": "CN=Peter Williams,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
}
```
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account created event, all aggregated account attributes will be listed, and their `oldValue` will be null.
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account created event, all aggregated account attributes will be listed, and their `oldValue` will be null.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `entitlementChanges` Contains a list of entitlements that have been aggregated with the account. the `removed` list will always be empty for an account created event.
- `entitlementChanges` Contains a list of entitlements that have been aggregated with the account. the `removed` list will always be empty for an account created event.
- `eventType` Will always be `ACCOUNT_CREATED` for account created events.
- `source` The source where this account originated from.
- `accountChangeTypes` A list of change types you can expect to see in the event input.
- Possible values are `ATTRIBUTES_CHANGED` and `ENTITLEMENTS_ADDED`.
- The above example lists both change types since both attributes and entitlements were added. If an event payload only contains attributes added, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- `multiValueAttributeChanges` List of multivalued attributes that were aggregated with the account. Only `addedValues` will appear for account created events.
- The above example lists both change types since both attributes and entitlements were added. If an event payload only contains attributes added, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- `multiValueAttributeChanges` List of multivalued attributes that were aggregated with the account. Only `addedValues` will appear for account created events.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
## Additional Information and Links

View File

@@ -14,7 +14,7 @@ tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
:::info Important Setup Steps
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
1. Invoke the [update native change detection configuration](https://developer.sailpoint.com/docs/api/beta/put-native-change-detection-config) for each source you want to receive events for NCD.
2. Configure the NCD options on the source in the source configuration UI.
@@ -38,7 +38,7 @@ flowchart TD
</div>
This event trigger can be used to immediately notify interested parties and remediate accounts that are deleted directly on the source. Some examples of how this trigger can be used are as follows:
This event trigger can be used to immediately notify interested parties and remediate accounts that are deleted directly on the source. Some examples of how this trigger can be used are as follows:
- Notify the identity's manager and the source owner of the deleted account
@@ -46,129 +46,126 @@ This is an example input from this trigger:
```json
{
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"name": "Letty Wilson",
"alias": "Letty.Wilson",
"id": "2c91808978eb9fab0178fb8ca6d308fb",
"type": "IDENTITY",
"email": "letty.wilson@sample_email.com"
},
"singleValueAttributeChanges": [{
"newValue": null,
"name": "cn",
"oldValue": "Letty Wilson"
},
{
"newValue": null,
"name": "displayName",
"oldValue": "Letty Wilson"
},
{
"newValue": null,
"name": "distinguishedName",
"oldValue": "CN=Letty Wilson,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"entitlementChanges": [{
"removed": [{
"owner": {
"id": "2c91808978eb9fab0178fb8ca9280919",
"name": "Gregory Brooks",
"type": "IDENTITY"
},
"name": "ProductionManagement",
"id": "2c91808778eb9fa30178fb9482f00c60",
"value": "CN=ProductionManagement,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "Employees",
"id": "2c91808378eb9fa30178fb94818e0af8",
"value": "CN=Employees,OU=BirthRight,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "WindowsAdministration",
"id": "2c91808378eb9fa30178fb9481c30b02",
"value": "CN=WindowsAdministration,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"added": [],
"attributeName": "memberOf"
}],
"eventType": "ACCOUNT_DELETED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
},
"accountChangeTypes": [
"ATTRIBUTES_CHANGED",
"ENTITLEMENTS_REMOVED"
],
"multiValueAttributeChanges": [{
"removedValues": [
"top",
"person",
"organizationalPerson",
"user"
],
"addedValues": [],
"name": "objectClass"
},
{
"removedValues": [
"Normal User Account",
"Password Cannot Expire",
"User Account is Disabled"
],
"addedValues": [],
"name": "accountFlags"
}
],
"account": {
"name": "letty.wilson",
"id": "6805a47c09cc4dfca9083f1ce84552ee",
"type": "ACCOUNT",
"uuid": "{3c096158-9188-46f4-bb13-20ef9daafa7f}",
"correlated": true,
"nativeIdentity": "CN=Letty Wilson,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"name": "Letty Wilson",
"alias": "Letty.Wilson",
"id": "2c91808978eb9fab0178fb8ca6d308fb",
"type": "IDENTITY",
"email": "letty.wilson@sample_email.com"
},
"singleValueAttributeChanges": [
{
"newValue": null,
"name": "cn",
"oldValue": "Letty Wilson"
},
{
"newValue": null,
"name": "displayName",
"oldValue": "Letty Wilson"
},
{
"newValue": null,
"name": "distinguishedName",
"oldValue": "CN=Letty Wilson,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"entitlementChanges": [
{
"removed": [
{
"owner": {
"id": "2c91808978eb9fab0178fb8ca9280919",
"name": "Gregory Brooks",
"type": "IDENTITY"
},
"name": "ProductionManagement",
"id": "2c91808778eb9fa30178fb9482f00c60",
"value": "CN=ProductionManagement,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "Employees",
"id": "2c91808378eb9fa30178fb94818e0af8",
"value": "CN=Employees,OU=BirthRight,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
},
{
"owner": null,
"name": "WindowsAdministration",
"id": "2c91808378eb9fa30178fb9481c30b02",
"value": "CN=WindowsAdministration,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"added": [],
"attributeName": "memberOf"
}
],
"eventType": "ACCOUNT_DELETED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
},
"accountChangeTypes": ["ATTRIBUTES_CHANGED", "ENTITLEMENTS_REMOVED"],
"multiValueAttributeChanges": [
{
"removedValues": ["top", "person", "organizationalPerson", "user"],
"addedValues": [],
"name": "objectClass"
},
{
"removedValues": [
"Normal User Account",
"Password Cannot Expire",
"User Account is Disabled"
],
"addedValues": [],
"name": "accountFlags"
}
],
"account": {
"name": "letty.wilson",
"id": "6805a47c09cc4dfca9083f1ce84552ee",
"type": "ACCOUNT",
"uuid": "{3c096158-9188-46f4-bb13-20ef9daafa7f}",
"correlated": true,
"nativeIdentity": "CN=Letty Wilson,OU=Austin,OU=Americas,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
}
```
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account deleted event, all aggregated account attributes will be listed, and their `newValue` will be null.
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account deleted event, all aggregated account attributes will be listed, and their `newValue` will be null.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `entitlementChanges` Contains a list of entitlements that have been aggregated with the account. the `added` list will always be empty for an account deleted event.
- `entitlementChanges` Contains a list of entitlements that have been aggregated with the account. the `added` list will always be empty for an account deleted event.
- `eventType` Will always be `ACCOUNT_DELETED` for account deleted events.
- `source` The source where this account originated from.
- `accountChangeTypes` A list of change types you can expect to see in the event input.
- Possible values are `ATTRIBUTES_CHANGED` and `ENTITLEMENTS_REMOVED`.
- The above example lists both change types since both attributes and entitlements were removed. If an event payload only contains attributes removed, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- `multiValueAttributeChanges` List of multivalued attributes that were aggregated with the account. Only `removedValues` will appear for account deleted events.
- The above example lists both change types since both attributes and entitlements were removed. If an event payload only contains attributes removed, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- `multiValueAttributeChanges` List of multivalued attributes that were aggregated with the account. Only `removedValues` will appear for account deleted events.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
## Additional Information and Links

View File

@@ -14,7 +14,7 @@ tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
:::info Important Setup Steps
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
You must have at least one source configured for Native Change Detection (NCD) before you will receive events from this trigger. There are two ways you can configure a source for NCD:
1. Invoke the [update native change detection configuration](https://developer.sailpoint.com/docs/api/beta/put-native-change-detection-config) for each source you want to receive events for NCD.
2. Configure the NCD options on the source in the source configuration UI.
@@ -38,7 +38,7 @@ flowchart TD
</div>
This event trigger can be used to immediately notify interested parties and remediate accounts that are updated directly on the source. Some examples of how this trigger can be used are as follows:
This event trigger can be used to immediately notify interested parties and remediate accounts that are updated directly on the source. Some examples of how this trigger can be used are as follows:
- Notify the identity's manager and the source owner of the new account
- Create a micro-certification for the identity to review their new account attributes and entitlements
@@ -48,82 +48,90 @@ This is an example input from this trigger:
```json
{
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"name": "Ann English",
"alias": "Ann.English",
"id": "2c91808978eb9fab0178fb8ca6d308fb",
"type": "IDENTITY",
"email": "ann.english@sample_email.com"
},
"singleValueAttributeChanges": [{
"newValue": "Call Center Representative",
"name": "title",
"oldValue": "Call Center Manager"
}],
"entitlementChanges": [{
"removed": [{
"owner": null,
"name": "AccountsReceivable",
"id": "d0470502d73d4c2e8c7543c712f518ca",
"value": "CN=AccountsReceivable,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}],
"added": [{
"owner": null,
"name": "Accounts Payable",
"id": "2c91808978eb9fab0178fb9482620b71",
"value": "CN=AccountsPayable,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}],
"attributeName": "memberOf"
}],
"eventType": "ACCOUNT_UPDATED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
},
"accountChangeTypes": [
"ATTRIBUTES_CHANGED",
"ENTITLEMENTS_ADDED",
"ENTITLEMENTS_REMOVED"
],
"multiValueAttributeChanges": [{
"removedValues": [],
"addedValues": [
"User Account is Disabled"
],
"name": "accountFlags"
}],
"account": {
"name": "Ann.English",
"id": "2c91808378eb9fa30178fb9481a30afa",
"type": "ACCOUNT",
"uuid": "{08ee6c6d-7d02-4978-9417-d92ba6a5ed50}",
"correlated": true,
"nativeIdentity": "CN=Ann English,OU=Call Center,OU=AI,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
"identity": {
"manager": {
"name": "Martena Heath",
"id": "2c91808378eb9fa30178fb8caf90097f",
"type": "IDENTITY",
"email": "martena.heath@sample_email.com"
},
"name": "Ann English",
"alias": "Ann.English",
"id": "2c91808978eb9fab0178fb8ca6d308fb",
"type": "IDENTITY",
"email": "ann.english@sample_email.com"
},
"singleValueAttributeChanges": [
{
"newValue": "Call Center Representative",
"name": "title",
"oldValue": "Call Center Manager"
}
],
"entitlementChanges": [
{
"removed": [
{
"owner": null,
"name": "AccountsReceivable",
"id": "d0470502d73d4c2e8c7543c712f518ca",
"value": "CN=AccountsReceivable,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"added": [
{
"owner": null,
"name": "Accounts Payable",
"id": "2c91808978eb9fab0178fb9482620b71",
"value": "CN=AccountsPayable,OU=Groups,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
],
"attributeName": "memberOf"
}
],
"eventType": "ACCOUNT_UPDATED",
"source": {
"owner": {
"name": "Aaron Andrew",
"id": "2c9180867a7c46d0017a7ca099d50531",
"type": "IDENTITY",
"email": "aaron.andrew@sample_email.com"
},
"name": "Active Directory",
"alias": "Active Directory [source]",
"id": "2c91808a78efc63e0178fb8624b248c5",
"type": "SOURCE",
"governanceGroup": {
"id": "fd0d1393-35fb-47d8-9809-0e385b73f25e",
"name": "Active Directory Owners",
"type": "GOVERNANCE_GROUP"
}
},
"accountChangeTypes": [
"ATTRIBUTES_CHANGED",
"ENTITLEMENTS_ADDED",
"ENTITLEMENTS_REMOVED"
],
"multiValueAttributeChanges": [
{
"removedValues": [],
"addedValues": ["User Account is Disabled"],
"name": "accountFlags"
}
],
"account": {
"name": "Ann.English",
"id": "2c91808378eb9fa30178fb9481a30afa",
"type": "ACCOUNT",
"uuid": "{08ee6c6d-7d02-4978-9417-d92ba6a5ed50}",
"correlated": true,
"nativeIdentity": "CN=Ann English,OU=Call Center,OU=AI,OU=Demo,DC=seri,DC=sailpointdemo,DC=com"
}
}
```
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account updated event, only account attributes that were modified will be listed, and their `oldValue` will contain the previous value before the change.
- `identity` The identity correlated to this account. If `account.correlated` is `false`, then this will be a system generated identity, not a real identity. For uncorrelated accounts, this system generated identity can be used to revoke entitlements on the account, or in any other API request that requires an identity ID.
- `singleValueAttributeChanges` Contains a list of account attributes that have changed. During an account updated event, only account attributes that were modified will be listed, and their `oldValue` will contain the previous value before the change.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `entitlementChanges` Contains a list of entitlements that have been added and/or removed on the account.
@@ -131,11 +139,11 @@ This is an example input from this trigger:
- `source` The source where this account originated from.
- `accountChangeTypes` A list of change types you can expect to see in the event input.
- Possible values are `ATTRIBUTES_CHANGED`, `ENTITLEMENTS_ADDED`, and `ENTITLEMENTS_REMOVED`.
- The above example lists all three change types since attributes were changed and entitlements were added and removed. If an event payload only contains changed attributes, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- The above example lists all three change types since attributes were changed and entitlements were added and removed. If an event payload only contains changed attributes, then this list will only contain the `ATTRIBUTES_CHANGED` value. This can be useful when filtering events based on change types, or quickly checking what types of objects changed in the account before continuing to process the input.
- `multiValueAttributeChanges` List of multivalued attributes that were added and/or removed on the account.
- it will include ALL account attributes if the config is `"allNonEntitlementAttributes": true`
- it will include the enumerated list of attributes contained in `"selectedNonEntitlementAttributes": []`
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
- `account` The details of the account as it appears in Identity Security Cloud. This information can be used to query the account API for more information.
## Additional Information and Links

View File

@@ -4,8 +4,7 @@ title: Outlier Detected
pagination_label: Outlier Detected
sidebar_label: Outlier Detected
sidebar_class_name: outlierDetected
keywords:
['event', 'trigger', 'outlier', 'detected']
keywords: ['event', 'trigger', 'outlier', 'detected']
description: Fires after an identity was detected as an outlier.
slug: /extensibility/event-triggers/triggers/outlier-detected
tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
@@ -13,7 +12,7 @@ tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']
## Event Context
The 'Outlier Detected' event trigger notifies subscribed applications of any identities that have unusual access when compared to their peers. Outliers are calculated daily, and any identities that are flagged as outliers will be sent to subscribers of the trigger.
The 'Outlier Detected' event trigger notifies subscribed applications of any identities that have unusual access when compared to their peers. Outliers are calculated daily, and any identities that are flagged as outliers will be sent to subscribers of the trigger.
This is an example input from this trigger:
@@ -30,7 +29,7 @@ This is an example input from this trigger:
```
- `outlierType` - Only `LOW_SIMILARITY` is supported at this time.
- `score` - The range is `0.0` to `1.0`. The higher the score, the more likely the identity is an outlier.
- `score` - The range is `0.0` to `1.0`. The higher the score, the more likely the identity is an outlier.
## Prerequisites
@@ -42,7 +41,7 @@ Before consuming this event trigger, the following prerequesites must be met:
:::caution Important
If you don't meet the prerequisites and you subscribe to this event trigger, you will not receive any events. The prerequisites must be met in order to receive events.
If you don't meet the prerequisites and you subscribe to this event trigger, you will not receive any events. The prerequisites must be met in order to receive events.
:::

View File

@@ -4,7 +4,8 @@ title: Scheduled Search
pagination_label: Scheduled Search
sidebar_label: Scheduled Search
sidebar_class_name: scheduledSearch
keywords: ['event', 'trigger', 'saved', 'scheduled', 'search', 'complete', 'available']
keywords:
['event', 'trigger', 'saved', 'scheduled', 'search', 'complete', 'available']
description: Fires after a scheduled search completes.
slug: /extensibility/event-triggers/triggers/scheduled-search
tags: ['Event Triggers', 'Available Event Triggers', 'Fire and Forget']

View File

@@ -33,7 +33,7 @@ After accounts are aggregated and the identity refresh process finds an identity
:::info
Identity Security Cloud will **hide** an identity from the identity list in the UI when the authoritative account is removed. This does not necessarily mean that the identity has been deleted. The identity will only be deleted when the above criteria are met. The deletion task run each night, so there will be a delay from when the criteria are met to when the identity will actually be deleted.
Identity Security Cloud will **hide** an identity from the identity list in the UI when the authoritative account is removed. This does not necessarily mean that the identity has been deleted. The identity will only be deleted when the above criteria are met. The deletion task run each night, so there will be a delay from when the criteria are met to when the identity will actually be deleted.
:::

View File

@@ -77,7 +77,7 @@ Operators provide more options to filter JSON structures.
### Developing Filters
Developing a filter can be faster when you use a tool like an online [JSONpath editor](https://www.javainuse.com/jsonpath). These tools can provide quick feedback on your filter, allowing you to focus on the exact filter expression you want before testing it on a trigger. Just paste an example of your event trigger input and start crafting an expression to see its result.
Developing a filter can be faster when you use a tool like an online [JSONpath editor](https://www.javainuse.com/jsonpath). These tools can provide quick feedback on your filter, allowing you to focus on the exact filter expression you want before testing it on a trigger. Just paste an example of your event trigger input and start crafting an expression to see its result.
![JSONPath editor](./img/jsonpath-editor.png)

View File

@@ -1,5 +1,5 @@
{
"customProps": {
"description": "Advanced configurations with custom logic."
}
"customProps": {
"description": "Advanced configurations with custom logic."
}
}

View File

@@ -19,24 +19,24 @@ This rule generates complex account attribute values during provisioning, e.g. w
In the following example, the template is `${firstname}.${lastname}${uniqueCounter}`, which is pulled in by the `Create Unique LDAP Attribute` rule and used to replace the `firstname`, `lastname` and `uniqueCounter` placeholders.
```json
{
"name": "userName",
"transform": {
"type": "rule",
"attributes": {
"name": "Create Unique LDAP Attribute"
}
},
"attributes": {
"template": "${firstname}.${lastname}${uniqueCounter}",
"cloudMaxUniqueChecks": "50",
"cloudMaxSize": "20",
"cloudRequired": "true"
},
"isRequired": false,
"type": "string",
"isMultiValued": false
{
"name": "userName",
"transform": {
"type": "rule",
"attributes": {
"name": "Create Unique LDAP Attribute"
}
},
"attributes": {
"template": "${firstname}.${lastname}${uniqueCounter}",
"cloudMaxUniqueChecks": "50",
"cloudMaxSize": "20",
"cloudRequired": "true"
},
"isRequired": false,
"type": "string",
"isMultiValued": false
}
```
## Execution

View File

@@ -16,9 +16,9 @@ Use this rule to modify a provisioning plan as provisioning is sent out. Do not
These are some examples of when to use this rule:
* Disable account and remove groups during provisioning when the lifecycle state of an identity is set to terminated
* Remove or add permissions when certain attribute criteria are met
* Move users to a specific organizational unit (OU) in Active Directory based upon attribute criteria
- Disable account and remove groups during provisioning when the lifecycle state of an identity is set to terminated
- Remove or add permissions when certain attribute criteria are met
- Move users to a specific organizational unit (OU) in Active Directory based upon attribute criteria
## Execution

View File

@@ -16,9 +16,7 @@ tags: ['Rules']
This rule manipulates raw input data provided by the rows and columns in a file and builds a map from the incoming data. Use this rule to create a new value by combining two columns together. For example, if one column was `access` and another `permissions` you could combine these together to create an entitlement `admin-read`.
:::info
This rule runs in the cloud, but it's really a connector rule because it executes against the DelimitedFileConnector.
:::
:::info This rule runs in the cloud, but it's really a connector rule because it executes against the DelimitedFileConnector. :::
## Execution

View File

@@ -16,9 +16,9 @@ This rule calculates a manager relationship between identities.
Use this rule to correlate an identity's manager for the following scenarios:
* The authoritative source has multiple accounts for an identity and you must pick the manager data from the `active` account.
* You need to do a lookup from an employee number to other data.
* The identity changes types, for example, from consultant to employee with the manager coming from a different authoritative source.
- The authoritative source has multiple accounts for an identity and you must pick the manager data from the `active` account.
- You need to do a lookup from an employee number to other data.
- The identity changes types, for example, from consultant to employee with the manager coming from a different authoritative source.
The manager correlation rule runs before configured manager account correlation.

View File

@@ -131,16 +131,12 @@ The value key is a list. All available AfterCreate, AfterModify, BeforeCreate, a
```json
[
  {
       "op": "add",
       "path": "/connectorAttributes/nativeRules",
       "value": [
           "Example Rule 1",
           "Example Rule 2"
      ]
  }
{
"op": "add",
"path": "/connectorAttributes/nativeRules",
"value": ["Example Rule 1", "Example Rule 2"]
}
]
```
### Correlation Rule

View File

@@ -290,8 +290,7 @@ public boolean isUnique ( String username ) throws GeneralException {
### Invoke `generateUsername()` With the Identity's First and Last Name
This is the final part of the rule. Call the `generateUsername()` function, passing in the identity's first and last name.
The `identity` variable is already initialized and included as input to our attribute generator rule.
This is the final part of the rule. Call the `generateUsername()` function, passing in the identity's first and last name. The `identity` variable is already initialized and included as input to our attribute generator rule.
```java
return generateUsername( identity.getFirstname(), identity.getLastname() );

View File

@@ -1,5 +1,5 @@
{
"customProps": {
"description": "Modify attribute data without code."
}
"customProps": {
"description": "Modify attribute data without code."
}
}

View File

@@ -56,7 +56,10 @@ You must use a `firstValid`. If the identity does not have a manager, `getManage
{
"type": "firstValid",
"attributes": {
"values": ["$identity.getManager().getStringAttribute('country')", "no manager exists"]
"values": [
"$identity.getManager().getStringAttribute('country')",
"no manager exists"
]
}
}
```

View File

@@ -38,11 +38,11 @@ This example and dates assume that the `now` keyword in the dateMath expression
:::
| id | email | first_name | last_name | end_date |
| ------ | ---------------------------- | ---------- | --------- | ---------- |
| 100010 | lewis.hamilton@sailpoint.com | Lewis | Hamilton | 2023-11-01 |
| 100011 | frank.williams@sailpoint.com | Frank | Williams | 2023-11-09 |
| 100012 | paddy.lowe@sailpoint.com | Paddy | Lowe | 2023-11-25 |
| id | email | first_name | last_name | end_date |
| --- | --- | --- | --- | --- |
| 100010 | lewis.hamilton@sailpoint.com | Lewis | Hamilton | 2023-11-01 |
| 100011 | frank.williams@sailpoint.com | Frank | Williams | 2023-11-09 |
| 100012 | paddy.lowe@sailpoint.com | Paddy | Lowe | 2023-11-25 |
| 100013 | keifer.sutherland@sailpoint.com | Keifer | Sutherland | 2023-12-25 |
### Check whether the end date was in the past
@@ -371,9 +371,9 @@ This is the logic within the static transform:
These are the results of the transform on each identity, given that `now` returns 2023-11-07:
| id | email | first_name | last_name | end_date | result |
| ------ | ---------------------------- | ---------- | --------- | ---------- | ------ |
| 100010 | lewis.hamilton@sailpoint.com | Lewis | Hamilton | 2023-11-01 | terminated |
| 100011 | frank.williams@sailpoint.com | Frank | Williams | 2023-11-09 | inactivePendingTermination |
| 100012 | paddy.lowe@sailpoint.com | Paddy | Lowe | 2023-11-25 | activePendingTermination |
| id | email | first_name | last_name | end_date | result |
| --- | --- | --- | --- | --- | --- |
| 100010 | lewis.hamilton@sailpoint.com | Lewis | Hamilton | 2023-11-01 | terminated |
| 100011 | frank.williams@sailpoint.com | Frank | Williams | 2023-11-09 | inactivePendingTermination |
| 100012 | paddy.lowe@sailpoint.com | Paddy | Lowe | 2023-11-25 | activePendingTermination |
| 100013 | keifer.sutherland@sailpoint.com | Keifer | Sutherland | 2023-12-25 | active |

View File

@@ -133,9 +133,7 @@ This is an example create provisioning policy response for a source:
This transform concatenates the identityAttributes `firstName`, `lastName`, the two digit month of the `hireDate` and the static string `Rt4e!` to form a temporaryPassword.
:::caution
You must use the `identityAttribute` type when you're writing transforms in provisioning policies. The `accountAttribute` type won't work during provisioning.
:::
:::caution You must use the `identityAttribute` type when you're writing transforms in provisioning policies. The `accountAttribute` type won't work during provisioning. :::
```json
{

View File

@@ -240,6 +240,7 @@ Account attribute transforms are configured on the account create profiles. They
These transforms are configured separately from the transforms applied via the identity profile mappings tab.
:::
#### Configuration
These can be configured in Identity Security Cloud by going to **Admin** > **Sources** > (A Source) > **Accounts** (tab) > **Create Account**.

View File

@@ -147,36 +147,36 @@ When you are mapping values like a username, focus on primary accounts from a pa
To determine whether an identity is a member of an entitlement.
- `input` contains the condition to be evaluated (is member of an entitlement or not). If the user doesn't meet the below conditions, the `firstValid` retuns "FALSE".
- `sourceName` is "Active Directory" because that is the source this data is coming from.
- `attributeName` is "sAMAccountName" because you are mapping the username of the user.
- `accountPropertyFilter` is filtering accounts that are members of an entitlement that contains "All AD Users-rshwart".
- `sourceName` is "Active Directory" because that is the source this data is coming from.
- `attributeName` is "sAMAccountName" because you are mapping the username of the user.
- `accountPropertyFilter` is filtering accounts that are members of an entitlement that contains "All AD Users-rshwart".
- `table` contains the boolean results: FALSE or TRUE (default).
```json
{
"attributes": {
"input": {
"attributes": {
"input": {
"attributes": {
"values": [
{
"attributes": {
"values": [
{
"attributes": {
"accountPropertyFilter": "(memberOf.contains(\"All AD Users-rshwart\"))",
"attributeName": "sAMAccountName",
"sourceName": "Active Directory"
},
"type": "accountAttribute"
},
"FALSE"
]
"accountPropertyFilter": "(memberOf.contains(\"All AD Users-rshwart\"))",
"attributeName": "sAMAccountName",
"sourceName": "Active Directory"
},
"type": "firstValid"
},
"table": {
"FALSE": "FALSE",
"default": "TRUE"
}
"type": "accountAttribute"
},
"FALSE"
]
},
"type": "firstValid"
},
"id": "Contains IT Access",
"type": "lookup"
"table": {
"FALSE": "FALSE",
"default": "TRUE"
}
},
"id": "Contains IT Access",
"type": "lookup"
}
```

View File

@@ -55,9 +55,7 @@ The date format transform takes whatever value provided as the input, parses the
- If no outputFormat is provided, the transform assumes that it is in [ISO8601 format](https://en.wikipedia.org/wiki/ISO_8601).
- **input** - This is an optional attribute that can explicitly define the input data passed into the transform logic. If no input is provided, the transform takes its input from the source and attribute combination configured with the UI.
:::note Important
This transform does not currently support the "now" keyword as an input value.
:::
:::note Important This transform does not currently support the "now" keyword as an input value. :::
## Examples

View File

@@ -16,7 +16,6 @@ Use the date math transform to add, subtract, and round components of a timestam
The output format for the DateMath transform is "yyyy-MM-dd'T'HH:mm". When you use this transform inside another transform (e.g., [dateCompare](./date-compare.md)), make sure to convert to [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) first.
:::note Other Considerations
- The input datetime value must always be in [ISO8601 format](https://en.wikipedia.org/wiki/ISO_8601), in UTC time zone:
@@ -90,6 +89,7 @@ Some examples of expressions are:
- `true` indicates the transform rounds up (i.e., truncate the fractional date/time component indicated and then add one unit of that component).
- `false` indicates the transform rounds down (i.e., truncate the fractional date/time component indicated).
- **input** - This is an optional attribute that can explicitly define the input data passed into the transform logic. If no input is provided, the transform takes its input from the source and attribute combination configured with the UI.
## Examples

View File

@@ -21,7 +21,7 @@ The following are examples of diacritical marks:
> - Ň
> - Ŵ
The decomposeDiacriticalMarks transform uses the [Normalizer library](https://docs.oracle.com/javase/7/docs/api/java/text/Normalizer.html) to decompose the diacritical marks. It specifically uses the Normalization Form KD (NFKD), as described in Sections 3.6, 3.10, and 3.11 of the Unicode Standard, also summarized under [Annex 4: Decomposition](https://www.unicode.org/reports/tr15/tr15-23.html#Decomposition).
The decomposeDiacriticalMarks transform uses the [Normalizer library](https://docs.oracle.com/javase/7/docs/api/java/text/Normalizer.html) to decompose the diacritical marks. It specifically uses the Normalization Form KD (NFKD), as described in Sections 3.6, 3.10, and 3.11 of the Unicode Standard, also summarized under [Annex 4: Decomposition](https://www.unicode.org/reports/tr15/tr15-23.html#Decomposition).
After decomposition, the transform uses a [Regex Replace](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html) to replace all diacritical marks by using the `InCombiningDiacriticalMarks` property of Unicode (ex. `replaceAll("[\\p{InCombiningDiacriticalMarks}]", "")`).

View File

@@ -12,6 +12,7 @@ tags: ['guides']
---
## Overview
Identity Security Cloud (ISC) has all sorts of potential specific solutions you can implement as long as you know how. These specific solutions may either not fall into one of the extensibility, connectivity, tools, or reporting categories, or they may fall into multiple categories. Read these guides to learn how to implement these specific solutions.
```mdx-code-block
@@ -22,6 +23,7 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
```
## Discuss
The most valuable resource for ISC developers is the SailPoint Developer Community itself, where ISC users and experts all over the world come together to ask questions and provide solutions.
To learn more about these ISC topics and discuss them with SailPoint Developer Community members, go to the [SailPoint Developer Community Forum](https://developer.sailpoint.com/discuss/c/isc/6).

View File

@@ -12,6 +12,7 @@ tags: ['AccessProfileRequestManagement']
---
## Overview
In Identity Security Cloud, [access profiles](https://documentation.sailpoint.com/saas/help/access/access-profiles.html) are groups of [entitlements](https://documentation.sailpoint.com/saas/help/access/entitlements.html), which represent access rights on [sources](https://documentation.sailpoint.com/saas/help/sources/index.html). By default, all access profiles are marked as requestable. This means that an organization's users can submit [access requests](https://documentation.sailpoint.com/saas/help/requests/index.html) for the access profiles in the Identity Security Cloud [Request Center](https://documentation.sailpoint.com/saas/user-help/requests/request_center.html), where all access profiles are listed.
You can disable requests for access profiles to prevent users from gaining inappropriate or undesired access. In the UI, you can edit the [individual access profile](https://documentation.sailpoint.com/saas/help/requests/config_ap_roles.html#configuring-access-profiles-for-requests) to disable requests for the access profile. You can also use the [PATCH Access Profile endpoint](https://developer.sailpoint.com/docs/api/v3/patch-access-profile) to mark the individual access profile as non-requestable.
@@ -19,22 +20,29 @@ You can disable requests for access profiles to prevent users from gaining inapp
You may have many access profiles that you want to disable requests for, and you don't want one to get overlooked and then inappropriately accessed. There are three different processes you can use to ensure that you have disabled requests for all access profiles that aren't currently associated with [applications](https://documentation.sailpoint.com/saas/help/common/app-config.html) configured for access requests. Read this guide to learn how to perform these processes.
## Disable requests for individual access profiles with the UI
Follow these steps to use the Identity Security Cloud UI to individually disable requests for all access profiles that aren't currently associated with applications:
1. Identify the access profiles that are associated with applications configured for access requests. Create a list of these associated access profiles.
- Go to **Admin > Applications** and open each application you use for access requests. These applications have both 'Visible in the Request Center' and 'Allow Access Requests' marked on the 'Configuration' tab.
- Go to the application's 'Access' tab and capture the names of each application's associated access profiles, recording them in your list of access profiles.
2. Edit each access profile that is **not** in your list to disable access requests.
- Go to **Admin > Access > Access Profiles** to view a list of all access profiles.
- For each access profile that isn't in your list of those associated with applications configured for access requests, select 'Edit', go to the 'Access Requests' tab, and disable 'Allow Access Requests'. Then save your changes.
Once you have performed this process, all the access profiles that aren't currently associated with applications will no longer be requestable.
## Disable requests for individual access profiles with the API
Follow these steps to use two API endpoints to individually disable access requests for all access profiles that aren't currently associated with applications:
1. Use the [Search endpoint](https://developer.sailpoint.com/docs/api/v3/search-post) to identify the access profiles that are **not** associated with applications configured for access requests. Sending the following query will return a list of these unassociated access profiles.
- Provide this request body. It will return all access profiles that have a null or empty `apps` list.
```
{
"queryDsl": {
@@ -62,9 +70,13 @@ Follow these steps to use two API endpoints to individually disable access reque
]
}
```
- The response body will include all the details of each unassociated access profile. Extract the `id` for each access profile returned.
2. Use the [PATCH Access Profile endpoint](https://developer.sailpoint.com/docs/api/v3/patch-access-profile) and provide the unassociated access profile's `id` to update the specified access profile's `requestable` field.
- Provide this request body. It will use the `replace` operation to update the value in the specified access profile's `requestable` path to `false`.
```
[
{
@@ -74,14 +86,19 @@ Follow these steps to use two API endpoints to individually disable access reque
}
]
```
- After a successful PATCH update, the response body will include all the specified access profile's details, including the updated `false` value in the `requestable` path.
Once you have performed this process for each of the unassociated access profiles returned in your search, all the access profiles that aren't associated with applications will no longer be requestable.
## Bulk disable requests for access profiles with the API
Follow these steps to use two API endpoints to bulk disable access requests for all access profiles that aren't currently associated with applications:
1. Use the [Search endpoint](https://developer.sailpoint.com/docs/api/v3/search-post) to identify the access profiles that are **not** associated with applications configured for access requests. Sending the following query will return a list of these unassociated access profiles.
- Provide this request body. It will return all access profiles that have a null or empty `apps` list.
```
{
"queryDsl": {
@@ -109,9 +126,13 @@ Follow these steps to use two API endpoints to bulk disable access requests for
]
}
```
- The response body will include all the details of each unassociated access profile. Extract the `id` for each access profile returned.
2. Use the [Update Requestability for Access Profiles endpoint](https://developer.sailpoint.com/docs/api/beta/update-access-profiles-in-bulk) and provide every unassociated access profile's `id`, along with the updated values for their `requestable` fields.
- Provide this request body. It can bulk update all the access profiles you specify - you just need to specify each access profile's `id` and the `requestable` value you want for the access profile.
```
[
{
@@ -124,6 +145,7 @@ Follow these steps to use two API endpoints to bulk disable access requests for
}
]
```
- After a successful update, the response body will include the `id` and new `requestable` values for all the updated access profiles, along with confirmations that they were successfully updated.
Once you have performed this process for all the unassociated access profiles returned in your search, all the access profiles that aren't associated with applications will no longer be requestable.

View File

@@ -5,10 +5,10 @@ pagination_label: IP Address Allow List
sidebar_label: IP Address Allow List
sidebar_position: 2
sidebar_class_name: allowList
keywords: ['connectivity', 'connectors', 'workflows', 'allowlist','ip address']
keywords: ['connectivity', 'connectors', 'workflows', 'allowlist', 'ip address']
description: Create an IP Address Allow List.
slug: /guides/ip-address-allow-list
tags: ['Connectivity', 'connectors', 'workflows', 'allowlist','ip address']
tags: ['Connectivity', 'connectors', 'workflows', 'allowlist', 'ip address']
---
## Overview
@@ -87,11 +87,11 @@ https://files.accessiq.sailpoint.com/network/us-east-1/source_ips.yaml
which will result in a file similar to the following:
```yaml
"region": "us-east-1"
"source_ips":
- "52.204.100.58/32"
- "52.205.92.24/32"
- "52.206.146.115/32"
'region': 'us-east-1'
'source_ips':
- '52.204.100.58/32'
- '52.205.92.24/32'
- '52.206.146.115/32'
```
These IP Address ranges can now be used as an allow list to permit any call from your Identity Security Cloud tenant to access your internal network.

View File

@@ -73,7 +73,7 @@ Click 'Save' and then 'Apply Changes' to create the first identity from the serv
![invite](./img/service-accounts/invite.png)
If you have not received the invite, check your junk folder or deleted folder because the invite may have been automatically filtered by your email provider. Once you receive the invite, follow the steps to register your service account. Once your service account user is registered, log in as the service account with the password you created for it.
If you have not received the invite, check your junk folder or deleted folder because the invite may have been automatically filtered by your email provider. Once you receive the invite, follow the steps to register your service account. Once your service account user is registered, log in as the service account with the password you created for it.
![login](./img/service-accounts/login.png)

View File

@@ -8,7 +8,7 @@ sidebar_class_name: plugin_developer_guide_appendix_migration
keywords: ['plugin']
description: Migration from IdentityIQ 7.0 to 7.1
slug: /iiq/plugin-developer-guide/appendix-migration
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Appendix A - Plugin Migration 7.0 to 7.1
@@ -19,40 +19,40 @@ The 7.1 Plugin Framework provides a dynamic, plugin-specific class loader. It al
The object model for plugins has also changed somewhat. This table maps the old (7.0) plugin object model to the new (7.1+) plugin object model:
|**7.0 Object Model**|**7.1 Object Model**|
| --- | --- |
|uniqueName|name|
|displayName|displayName|
|enabled|disabled|
|installationDate|installDate|
|version|version|
|order|position|
|vendorName|n/a|
|vendorID|n/a|
|visible|n/a|
|allowDisable|n/a|
|allowUninstall|n/a|
|minUpgradeableVersion|minUpgradeableVersion|
|minFrameworkVersion|minSystemVersion|
|maxFrameworkVersion|maxSystemVersion|
|installationMode|n/a|
|configurationSettings|attributes|
|certificationLevel|certificationLevel|
|pluginAccessRight|rightRequired|
| **7.0 Object Model** | **7.1 Object Model** |
| --------------------- | --------------------- |
| uniqueName | name |
| displayName | displayName |
| enabled | disabled |
| installationDate | installDate |
| version | version |
| order | position |
| vendorName | n/a |
| vendorID | n/a |
| visible | n/a |
| allowDisable | n/a |
| allowUninstall | n/a |
| minUpgradeableVersion | minUpgradeableVersion |
| minFrameworkVersion | minSystemVersion |
| maxFrameworkVersion | maxSystemVersion |
| installationMode | n/a |
| configurationSettings | attributes |
| certificationLevel | certificationLevel |
| pluginAccessRight | rightRequired |
Gone in 7.1 is the idea of a plugin configuration model, and a snippet model. Instead, these elements have been rolled into the 'PluginAttributes' map that appears in the 'manifest.xml' file required by each plugin. The 'fullPage' object is now a single entry in the attributes mapping, which only holds the title of the 'fullPage'. Snippets move into a 'List' entry key in the attributes map. For each snippet entry in the 'List', implementers can define a regular expression 'regexPattern' to match against, the 'rightRequired' to see the snippet, and then a list of <Scripts/> and <StyleSheets/> that determine the look and action of the snippet.
Gone in 7.1 is the idea of a plugin configuration model, and a snippet model. Instead, these elements have been rolled into the 'PluginAttributes' map that appears in the 'manifest.xml' file required by each plugin. The 'fullPage' object is now a single entry in the attributes mapping, which only holds the title of the 'fullPage'. Snippets move into a 'List' entry key in the attributes map. For each snippet entry in the 'List', implementers can define a regular expression 'regexPattern' to match against, the 'rightRequired' to see the snippet, and then a list of <Scripts/> and <StyleSheets/> that determine the look and action of the snippet.
The most readily apparent change in plugin definition going from 7.0 to 7.1 is the location of each setting's plugins. Previously, developers could define a URL to a settings page ('settingsPageTemplateURL') that they could completely customize. In 7.1, in order to support future portability and support, the settings page has been removed, and individual plugin settings have been internalized to the 'manifest.xm'l file. These settings are now defined in a 'Settings' list in the 'PluginAttributes' map. Each element of the list is a 'Setting', which can have the following defined:
The most readily apparent change in plugin definition going from 7.0 to 7.1 is the location of each setting's plugins. Previously, developers could define a URL to a settings page ('settingsPageTemplateURL') that they could completely customize. In 7.1, in order to support future portability and support, the settings page has been removed, and individual plugin settings have been internalized to the 'manifest.xm'l file. These settings are now defined in a 'Settings' list in the 'PluginAttributes' map. Each element of the list is a 'Setting', which can have the following defined:
|Attribute Name|Description|
|---|---|
|name|Name of the current setting|
|dataType|Setting type (Ex. string or int or boolean)|
|value|Value for the setting|
|label|Display label for the setting|
|helpText|Associated help text for the setting|
|allowedValues|List of allowed values for dropdown population|
|defaultValue|Default value for the setting|
| Attribute Name | Description |
| -------------- | ---------------------------------------------- |
| name | Name of the current setting |
| dataType | Setting type (Ex. string or int or boolean) |
| value | Value for the setting |
| label | Display label for the setting |
| helpText | Associated help text for the setting |
| allowedValues | List of allowed values for dropdown population |
| defaultValue | Default value for the setting |
## Convert manifest
@@ -70,7 +70,6 @@ Refactor old JAX-RS based REST service classes that extended 'sailpoint.plugin.r
Any 7.0 plugins that extended the 'AbstractPluginBackgroundService' for a background service will now need to extend 'sailpoint.server.BasePluginService'. Details on this new class are elsewhere in this document. In addition to refactoring the service class itself, care should be taken to also modify the 'ServiceDefinition' XML object. The 'implementationClass' attribute entry is now gone. Instead, the 'executor' attribute will now change from 'sailpoint.plugin.server.PluginServiceExecutor' to the actual service that used to be listed in the 'implementationClass' entry.
### Example: A prior ServiceDefinition in 7.0
```xml

View File

@@ -8,14 +8,15 @@ sidebar_class_name: plugin_developer_guide_updates
keywords: ['plugin']
description: IdentityIQ 8.0 Updates
slug: /iiq/plugin-developer-guide/updates
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Appendix B - 8.0 Updates
Version 8.0 of IdentityIQ offers a number of enhancements to plugins:
* Classes contained in a plugin can be leveraged from any area or feature of IdentityIQ where BeanShell can be used, such as rules, workflow steps, and scriptlets. Version 8.0 also provides mechanisms for limiting or blocking scripting access to plugin classes as needed, and some new IIQ console commands to support troubleshooting of plugin classes.
* Support for forms in the plugin configuration UI, giving you new ways to present complex or dynamic options in the plugin's configuration page.
* Stricter handling of executors for tasks, services, and policies, with a global configuration option allowing you to "relax" the stricter declarations for legacy plugins, to help with forward compatibility.
- Classes contained in a plugin can be leveraged from any area or feature of IdentityIQ where BeanShell can be used, such as rules, workflow steps, and scriptlets. Version 8.0 also provides mechanisms for limiting or blocking scripting access to plugin classes as needed, and some new IIQ console commands to support troubleshooting of plugin classes.
- Support for forms in the plugin configuration UI, giving you new ways to present complex or dynamic options in the plugin's configuration page.
- Stricter handling of executors for tasks, services, and policies, with a global configuration option allowing you to "relax" the stricter declarations for legacy plugins, to help with forward compatibility.
A further detailed explanation of enhancements can be found here: [IdentityIQ 8.0: Plugin Enhancements](https://community.sailpoint.com/docs/DOC-13331)

View File

@@ -8,7 +8,7 @@ sidebar_class_name: plugin_developer_guide_overview
keywords: ['plugin']
description: IdentityIQ Plugin Developer Guide Overview
slug: /iiq/plugin-developer-guide/overview
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Overview
@@ -19,7 +19,7 @@ The first iteration of the plugin framework was released as an add-on to Identit
Developing a plugin requires a fairly robust knowledge of IdentityIQ and its object model, Java, JavaScript, CSS, and SQL. This document is designed to provide development guidance at a high level - it goes over what the components of a plugin are, which components are required, and how those objects interact. Language specific tutorials are beyond its scope. Throughout this document, examples will be taken and discussed from the 'TodoPlugin'.
*A quick note about plugin loading...*
_A quick note about plugin loading..._
Before getting into the structure of a plugin project and why it is important, it may be helpful to understand how a plugin is represented in IdentityIQ once installed. IdentityIQ stores the '.zip' archive file of the plugin in the IdentityIQ database in a data LONGBLOB in the 'spt_file_bucket' table. The data in the 'spt_file_bucket' table is referenced (by 'id') to an entry in the 'spt_persisted_file' table as shown below.
@@ -33,20 +33,20 @@ A plugin is defined in IdentityIQ by the 'Plugin' XML object. This object define
**Plugin Model Attributes**
|**Attribute Name**|**Description**|
| --- | --- |
|name|Unique Name of the Plugin|
|installDate|Date when plugin was installed|
|displayName|Plugin's display name|
|certificationLevel|Plugin's certification level|
|disabled|Plugin's status|
|rightRequired|SPRIGHT required for this plugin|
|position|TBD|
|version|Plugin's version|
|minSystemVersion|Minimum IdentityIQ version the plugin will run on|
|maxSystemVersion|Maximum IdentityIQ version the plugin will run on|
|attributes|List of configurable attributes|
|file|Reference to the persisted file in the database|
| **Attribute Name** | **Description** |
| ------------------ | ------------------------------------------------- |
| name | Unique Name of the Plugin |
| installDate | Date when plugin was installed |
| displayName | Plugin's display name |
| certificationLevel | Plugin's certification level |
| disabled | Plugin's status |
| rightRequired | SPRIGHT required for this plugin |
| position | TBD |
| version | Plugin's version |
| minSystemVersion | Minimum IdentityIQ version the plugin will run on |
| maxSystemVersion | Maximum IdentityIQ version the plugin will run on |
| attributes | List of configurable attributes |
| file | Reference to the persisted file in the database |
## Plugin Structure

View File

@@ -8,67 +8,67 @@ sidebar_class_name: plugin_developer_guide_manifest
keywords: ['plugin']
description: IdentityIQ Plugin Manifest File
slug: /iiq/plugin-developer-guide/manifest
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Manifest File
A plugin is defined in IdentityIQ by the 'Plugin' XML object that defines the parameters of the plugin. Features such as REST resources, snippets, settings, etc. are defined in these parameters. The 'Plugin' object is defined in the 'manifest.xml' file. This is a required artifact. The 'Todo' plugin manifest will be examined:
```xml
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Plugin PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Plugin certificationLevel="None" displayName="Todo Plugin" minSystemVersion="7.1" name="TodoPlugin" version="2.0">
<Attributes>
<Map>
<entry key="minUpgradableVersion" value="1.0" />
<entry key="fullPage">
<value>
<FullPage title="Todo List" />
</value>
</entry>
<entry key="restResources">
<value>
<List>
<String>com.acme.todo.rest.TodoResource</String>
<String>com.acme.todo.rest.FlaggedUserResource</String>
<String>com.acme.todo.rest.PageConfigResource</String>
</List>
</value>
</entry>
<entry key="serviceExecutors">
<value>
<List>
<String>com.acme.todo.server.TodoFlaggingService</String>
</List>
</value>
</entry>
<entry key="settings">
<value>
<List>
<Setting dataType="boolean" helpText="Indicates whether or not todos can be deleted" label="Delete Allowed" name="canDelete" defaultValue="true"/>
<Setting dataType="string" helpText="The default name for a todo" label="Default Name" name="defaultName" defaultValue="My Todo"/>
<Setting dataType="int" helpText="The default time in minutes for a todo" label="Default Time" name="defaultTime" defaultValue="30"/>
<Setting dataType="int" helpText="The maximum numer of active todos a user is allowed to have before being flagged" label="Max Active Todos" name="maxUntilFlagged" defaultValue="10"/>
</List>
</value>
</entry>
<entry key="snippets">
<value>
<List>
<Snippet regexPattern=".*" rightRequired="ViewTodoPluginIcon">
<Scripts>
<String>ui/js/snippets/header.js</String>
</Scripts>
<StyleSheets>
<String>ui/css/todo.css</String>
</StyleSheets>
</Snippet>
</List>
</value>
</entry>
</Map>
</Attributes>
<Attributes>
<Map>
<entry key="minUpgradableVersion" value="1.0" />
<entry key="fullPage">
<value>
<FullPage title="Todo List" />
</value>
</entry>
<entry key="restResources">
<value>
<List>
<String>com.acme.todo.rest.TodoResource</String>
<String>com.acme.todo.rest.FlaggedUserResource</String>
<String>com.acme.todo.rest.PageConfigResource</String>
</List>
</value>
</entry>
<entry key="serviceExecutors">
<value>
<List>
<String>com.acme.todo.server.TodoFlaggingService</String>
</List>
</value>
</entry>
<entry key="settings">
<value>
<List>
<Setting dataType="boolean" helpText="Indicates whether or not todos can be deleted" label="Delete Allowed" name="canDelete" defaultValue="true"/>
<Setting dataType="string" helpText="The default name for a todo" label="Default Name" name="defaultName" defaultValue="My Todo"/>
<Setting dataType="int" helpText="The default time in minutes for a todo" label="Default Time" name="defaultTime" defaultValue="30"/>
<Setting dataType="int" helpText="The maximum numer of active todos a user is allowed to have before being flagged" label="Max Active Todos" name="maxUntilFlagged" defaultValue="10"/>
</List>
</value>
</entry>
<entry key="snippets">
<value>
<List>
<Snippet regexPattern=".*" rightRequired="ViewTodoPluginIcon">
<Scripts>
<String>ui/js/snippets/header.js</String>
</Scripts>
<StyleSheets>
<String>ui/css/todo.css</String>
</StyleSheets>
</Snippet>
</List>
</value>
</entry>
</Map>
</Attributes>
</Plugin>
```
@@ -80,7 +80,6 @@ A plugin is defined in IdentityIQ by the 'Plugin' XML object that defines the pa
- **Line 28-37** - specifies the settings that are end-user configurable for this plugin.
- **Line 38-51** - lists the various snippets that can be injected into IdentityIQ pages, the match criteria, and the content and style of the snippet.
## Settings
Plugin settings are attributes that are available for the end-user/system administrator to modify as part of their installation. The example from the 'Todo' plugin has four settings available that control default values for certain elements, as well as whether or not 'Todo' entries can be deleted in the UI. Settings appear to the end user when they click the 'Configure' button for the specific plugin on the 'Plugins' dashboard.
@@ -91,61 +90,61 @@ One concept not shown in the 'Todo' plugin example, the concept of 'allowed valu
Plugin setting object can be used to represent a single setting the settings/configuration page for a Plugin. Each object is used to represent a single configurable setting on the settings page.
|Attribute Name|Description|
|---|---|
|name|Name of the current setting|
|dataType|Setting type ( Ex. string or int or boolean)|
|value|Value for the setting|
|label|Display label for the setting|
|helpText|Associated help text for the setting|
|allowedValues|List of allowed values for dropdown population|
|defaultValue|The default value for the setting|
| Attribute Name | Description |
| -------------- | ---------------------------------------------- |
| name | Name of the current setting |
| dataType | Setting type ( Ex. string or int or boolean) |
| value | Value for the setting |
| label | Display label for the setting |
| helpText | Associated help text for the setting |
| allowedValues | List of allowed values for dropdown population |
| defaultValue | The default value for the setting |
## Snippets
Snippets are small, configurable pieces of code that can be injected into the rendering of normal IdentityIQ UI pages. A snippet contains four equally important components:
|**Attribute Name**|**Description**|
| **Attribute Name** | **Description** |
| --- | --- |
|regexPattern|Regular expression pattern run against the current URL in the browser - if the URL matches the pattern, the snippet will attempt to display.|
|rightRequired|Determines the scope of users allowed to view the snippet element - this should reference an IdentityIQ 'SPRight' object.|
|scripts|List of scripts to run when a particular URL matches the `regexPattern`. Normally this will consist of injecting an element into the DOM of the page. The 'Todo' example's 'hearder.js' file uses JQuery for this purpose.|
|styleSheets|list of any css files that are required by Snippet Scripts|
| regexPattern | Regular expression pattern run against the current URL in the browser - if the URL matches the pattern, the snippet will attempt to display. |
| rightRequired | Determines the scope of users allowed to view the snippet element - this should reference an IdentityIQ 'SPRight' object. |
| scripts | List of scripts to run when a particular URL matches the `regexPattern`. Normally this will consist of injecting an element into the DOM of the page. The 'Todo' example's 'hearder.js' file uses JQuery for this purpose. |
| styleSheets | list of any css files that are required by Snippet Scripts |
The 'Todo' plugin snippet creates a new top level icon on every page of the IdentityIQ UI, which is visible to someone with the `ViewTodoPluginIcon` SPRight.
```xml
<entry key="snippets">
<value>
<List>
<Snippet regexPattern=".*" rightRequired="ViewTodoPluginIcon">
<Scripts>
<String>ui/js/snippets/header.js</String>
</Scripts>
<StyleSheets>
<String>ui/css/todo.css</String>
</StyleSheets>
</Snippet>
</List>
</value>
</entry>
```xml
<entry key="snippets">
<value>
<List>
<Snippet regexPattern=".*" rightRequired="ViewTodoPluginIcon">
<Scripts>
<String>ui/js/snippets/header.js</String>
</Scripts>
<StyleSheets>
<String>ui/css/todo.css</String>
</StyleSheets>
</Snippet>
</List>
</value>
</entry>
```
The script, `header.js` looks for `ul.navbar-right li:first`. Then, using the JQuery operation `.before()`, the script injects an icon link pointing to the fullPage (/plugins/pluginPage.jsf?pn=TodoPlugin) of the 'Todo' plugin.
```javascript
var url = SailPoint.CONTEXT_PATH + '/plugins/pluginPage.jsf?pn=TodoPlugin';
jQuery(document).ready(function(){
jQuery("ul.navbar-right li:first")
.before(
'<li class="dropdown">' +
' <a href="' + url + '" tabindex="0" role="menuitem" title="View your Todo list">' +
' <i role="presenation" class="fa fa-sticky-note-o fa-lg example"></i>' +
' </a>' +
'</li>'
);
jQuery(document).ready(function () {
jQuery('ul.navbar-right li:first').before(
'<li class="dropdown">' +
' <a href="' +
url +
'" tabindex="0" role="menuitem" title="View your Todo list">' +
' <i role="presenation" class="fa fa-sticky-note-o fa-lg example"></i>' +
' </a>' +
'</li>',
);
});
```

View File

@@ -8,7 +8,7 @@ sidebar_class_name: plugin_developer_guide_build_file
keywords: ['plugin']
description: IdentityIQ Plugin Build File
slug: /iiq/plugin-developer-guide/build-file
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Build File
@@ -24,7 +24,6 @@ version=2.0.0
The earlier example illustrates how a properties file can be leveraged to allow multiple developers to use the same build process, despite having different build environments. The actual 'build.xml' file is fairly straightforward, and it's responsible for creating the build directory, compiling any java classes, packaging those compiled classes into a .jar archive, and then archiving the complete plugin in .zip format. A more detailed explanation is provided for the 'Todo' plugin build file.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Todo Plugin" default="package">

View File

@@ -8,7 +8,7 @@ sidebar_class_name: plugin_developer_guide_database_scripts
keywords: ['plugin']
description: IdentityIQ Plugin Database Scripts
slug: /iiq/plugin-developer-guide/database-scripts
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# Database Scripts

View File

@@ -8,8 +8,9 @@ sidebar_class_name: plugin_developer_guide_ui_elements
keywords: ['plugin']
description: IdentityIQ Plugin UI Elements
slug: /iiq/plugin-developer-guide/ui-elements
tags: ['plugin','guide','identityiq']
tags: ['plugin', 'guide', 'identityiq']
---
# UI Elements
Most plugins will have some additional UI component that will display in IdentityIQ. You can use images, CSS files, HTML templates, and JavaScript to provide the interactions and views required by the plugin. Plugins using a `fullPage` element will look for a file called 'page.xhtml' in the build.
@@ -51,16 +52,26 @@ me.viewFlaggedUsers = function() {
});
};
```
The 'TodoController' controller (and available methods) can then be referenced in `page.xhtml`.
```html
<ui:composition>
<div class="container" ng-app="TodoList" ng-controller="TodoController as ctrl">
<div class="row m-t" ng-if="ctrl.pageConfig.showFlagged">
<button class="btn btn-danger pull-right" ng-click="ctrl.viewFlaggedUsers()">Flagged Users</button>
</div>
<div class="row m-t">
<div
class="container"
ng-app="TodoList"
ng-controller="TodoController as ctrl">
<div class="row m-t" ng-if="ctrl.pageConfig.showFlagged">
<button
class="btn btn-danger pull-right"
ng-click="ctrl.viewFlaggedUsers()">
Flagged Users
</button>
</div>
<div class="row m-t"></div></div
></ui:composition>
```
- **Line 2** - shows the angular controller `ng-controller` defined as 'TodoController' from **line 8** of 'TodoModule.js'.
- **Line 4** - example of accessing controller method `viewFlaggedUsers` from **line 21** of 'TodoModule.js'.
@@ -69,9 +80,9 @@ This example demonstrates how to use the Angular concept of the modal within a p
One last aspect to remember for the `page.xhtml` is the necessity to include references to the JavaScript packages the plugin will use. Use this path to reference the packages: `#{plugins.requestContextPath}/plugin/<Plugin Name>/path/to/js/files.js`.
```html
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/angular.min.js"></script>
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/ui-bootstrap.min.js"></script>
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/TodoModule.js"></script>
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/angular.min.js"></script>
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/ui-bootstrap.min.js"></script>
<script src="#{plugins.requestContextPath}/plugin/TodoPlugin/ui/js/TodoModule.js"></script>
```
The path to the page would be the following: `{serverpath}/plugins/pluginPage.jsf?pn={PluginName}`, where `PluginName` is the name of your plugin, as specified in the manifest, and `serverpath` is the path to your server.

Some files were not shown because too many files have changed in this diff Show More