Merge branch 'main' into feature/upgrade-open-api-generator

This commit is contained in:
Jordan Violet
2022-09-27 11:33:15 -04:00
1559 changed files with 4346 additions and 4476 deletions

5
.firebaserc Normal file
View File

@@ -0,0 +1,5 @@
{
"projects": {
"default": "developer-community-site"
}
}

56
.github/bot.yml vendored
View File

@@ -4,7 +4,7 @@ labelPRBasedOnFilePath:
Docs:
- products/**/*.md*
IdentityNow:
- products/idn/**/*
- products/idn/**/*
IdentityIQ:
- products/iiq/**/*
Event Trigger Docs:
@@ -38,11 +38,59 @@ labelPRBasedOnFilePath:
- navbar.js
Plugins:
- plugins.js
##### Reviewer #########################################################################################################
addReviewerBasedOnLabel:
labels:
Docs:
- james-haytko-sp
IdentityNow:
- colin-mckibben-sp
IdentityIQ:
- colin-mckibben-sp
Event Trigger Docs:
- colin-mckibben-sp
SaaS Connectivity Docs:
- philip-ellis-sp
Transform Docs:
- tyler-mairose-sp
Rules Docs:
- tyler-mairose-sp
SaaS Configuration Docs:
- colin-mckibben-sp
Introduction Doc:
- jordan-violet-sp
- colin-mckibben-sp
- tyler-mairose-sp
- james-haytko-sp
- philip-ellis-sp
Pages:
- philip-ellis-sp
Components:
- philip-ellis-sp
CSS:
- philip-ellis-sp
Swizzled Components:
- philip-ellis-sp
- jordan-violet-sp
Sidebar:
- philip-ellis-sp
Docusaurus Config:
- philip-ellis-sp
Footer:
- jordan-violet-sp
- philip-ellis-sp
Navbar:
- jordan-violet-sp
- colin-mckibben-sp
- tyler-mairose-sp
- james-haytko-sp
- philip-ellis-sp
Plugins:
- philip-ellis-sp
##### Greetings ########################################################################################################
# Comment to be posted to welcome users when they open their first PR
firstPRWelcomeComment: >
🎉 Thanks for opening this pull request! We really appreciate contributors like you! 🙌
🎉 Thanks for opening this pull request! Please be sure to check out our contributing guidelines. 🙌
# Comment to be posted to congratulate user on their first merged PR
firstPRMergeComment: >
@@ -50,4 +98,4 @@ firstPRMergeComment: >
# Comment to be posted to on first time issues
firstIssueWelcomeComment: >
🎉 Thanks for opening your first issue here! Welcome to the community!
🎉 Thanks for opening your first issue here! Be sure to follow the issue template, and welcome to the community! 🙌

View File

@@ -22,6 +22,9 @@ concurrency:
group: "pages"
cancel-in-progress: true
env:
BASE_URL: '/developer.sailpoint.com/'
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
publish:

View File

@@ -0,0 +1,19 @@
# This file was auto-generated by the Firebase CLI
# https://github.com/firebase/firebase-tools
name: Deploy to Firebase Hosting on PR
'on': pull_request
jobs:
build_and_preview:
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
runs-on: ubuntu-latest
env:
NODE_ENV: 'development'
steps:
- uses: actions/checkout@v2
- run: npm install && npm run docusaurus gen-api-docs all && npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_DEVELOPER_COMMUNITY_SITE }}'
projectId: developer-community-site

View File

@@ -1,35 +0,0 @@
name: Build Developer Community Site
on:
# Runs on pull requests targeting the default branch
pull_request:
branches: ["main"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: write
pages: write
id-token: write
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Check out repo
uses: actions/checkout@v3
# Node is required for npm
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: "16"
# Install and build Developer Community site
- name: Build Developer Community site
run: |
npm install
npm run gen-api-docs-all
npm run build

View File

@@ -21,7 +21,7 @@
<img src="./static/img/screenshot.png" width="500" height="" style="text-align:center">
</div>
</div>
<!-- ABOUT THE PROJECT -->
## About The Project

View File

@@ -7,12 +7,13 @@ const darkCodeTheme = require("prism-react-renderer/themes/dracula");
const footer = require("./footer");
const navbar = require("./navbar");
const plugins = require("./plugins");
const baseUrl = process.env.BASE_URL ?? '/';
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "SailPoint Developer Community",
url: "https://developer.sailpoint.com",
baseUrl: "/developer.sailpoint.com/",
baseUrl,
favicon: "img/SailPoint-Logo-Icon.ico",
onBrokenLinks: "warn",
onBrokenMarkdownLinks: "warn",

10
firebase.json Normal file
View File

@@ -0,0 +1,10 @@
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}

View File

@@ -41,7 +41,7 @@ module.exports = [
docsPluginId: "idn",
config: {
idn_v3: {
specPath: "static/idn-api/sailpoint-api.v3.yaml",
specPath: "static/api-specs/idn/sailpoint-api.v3.yaml",
outputDir: "products/idn/api/v3",
sidebarOptions: {
groupPathsBy: "tag",
@@ -49,7 +49,7 @@ module.exports = [
},
},
idn_beta: {
specPath: "static/idn-api/sailpoint-api.beta.yaml",
specPath: "static/api-specs/idn/sailpoint-api.beta.yaml",
outputDir: "products/idn/api/beta",
sidebarOptions: {
groupPathsBy: "tag",
@@ -66,7 +66,7 @@ module.exports = [
docsPluginId: "iiq",
config: {
iiq: {
specPath: "static/iiq-api/swagger.json",
specPath: "static/api-specs/iiq/swagger.json",
outputDir: "products/iiq/api",
sidebarOptions: {
groupPathsBy: "tag",

View File

@@ -3,7 +3,7 @@ id: event-triggers
title: Event Triggers
pagination_label: Event Triggers
sidebar_label: Event Triggers
sidebar_position: 2
sidebar_position: 3
sidebar_class_name: eventTriggers
keywords: ["event", "triggers", "webhooks"]
description:

View File

@@ -31,7 +31,7 @@ platfrom beyond what comes out of the box. Please, explore our documentation and
see what is possible! This documentation assumes that you are a current customer
or partner and already have access to the IdentityNow application.
:::info
:::info Are you a partner?
Looking to become a partner? If you are interested in becoming a partner, be it
an ISV or Channel/Implementation partner,

View File

@@ -0,0 +1,117 @@
---
id: account-profile-attribute-generator
title: Account Profile Attribute Generator
pagination_label: Account Profile Attribute Generator
sidebar_label: Account Profile Attribute Generator
sidebar_class_name: accountProfileAttributeGenerator
keywords: ["cloud", "rules", "account profile", "attribute generator"]
description:
This rule generates complex account attribute values during provisioning, e.g. when
creating an account.
slug: /docs/rules/cloud-rules/account-profile-attribute-generator
tags: ["Rules"]
---
## Overview
This rule generates complex account attribute values during provisioning, e.g. when creating an account.
You would typically use this rule when you are creating an account to generate attributes like usernames.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| identity | sailpoint.object.Identity | Reference to identity object representing the identity being calculated. |
| application | java.lang.Object | Attribute value of the identity attribute before the rule runs. |
| field | sailpoint.object.Field | Field object used to get information about the attribute being generated. |
## Output
| Argument | Type | Purpose |
| -------- | ---------------- | ---------------------------------------- |
| value | java.lang.Object | Value returned for the account attribute. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="AttributeGenerator">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Generate Username
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="Generate Username" type="AttributeGenerator">
<Description>This will generate a username.</Description>
<Source><![CDATA[
import sailpoint.tools.GeneralException;
import java.util.Iterator;
import sailpoint.object.*;
import java.util.ArrayList;
import sailpoint.api.*;
import sailpoint.object.*;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang.StringUtils;
int maxIteration = 1000;
public String generateUsername ( String firstName, String lastName, int iteration ) {
// Data protection.
firstName = StringUtils.trimToNull( firstName );
lastName = StringUtils.trimToNull( lastName );
if ( ( firstName == null ) || ( lastName == null ) )
return null;
// This will hold the final username;
String username = null;
switch ( iteration ) {
case 0:
username = firstName + "." + lastName;
break;
default:
username = firstName + "." + lastName + ( iteration - 1 );
break;
}
if ( isUnique ( username ) )
return username;
else if ( iteration < maxIteration )
return generateUsername ( firstName, lastName, ( iteration + 1 ) );
else
return null;
}
public boolean isUnique ( String username ) throws GeneralException {
return !idn.accountExistsByDisplayName(application.getName(), username);
}
return generateUsername( identity.getFirstname(), identity.getLastname(), 0 );
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,114 @@
---
id: account-profile-attribute-generator-template
title: Account Profile Attribute Generator (from Template)
pagination_label: Account Profile Attribute Generator (from Template)
sidebar_label: Account Profile Attribute Generator (from Template)
sidebar_class_name: accountProfileAttributeGeneratorTemplate
keywords: ["cloud", "rules", "account profile", "attribute generator"]
description:
This rule generates complex account attribute values during provisioning, e.g. when
creating an account. The rule's configuration comes from a template of values.
slug: /docs/rules/cloud-rules/account-profile-attribute-generator-template
tags: ["Rules"]
---
# Account Profile Attribute Generator (from Template)
## Overview
This rule generates complex account attribute values during provisioning, e.g. when creating an account.
The rule's configuration comes from a template of values.
You would typically use this rule when you are creating an account to generate attributes like usernames.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| -------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| identity | sailpoint.object.Identity | Reference to identity object representing the identity being calculated. |
| field | sailpoint.object.Field | Field object used to get information about the attribute being generated. |
## Output
| Argument | Type | Purpose |
| -------- | ---------------- | ---------------------------------------- |
| value | java.lang.Object | Value returned for the account attribute. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="AttributeGeneratorFromTemplate">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="Generate Username" type="AttributeGeneratorFromTemplate">
<Description>This will generate a username.</Description>
<Source><![CDATA[
import java.util.Iterator;
import sailpoint.object.*;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public String generateUniqueUsername ( String loginId, int iteration)
{
switch ( iteration )
{
case 0:
username = StringUtils.left(loginId, prefixLength) + suffix;
break;
// Default: add numbers until we get a unique username
default:
username = StringUtils.left(loginId, prefixLength - String.valueOf(iteration).length()).toString();
username = username + iteration + suffix;
break;
}
if ( isUnique ( username) )
return username;
else
return generateUniqueUsername ( loginId, ( iteration + 1 ));
}
public boolean isUnique ( String username )
{
return !idn.accountExistsByDisplayName(application.getName(), username);
}
int MAX_LENGTH = 20;
String suffix = field.getStringAttribute("template");
String loginId = identity.getAttribute("loginId");
int prefixLength = MAX_LENGTH - suffix.length();
if (StringUtils.isBlank(loginId))
return null;
else
return generateUniqueUsername( loginId, 0);
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,84 @@
---
id: before-provisioning-rule
title: Before Provisioning Rule
pagination_label: Before Provisioning Rule
sidebar_label: Before Provisioning Rule
sidebar_class_name: beforeProvisioningRule
keywords: ["cloud", "rules", "before provisioning"]
description: This rule runs before provisioning to a source.
slug: /docs/rules/cloud-rules/before-provisioning-rule
tags: ["Rules"]
---
## Overview
Use this rule to modify a provisioning plan as provisioning is sent out.
Do not use this rule to create new attributes. Use an account
creation profile (provisioning policy) instead.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| plan | sailpoint.object.ProvisioningPlan | Reference to identity object representing the identity being calculated. |
| application | java.lang.Object | Attribute value for the identity attribute before the rule runs. |
> Note: Logs are not supported for BeforeProvisioning rules.
## Output
There is no output for a Before Provisioning rule.
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="BeforeProvisioning">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Before Provisioning Rule that Changes Disables and Enables to a Modify
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="BeforeProvisioning">
<Description>Before Provisioning Rule which changes disables and enables to a modify.</Description>
<Source><![CDATA[
import sailpoint.object.*;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AccountRequest.Operation;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.Operation;
for ( AccountRequest accountRequest : plan.getAccountRequests() ) {
if ( accountRequest.getOp().equals( ProvisioningPlan.ObjectOperation.Disable ) ) {
accountRequest.setOp( ProvisioningPlan.ObjectOperation.Modify );
}
if ( accountRequest.getOp().equals( ProvisioningPlan.ObjectOperation.Enable ) ) {
accountRequest.setOp( ProvisioningPlan.ObjectOperation.Modify );
}
}
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,78 @@
---
id: correlation-rule
title: Correlation Rule
pagination_label: Correlation Rule
sidebar_label: Correlation Rule
sidebar_class_name: Correlation Rule
keywords: ["cloud", "rules", "correlation"]
description:
This rule associates or correlates an account to an identity, based on
complex logic.
slug: /docs/rules/cloud-rules/correlation-rule
tags: ["Rules"]
---
## Overview
This rule associates or correlates an account to an identity, based on complex logic.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| -------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| account | sailpoint.object.ResourceObject | Read-only representation of account data that has been aggregated. Use this as a basis to determine correlation linkages with a specific identity. |
## Output
| Argument | Type | Purpose |
| --------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| returnMap | java.util.Map | Map object containing a reference to the identity attributes to correlate to. These should contain both `identityAttributeName` and `identityAttributeValue` as keys. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="Correlation">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Correlate Account to Identity Based on Calculated Email Address
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="Correlation">
<Description>Correlates based on a calculated email address.</Description>
<Source><![CDATA[
Map returnMap = new HashMap();
String calculatedEmail = account.getStringAttribute( "username" ) + "@example.com";
returnMap.put( "identityAttributeName", "email");
returnMap.put( "identityAttributeValue", calculatedEmail );
return returnMap;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,189 @@
---
id: generic-rule
title: Generic Rule
pagination_label: Generic Rule
sidebar_label: Generic Rule
sidebar_class_name: Generic Rule
keywords: ["cloud", "rules", "generic"]
description: This rule performs transforms.
slug: /docs/rules/cloud-rules/generic-rule
tags: ["Rules"]
---
## Overview
This rule performs transforms.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| -------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
## Output
| Argument | Type | Purpose |
| -------- | ---------------- | ------------------------------------------------------------ |
| value | java.lang.Object | Value returned for the account attribute, typically a string. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Name Normalizer
This rule normalizes any names into normal names capitaliztion. For
example: JOHN DOE -> John Doe.
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Name Normalizer">
<Description>
This rule normalizes any names into normal names capitaliztion. For example:
JOHN DOE -> John Doe
tony smith -> Tony Smith
CORNELIUS AUGUSTINE MCGLENNON IV -> Cornelius Augustine McGlennon IV
NEIL MC GLENNON -> Neil McGlennon
mArTiN o'mAlLeY -> Martin O'Malley
Dr. JOHN D. O'BRIEN -> Dr. John D. O'Brien
john wilkes-booth -> John Wilkes-Booth
JOAN OF ARC -> Joan of Arc
MACKENNA -> MacKenna
OSCAR DE LA HOYA -> Oscar de la Hoya
CAPTAIN VON TRAPP -> Captain von Trapp
Dell dEl Roach -> Dell del Roach
Augustiner Anstruther-Gough-Calthorpe -> Augustiner Anstruther-Gough-Calthorpe
GEORGE HENRY LANE-FOX PITT-RIVERS ESQ. -> George Henry Lane-Fox Pitt-Rivers Esq.
JOSÉ ORTEGA Y GASSET -> José Ortega y Gasset
</Description>
<Source><![CDATA[
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import com.google.gson.Gson;
/*
* Delimiter Constant (Step 2): These define default word boundaries for the 'capitalizeFully' function.
* Default is hyphenated last names, space, and anything with ' character.
*/
char[] delimiters = delimiters;
/*
* Patterns Constant (Step 3): These are for special replacements for Mc and Mac surnames.
*/
String patterns = patterns;
/*
* Replacements Constant (Step 4): These are for special replacements for titles, suffixes, and name linkages.
*/
String replacements = replacements;
/*
* Normalize Name Function
* Input: String
* Output: String
*/
public String normalizeName ( String input ) {
/*
* Step 1: If we're null or empty, we're done.
*/
input = StringUtils.trimToNull( input );
if ( input == null )
return null;
/*
* Step 2: Iterate through delimiters, and do a pattern match on capitalizaion. This takes care of 99% of the simple stuff.
* e.g. john doe -> John Doe
*/
input = WordUtils.capitalizeFully( input, delimiters );
/*
* Step 3: Iterate through and handle special cases.
* e.g. Mcglennon -> McGlennon, Mackenna -> MacKenna
*/
Matcher m = Pattern.compile( patterns ).matcher( input );
while ( m.find() ) {
input = WordUtils.capitalizeFully( input.substring( 0, m.start() ), delimiters )
+ WordUtils.capitalizeFully( input.substring( m.start(), m.end() ), delimiters )
+ WordUtils.capitalizeFully( input.substring( m.end(), input.length() ), delimiters );
}
/*
* Step 4: Iterate through special replacement exceptions.
* e.g. CAPTAIN VON TRAPP -> Captain Von Trapp -> Captain von Trapp
*/
Map replaceMap = new Gson().fromJson( replacements, Map.class );
Iterator it = replaceMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
input = Pattern.compile( (String) pair.getKey() ).matcher( input ).replaceAll( (String) pair.getValue() );
it.remove(); // avoids a ConcurrentModificationException
}
/*
* We're done!
*/
return input;
}
return normalizeName( input );
]]></Source>
</Rule>
```
## Transform Reference
```json
{
"name": "Normalize Name",
"type": "rule",
"attributes": {
"name": "Name Normalizer",
"delimiters": ["-", " ", "\\'"],
"replacements": {
"\\\\b(?:Von)\\\\b": "von",
"\\\\b(?:Del)\\\\b": "del",
"\\\\b(?:Of)\\\\b": "of",
"\\\\b(?:De)\\\\b": "de",
"\\\\b(?:La)\\\\b": "la",
"\\\\b(?:Y)\\\\b": "y",
"\\\\b(?:Iv)\\\\b": "IV",
"\\\\b(?:Iii)\\\\b": "III",
"\\\\b(?:Ii)\\\\b": "II",
"\\\\b(?:Mc )\\\\b": "Mc"
},
"patterns": "\\b(Mc|Mac)",
"input": {
"type": "trim"
}
}
}
```

View File

@@ -0,0 +1,104 @@
---
id: identity-attribute-rule
title: Identity Attribute Rule
pagination_label: Identity Attribute Rule
sidebar_label: Identity Attribute Rule
sidebar_class_name: identityAttributeRule
keywords: ["cloud", "rules", "identity attribute"]
description:
This rule calculates and returns an identity attribute for a specific
identity.
slug: /docs/rules/cloud-rules/identity-attribute-rule
tags: ["Rules"]
---
# Identity Attribute Rule
## Overview
This rule calculates and returns an identity attribute for a specific identity.
This rule is also known as a "complex" rule on the identity profile.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| -------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| identity | sailpoint.object.Identity | Reference to identity object representing the identity being calculated. |
| oldValue | java.lang.Object | Attribute value for the identity attribute before the rule runs. |
## Output
| Argument | Type | Purpose |
| -------------- | ---------------- | ----------------------------------------- |
| attributeValue | java.lang.Object | Value returned for the identity attribute. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="IdentityAttribute">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Calculate Lifecycle State Based on Start and End Dates
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="IdentityAttribute">
<Description>Calculates LCS based on start and end dates.</Description>
<Source><![CDATA[
import java.text.SimpleDateFormat;
import java.util.Date;
// Date format we expect dates to be in (ISO8601)
SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd" );
// Parse the start date from the identity, and put in a Date object.
Date startDate = null;
if ( identity.getAttribute( "startDate" ) != null ) {
startDate = dateFormat.parse( identity.getAttribute( "startDate" ) );
}
// Parse the end date from the identity, and put in a Date object.
Date endDate = null;
if ( identity.getAttribute( "endDate" ) != null ) {
endDate = dateFormat.parse( identity.getAttribute( "endDate" ) );
}
// Define a date for today
Date today = new Date();
// Calculate lifecycle state based on the attributes.
if( startDate.before( today ) && endDate.after( today ) ) {
return "active";
} else if ( endDate.before( today ) ) {
return "inactive";
}
// If we haven't calculated a state already; return null.
return null;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,151 @@
---
id: cloud-executed-rules
title: Cloud Executed Rules
pagination_label: Cloud Executed Rules
sidebar_label: Cloud Executed Rules
sidebar_position: 1
sidebar_class_name: cloudExecutedRules
keywords: ["cloud", "rules"]
description: Overview of cloud-executed rules
slug: /docs/rules/cloud-rules
tags: ["Rules"]
---
## Overview
**Cloud-Executed Rules** or **Cloud Rules** typically only perform a
specific function, such as calculating attribute values.
Cloud Rules all execute within the SailPoint cloud and offer access to
objects and data, but they do not offer any sort of externalized
connectivity.
Because these rules execute in a multi-tenant cloud environment, they have a very
restricted context, and the review process is carefully scrutinized to ensure
that they execute in an efficient and secure manner.
## Supported Cloud Rules
```mdx-code-block
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
<DocCardList items={useCurrentSidebarCategory().items}/>
```
## Configuration Process
To ensure maximum compatibility, platform integrity, and security, SailPoint has
instantiated a review process to ensure that any submitted Cloud Rules meet SailPoint
requirements and that they do not contain code that can harm the system.
The review process also checks the rules to verify their intended purposes and use cases.
In this process, SailPoint does _not check_ whether the rule executes correctly
or verify that it works as expected to deliver specific outcomes. The review is merely
an integrity check on the rule itself.
## Submitting for Rule Review
To submit your Cloud Rule for review, approval, and inclusion in the
SailPoint platform, submit them with
[SailPoint Professional Services](https://www.sailpoint.com/services/professional/).
If you need help writing and testing rules, Professional Services can help you with
that process as well. Make sure your contact information is up to date,
in case the review team needs to contact you.
## Review Guidelines
All submitted rules must follow proper rule submission guidelines.
- **Best Practices**
- Ensure that all rule configurations are complete and accurate.
- Check whether your rule follows SailPoint best practice guidance, and ensure that you have
considered other product features first.
- **Rule Quality**
- Rules must follow the [Rule Guidelines](../rule_guide#rule-guidelines)
and [Code Restrictions](../rule_guide#rule-code-restrictions)
- Rules must be adequately tested prior to submission.
- **Documentation**
- Include detailed comments for non-obvious features in the configurations,
including supporting documentation where appropriate. This includes
justification for why something was created or done in a certain way. -
_e.g. I did this because..._
- **Standards**
- Rules must omit commented out blocks or unfinished, incomplete, or untested
code.
- Rules must be submitted with appropriate UTF-8 encoding.
- Rules must convert url-encoded characters:
- `&amp;` should be `&`
- `&lt;` should be `<`
- `&gt;` should be `>`
- **Rule File Naming**
The file naming convention for rules is: `Rule - {type} - {name}.xml`
If this is your rule:
`<Rule language="beanshell" name="Calculate Lifecycle" type="IdentityAttribute">`
This should be your file name:
`Rule - IdentityAttribute - Calculate Lifecycle.xml`
If you do not have a type, use "Generic" as the type. It would look
like this:
`Rule - Generic - My Generic Rule.xml`
- **Updating Existing Rules and Versioning**
- The best practice is to maintain a single rule for a given use case in the
tenant. Creating additional rules while updating to maintain versioning is
not supported because doing so may cause issues during reviews and support.
- **Example:** For an AD Before Provisioning rule called "AD
BeforeProvisioningRule", you have the file "Rule - BeforeProvisioning -
AD BeforeProvisioningRule.xml". When you are updating the logic for AD, it is best
to update the file/rule with the same name, so changes can be properly
tracked to the single object.
- **Deployment Window Requirements**
- Rules are generally reviewed and deployed, if they are accepted
without feedback, within 24 hours.
- If specific windows are required and you want full control of when a rule
is updated, use these steps to follow the versioning best practices:
- Submit your request for a new rule with the name: `<original name>-TEMP`
- Apply the new rule during the change window.
- Validate the updated rule logic.
- Once the rule is validated, submit your request to update original rule with the updated logic.
- Once the original rule is updated, apply the original rule as the production
configuration.
- Submit your request to delete the TEMP rule.
## Review Expectations
Once you have submitted your rule and you are in the review process, remember these points:
- **Timing:** SailPoint will examine your rule as soon as possible. Most rules are
reviewed within 24 hours of submission. However, if your rule is complex,
poorly documented, hard to read, or if it presents new issues, it may require
greater scrutiny and consideration. If your rule is repeatedly rejected for
the same guideline violation, your rule's review may take longer to complete.
- **Status Updates:** Your rule's current status will be reflected in your
[SailPoint Expert Services request](https://www.sailpoint.com/services/professional/#contact-form),
so you can monitor its progress there.
- **Expedite Requests:** If you have a critical timing issue, you can request an
expedited review. Respect your fellow implementers by seeking expedited
review only when you truly need it. If you are found to be abusing this system, SailPoint
may reject further requests going forward.
- **Rejections:** SailPoint's goal is to apply these guidelines fairly and consistently,
but mistaken rejections can happen. If your rule has been rejected and you have questions or you
would like to provide additional information, communicate directly with
the rule review team. This may help get your rule into IdentityNow, and it can
help SailPoint improve the process or identify a need for clarity in its policies. If
you still disagree with the outcome, let SailPoint know and someone can look into it.
- **Changes:** Rule changes or modifications to meet guidelines are not the reviewer's
responsibility. They are the responsibility of the person(s) submitting the rule.
Reviewers may give advice, examples, etc. to
help, but doing so does not guarantee a solution. You should test the rules with the changes
before resubmission.
```
```

View File

@@ -0,0 +1,77 @@
---
id: manager-correlation-rule
title: Manager Correlation Rule
pagination_label: Manager Correlation Rule
sidebar_label: Manager Correlation Rule
sidebar_class_name: managerCorrelationRule
keywords: ["cloud", "rules", "manager correlation"]
description:
This rule calculates a manager relationship between identities.
slug: /docs/rules/cloud-rules/manager-correlation-rule
tags: ["Rules"]
---
## Overview
This rule calculates a manager relationship between identities.
## Execution
- **Cloud Execution** - This rule executes in the IdentityNow cloud, and it has
read-only access to IdentityNow data models, but it does not have access to
on-premise sources or connectors.
- **Logging** - Logging statements are currently only visible to SailPoint
personnel.
![Rule Execution](../img/cloud_execution.png)
## Input
| Argument | Type | Purpose |
| --------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| log | org.apache.log4j.Logger | Logger to log statements. _Note: This executes in the cloud, and logging is currently not exposed to anyone other than SailPoint._ |
| idn | sailpoint.server.IdnRuleUtil | Provides a read-only starting point for using the SailPoint API. From this passed reference, the rule can interrogate the IdentityNow data model including identities or account information via helper methods as described in [IdnRuleUtil](../idn_rule_utility.md). |
| link | sailpoint.object.Link | Read-only representation of account data that has been aggregated. Use this as a basis to determine manager linkages to a specific manager identity. |
| managerAttributeValue | java.lang.Object | Attribute value stored in the manager attribute. |
## Output
| Argument | Type | Purpose |
| --------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| returnMap | java.util.Map | Map object containing a reference to the identity attributes to identify the manager's identity. These should contain both `identityAttributeName` and `identityAttributeValue` as keys. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="ManagerCorrelation">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example - Find a manager based on the manager.email attribute
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Manager Email Correlation" type="ManagerCorrelation">
<Description>Finds a manager based on the manager.email attribute.</Description>
<Source><![CDATA[
Map returnMap = new HashMap();
String managerEmail = link.getAttribute( "manager.email" );
returnMap.put( "identityAttributeName", "email");
returnMap.put( "identityAttributeValue", managerEmail );
return returnMap;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,244 @@
---
id: before-and-after-rule-operations
title: Before and After Operations on Source Account Rule
pagination_label: Before and After Operations
sidebar_label: Before and After Rule Operations
sidebar_class_name: beforeAndAfterRuleOperations
keywords: ["cloud", "rules"]
description:
This rule executes PowerShell commands on the IQService component
after a source account has an operation performed on it.
slug: /docs/rules/connector-rules/before-and-after-rule-operations
tags: ["Rules"]
---
# Before and After Operations on Source Account Rule
## Overview
This rule executes PowerShell commands on the IQService component after a source account has an operation performed on it.
The following operations can be performed on a source:
| Rule Name | Rule Type | Source Type(s) | Purpose |
| -------------------- | --------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------- |
| Before Creation Rule | ConnectorBeforeCreate | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is created. |
| Before Modify Rule | ConnectorBeforeModify | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is modified. |
| Before Delete Rule | ConnectorBeforeDelete | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is deleted. |
| After Creation Rule | ConnectorAfterCreate | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is created. |
| After Modify Rule | ConnectorAfterModify | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is modified. |
| After Delete Rule | ConnectorAfterDelete | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is deleted. |
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | -------------------------------------- | ------------------------------------------------------------------------- |
| Application | System.Collections.Hashtable | Map of the application configuration. |
| Request | SailPoint.Utils.objects.AccountRequest | Reference to the account request provisioning instructions. |
| Result | SailPoint.Utils.objects.ServiceResult | Reference to the provisioning result that can be manipulated if necessary. |
## Architecture Best Practices
For supportability, it is recommended that you write these operation rules with
only the most basic logic necessary to trigger a PowerShell script and shift
the bulk of the downstream events and/or modifications to the PowerShell script
itself. This script would reside on the client's servers and can therefore be
easily maintained or modified by the client as needed. It also allows the client
to implement changes to the PowerShell scripted functionality without requiring
code review by SailPoint because the code runs outside of the IdentityNow platform.
## Rule Template
This example triggers on the BeforeCreate operation. If you want
to use another operation, replace `BeforeCreate` in the name and
`ConnectorBeforeCreate` in the type with one of the other operations described
earlier in the [Overview](#overview) section.
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="SampleSource BeforeCreate" type="ConnectorBeforeCreate">
<Attributes>
<Map>
<entry key="ObjectOrientedScript" value="true" />
<entry key="disabled" value="false" />
<entry key="extension" value=".ps1" />
<entry key="program" value="powershell.exe" />
<entry key="timeout" value="300" />
</Map>
</Attributes>
<Description>
This is an IQService afterScript - On a successful provisioning event, this after script should be used as the starting point to
initiate a separate PowerShell script residing on the client's IQService server.
Configuration tasks include the following:
- Set a proper location for the $logFile variable.
- Set the proper script location and name for the $command variable.
- Set the $enableDebug flag to $true or $false to toggle debug mode.
</Description>
<Source>
<![CDATA[
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\Scripts\Logs\ConnectorAfterCreate_$logDate.log"
$command = "c:\SailPoint\Scripts\SampleSource-AfterCreate.ps1"
$enableDebug = $false
#====================-------Helper functions-------====================
function LogToFile([String] $info) {
$info | Out-File $logFile -Append
}
#====================-------Get the request object-------====================
Try{
if($enableDebug) {
LogToFile("Entering SailPoint rule")
}
Add-type -path utils.dll;
$sReader = New-Object System.IO.StringReader([System.String]$env:Request);
$xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));
$requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
$requestAsString = $env:Request
if($enableDebug) {
LogToFile("Request as XML object is: $requestAsString")
}
#Call the client script
$command = -join ($command, " -requestString '$requestAsString'")
Invoke-Expression $command
}Catch{
$ErrorMessage = $_.Exception.Message
$ErrorItem = $_.Exception.ItemName
LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
}
if($enableDebug) {
LogToFile("Exiting SailPoint rule")
}
]]>
</Source>
</Rule>
```
## Powershell Script Template
You can also use the following Powershell script template for each operation in
the [Overview](#overview) section. Be sure to update the `$logFile` variable
with the operation you use to ensure you are logging to a file with the correct
operation name.
```powershell
###############################################################################################################################
# SETUP
# Instructions (for each IQService host that could run the script):
# - Update the path to Utils.dll (can be an unqualified path like "Utils.dll" since script is copied to IQService folder for execution)
# - Make sure Utils.dll is in the specified folder on each IQService host
# - Be sure the account that runs IQService has appropriate permissions to create directories and set permissions on them
# - Be sure to set the "run as" account for the IQService in Windows Service to the above-specified account instead of just the "logged on" user
# - Set a proper location for the $logFile variable
# - Set the $enableDebug flag to $true or $false to toggle debug mode
###############################################################################################################################
param (
[Parameter(Mandatory=$true)][System.String]$requestString
)
#include SailPoint library
Add-Type -Path "c:\SailPoint\IQService\Utils.dll";
#import AD cmdlets
Import-Module activeDirectory
#log file info
$logDate = Get-Date -UFormat "%Y%m%d"
$logFile = "c:\SailPoint\Scripts\Logs\SampleSourceBeforeCreateScript_$logDate.log"
$enableDebug = $false
###############################################################################################################################
# HELPER FUNCTIONS
###############################################################################################################################
#save logging files to a separate txt file
function LogToFile([String] $info) {
$info | Out-File $logFile -Append
}
#if we have a non-null account request, get our value; otherwise return nothing
function Get-AttributeValueFromAccountRequest([sailpoint.Utils.objects.AccountRequest] $request, [String] $targetAttribute) {
$value = $null;
if ($request) {
foreach ($attrib in $request.AttributeRequests) {
if ($attrib.Name -eq $targetAttribute) {
$value = $attrib.Value;
break;
}
}
} else {
LogToFile("Account request object was null");
}
return $value;
}
###############################################################################################################################
# BODY
###############################################################################################################################
if($enableDebug) {
LogToFile("Entering beforeScript")
}
try {
##########################
# Begin SailPoint protected code -- do not modify this code block
#
$sReader = New-Object System.IO.StringReader([System.String]$requestString);
$xmlReader = [System.xml.XmlTextReader]([sailpoint.utils.xml.XmlUtil]::getReader($sReader));
$requestObject = New-Object Sailpoint.Utils.objects.AccountRequest($xmlReader);
#debug line for testing
if($enableDebug) {
LogToFile("Request object contents:")
LogToFile($requestObject | Out-String)
}
#
# End SailPoint protected code
##########################
##########################
# Begin Client-provided code
#get the necessary info we need from the accountRequest object
#as an example: $nativeIdentity = $requestObject.nativeIdentity
#do whatever work needs to be done here
#
# End Client-provided code
}
catch {
$ErrorMessage = $_.Exception.Message
$ErrorItem = $_.Exception.ItemName
LogToFile("Error: Item = $ErrorItem -> Message = $ErrorMessage")
}
if($enableDebug) {
LogToFile("Exiting beforeScript")
}
```

View File

@@ -0,0 +1,79 @@
---
id: buildmap-rule
title: BuildMap Rule
pagination_label: BuildMap Rule
sidebar_label: BuildMap Rule
sidebar_class_name: buildMapRule
keywords: ["cloud", "rules"]
description:
This rule manipulates raw input data provided by the
rows and columns in a file and builds a map from the incoming data.
slug: /docs/rules/connector-rules/buildmap-rule
tags: ["Rules"]
---
# BuildMap Rule
## Overview
This rule manipulates raw input data provided by the rows and columns in a file and builds a map from the incoming data.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | ---------------------------- | ---------------------------------------------------------------------------------------------- |
| col | java.util.List | Ordered list of the column names from the files header records or specified columns list. |
| record | java.util.List | Ordered list of the values for the current record, parsed based on the specified delimiter. |
| application | System.Collections.Hashtable | Map of the application configuration. |
| schema | sailpoint.object.Schema | Reference to the schema object for the delimited file source being read. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="BuildMap">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="BuildMap">
<Description>This basic rule performs the combines 2 values into a single attribute.</Description>
<Source><![CDATA[
import sailpoint.connector.DelimitedFileConnector;
Map map = DelimitedFileConnector.defaultBuildMap( cols, record );
String access = (String) map.get( "access" );
String permission = (String) map.get( "permission" );
if ( access != null && permission != null ) {
map.remove("access");
map.remove("permission");
map.put("access", access + " - " + permission);
}
return map;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,281 @@
---
id: connector-executed-rules
title: Connector Executed Rules
pagination_label: Connector Executed Rules
sidebar_label: Connector Executed Rules
sidebar_position: 1
sidebar_class_name: cloudExecutedRules
keywords: ["connector", "rules"]
description: Overview of connector-executed rules.
slug: /docs/rules/connector-rules
tags: ["Rules"]
---
**Connector-Executed Rules** or **Connector Rules** are rules that are executed
in the IdentityNow virtual appliance, and they are usually extensions of the
connector itself. The rules are commonly used to perform complex
connector-related functions, so they are specific to only certain connectors.
Because these rules execute in the virtual appliance, they do not have access to
query the IdentityNow data model or fetch information from IdentityNow. They
rely instead on contextual information sent from IdentityNow. Connector-executed
rules may also have managed connections provided in their contexts to support
querying end systems or sources. Though these managed connections may be used,
making additional connections or call-outs is not allowed.
Unlike cloud rules, connector rules do not have a rule review process and are
directly editable with the
[Connector Rule REST APIs](https://developer.sailpoint.com/apis/beta/#tag/Connector-Rule-Management).
For more details, see [Configuration Process](#configuration-process).
## Supported Connector Rules
| Rule Name | Rule Type | Source Type(s) | Purpose |
| --------------------------------------------------- | ---------------------------------------------------- | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Before Creation Rule](before_after_operation_rule) | [ConnectorBeforeCreate](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is created. |
| [Before Modify Rule](before_after_operation_rule) | [ConnectorBeforeModify](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is modified. |
| [Before Delete Rule](before_after_operation_rule) | [ConnectorBeforeDelete](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component before a source account is deleted. |
| [After Creation Rule](before_after_operation_rule) | [ConnectorAfterCreate](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is created. |
| [After Modify Rule](before_after_operation_rule) | [ConnectorAfterModify](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is modified. |
| [After Delete Rule](before_after_operation_rule) | [ConnectorAfterDelete](before_after_operation_rule) | Active Directory, Azure Active Directory | Executes PowerShell commands on the IQService component after a source account is deleted. |
| Build Map Rule | BuildMap | Delimited File | Calculates and transforms data from a parsed file during the aggregation process. _Note: This is only available for the Delimited File source type, not Generic source types._ |
| JDBC Build Map Rule | JDBCBuildMap | JDBC | Calculates and transforms data from a database query result during the aggregation process. It can also perform additional calls back to the database. _Note: This rule is available for the JDBC Generic source, as well as other sources that derive from the JDBC connector (e.g., Oracle EBS, PeopleSoft, etc.)_ |
| JDBC Provision Rule | JDBCProvision | JDBC | Executes database queries to perform provisioning of account and access for all account operations. |
| SAP Build Map Rule | SAPBuildMap | SAP HR, SAP | Calculates and transforms data from SAP during the aggregation process. It can also perform additional calls back to the SAP system using SAP BAPI calls. |
| SAP HR Provisioning Modify Rule | SapHrOperationProvisioning | SAP HR | Performs SAP HR modification operations during provisioning. Often used for attribute sync to custom SAP HR attributes. |
| Web Services Before Operation Rule | WebServiceBeforeOperationRule | Web Services | Executes before the next web-services HTTP(S) operation. Often used to calculate values. |
| Web Services After Operation Rule | WebServiceAfterOperationRule | Web Services | Executes after a web-services HTTP(S) operation. Often used to parse complex data. |
## Configuration Process
Connector Rules are directly editable with the
[Connector Rule REST APIs](https://developer.sailpoint.com/apis/beta/#tag/Connector-Rule-Management),
which provide ability to interact with rules directly.
| Name | Path |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------- |
| [List Connector Rules](https://developer.sailpoint.com/apis/beta/#operation/getConnectorRuleList) | `GET /beta/connector-rules/` |
| [Get Connector Rule](https://developer.sailpoint.com/apis/beta/#operation/getConnectorRule) | `GET /beta/connector-rules/{id}` |
| [Create Connector Rule](https://developer.sailpoint.com/apis/beta/#operation/createConnectorRule) | `POST /beta/connector-rules/` |
| [Update Connector Rule](https://developer.sailpoint.com/apis/beta/#operation/updateConnectorRule) | `PUT /beta/connector-rules/{id}` |
| [Delete Connector Rule](https://developer.sailpoint.com/apis/beta/#operation/deleteConnectorRule) | `DELETE /beta/connector-rules/{id}` |
| [Validate Connector Rule](https://developer.sailpoint.com/apis/beta/#operation/validateConnectorRule) | `POST /beta/connector-rules/validate` |
SailPoint architectural optimizations have added resiliency and protections
against malformed or long-running rules. These APIs also offer built-in
protection and checking against potentially harmful code. For more information,
see [Rule Code Restrictions](../rule_guide.md#rule-code-restrictions).
## Connector Rule Object Model
```json
{
"id": "2c91808674a2816a0174af21a6450009",
"name": "Example WebServices Rule",
"description": "This is just an example",
"created": "2020-09-21T05:27:32.170Z",
"modified": null,
"type": "WebServiceBeforeOperationRule",
"signature": {
"input": [],
"output": null
},
"attributes": {
"sourceVersion": "2020-09-21 05:27:31"
},
"sourceCode": {
"version": "2020-09-21 05:27:31",
"script": "\n import java.util.HashMap;\n import org.json.JSONArray;\n import org.json.JSONException;\n import org.json.JSONObject;\n\n import org.apache.http.HttpEntity;\n import org.apache.http.HttpResponse;\n import org.apache.http.client.HttpClient;\n import org.apache.http.client.methods.HttpPost;\n import ...
requestEndPoint.getBody().put(\"jsonBody\",requestXML); \n }\n }\n }\n log.info(\"Done Ultipro Onboarding before operation rule...\");\n return requestEndPoint;\n"
}
}
```
- `id` - Unique UUID that the REST APIs refers to this rule by. This is
generated on creation.
- `name` - Name the user interface and references may use to refer to this rule.
- `description` - Description of the rules purpose or usage.
- `created` - Timestamp when the rule was created.
- `modified` - Timestamp when the rule was last modified. The default is `null`.
- `type` - Type of connector rule. For a list of supported rule types, see
[Supported Connector Rules](#supported-connector-rules).
- `attributes` - List of attributes.
- `sourceVersion` - String indicating the rule's version. Typically, this is
the same as `version`.
- `sourceCode` - Object housing the actual source code that makes the rule work.
- `version` - String indicating the rule's version. Typically, this is the
same as `sourceVersion`.
- `script` - Rules code the connector runs. This must be an escaped string.
For help with formatting, use an escaping tool like
[Free Formatter.](https://www.freeformatter.com/java-dotnet-escape.html#before-output)
## Attaching Connector-Related Rules to Sources
Once a connector-related rule has been imported to your tenant, you must
configure any sources that need to reference that rule during the desired
operation. You can accomplish this configuration through the execution of an API
call on the source. The following examples all use a `PATCH` operation for a
partial source update, but `PUT` operations work too, as long as the entire
source object model is provided.
For the `PATCH` operations, you must provide an `op` key. For new
configurations, this key is typically set to `add` as the example shows, but
they can be any of the following:
- `add` - Add a new value to the configuration. Use this operation if this is
the first time you are setting the value, i.e. it has never been configured
before.
- `replace` - Use this operation to change the existing value. Use this
operation if you are updating the value, i.e. you want to change the
configuration.
- `remove` - Removes a value from the configuration. Use this operation if you
want to unset a value. **Caution: Removals can be destructive if the path is
improperly configured. This can negatively alter your source config.**
## Example API calls by Rule Type
### BeforeProvisioning Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "add",
"path": "/beforeProvisioningRule",
"value": {
"type": "RULE",
"id": "2c918085708c274401708c2a8a760001",
"name": "Example Rule"
}
}
]
```
### Correlation Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "add",
"path": "/accountCorrelationRule",
"value": {
"type": "RULE",
"id": "2c9180896fc824e5016fc827ea880005",
"name": "Example Rule"
}
}
]
```
### ManagerCorrelation Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "replace",
"path": "/managerCorrelationRule",
"value": {
"type": "RULE",
"id": "2c9180836fb03f35016fb05dae3b0001",
"name": "Example Rule"
}
}
]
```
### BuildMap Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "add",
"path": "/connectorAttributes/buildMapRule",
"value": "Example Rule"
}
]
```
### JDBCBuildMap Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "add",
"path": "/connectorAttributes/buildMapRule",
"value": "Example Rule"
}
]
```
### JDBCProvision Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
```json
[
{
"op": "add",
"path": "/connectorAttributes/jdbcProvisionRule",
"value": "Example Rule"
}
]
```
### WebServiceBeforeOperation Rule
`PATCH` /v3/sources/{id}
Content-Type: `application/json-patch+json`
_Note: Replace
`_`with the index location of operation the way it is configured on the source. For example, 0, 1, 2, etc. You can use a`GET`call on the source first to verify the index location prior to executing the`PATCH`
call to attach the rule.\*
```json
[
{
"op": "replace",
"path": "/connectorAttributes/connectionParameters/[*]/beforeRule",
"value": "Example Rule"
}
]
```
### WebServiceAfterOperation Rule
`PATCH` /v3/sources/{id} Content-Type: `application/json-patch+json`
_Note: Replace \[\*\] with the index location of the operation the way it is
configured on the source. For example, 0, 1, 2, etc. You can use a `GET` call on
the source first to verify the index location prior to executing the `PATCH`
call to attach the rule._
```json
[
{
"op": "replace",
"path": "/connectorAttributes/connectionParameters/[*]/afterRule",
"value": "Example Rule"
}
]
```

View File

@@ -0,0 +1,95 @@
---
id: jdbc-buildmap-rule
title: JDBC BuildMap Rule
pagination_label: JDBC BuildMap Rule
sidebar_label: JDBC BuildMap Rule
sidebar_class_name: jdbcBuildMapRule
keywords: ["cloud", "rules"]
description:
This rule manipulates raw input data provided by the
rows and columns in a file and builds a map from the incoming data.
slug: /docs/rules/connector-rules/jdbc-buildmap-rule
tags: ["Rules"]
---
## Overview
This rule manipulates raw input data provided by the rows and columns in a file and builds a map from the incoming data.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
| result | java.sql.ResultSet | Current ResultSet from the JDBC Connector. |
| connection | java.sql.Connection | Reference to the current SQL connection. |
| state | java.util.Map | Map that can be used to store and share data between executions of this rule during a single aggregation run. |
| application | sailpoint.object.Application | Attribute value of the identity attribute before the rule runs. |
| schema | sailpoint.object.Schema | Reference to the schema object for the delimited file source being read. |
## Output
| Argument | Type | Purpose |
| -------- | ------------ | --------------------------------------------------------------------- |
| map | java.utl.Map | Map of names/values representing a row of data from the JDBC resource. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="JDBCBuildMap">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="JDBCBuildMap">
<Description>
This basic rule performs the default mapping and then replaces the status value read from the database with a
Boolean inactive attribute in the map.
</Description>
<Source><![CDATA[
import sailpoint.connector.*;
Map map = JDBCConnector.buildMapFromResultSet(result, schema);
String status = (String) map.get("status");
if( "inactive".equals(status) ) {
map.put("inactive", true);
} else {
map.put("inactive", false);
}
map.remove("status");
return map;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,183 @@
---
id: jdbc-provisioning-rule
title: JDBC Provision Rule
pagination_label: JDBC Provision Rule
sidebar_label: JDBC Provision Rule
sidebar_class_name: jdbcProvisionRule
keywords: ["cloud", "rules", "jdbc"]
description:
This rule performs provisioning actions from a provisioning
plan provided by a supplied JDBC connection. These actions typically issue SQL commands, such
as insert, update, select, and delete.
slug: /docs/rules/connector-rules/jdbc-provisioning-rule
tags: ["Rules"]
---
## Overview
This rule performs provisioning actions from a provisioning plan provided by a supplied JDBC connection.
These actions typically issue SQL commands, such as insert, update, select, and delete.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | --------------------------------- | ------------------------------------------------------------------------- |
| connection | java.sql.Connection | Reference to the current SQL connection. |
| plan | sailpoint.object.ProvisioningPlan | Provisioning plan containing the provisioning request(s). |
| application | sailpoint.object.Application | Attribute value for the identity attribute before the rule runs. |
| schema | sailpoint.object.Schema | Reference to the schema object for the delimited file source being read. |
## Output
| Argument | Type | Purpose |
| -------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| result | sailpoint.object.ProvisioningResult | ProvisioningResult object containing the provisioning request's status (success, failure, retry, etc.). |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="JDBCProvision">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="JDBCProvision">
<Description>This example JDBC rule can process account creation requests, deletion requests, and modification requests that pertain to the role attribute. It logs debug messages if other account request types are submitted.</Description>
<Source><![CDATA[
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import sailpoint.api.SailPointContext;
import sailpoint.connector.JDBCConnector;
import sailpoint.object.Application;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.ProvisioningPlan.PermissionRequest;
import sailpoint.object.ProvisioningResult;
import sailpoint.object.Schema;
public String getAttributeRequestValue(AccountRequest acctReq, String attribute) {
if ( acctReq != null ) {
AttributeRequest attrReq = acctReq.getAttributeRequest(attribute);
if ( attrReq != null ) {
return attrReq.getValue();
}
}
return null;
}
ProvisioningResult result = new ProvisioningResult();
PreparedStatement statement;
if ( plan != null ) {
List accounts = plan.getAccountRequests();
if ( ( accounts != null ) && ( accounts.size() > 0 ) ) {
for ( AccountRequest account : accounts ) {
try {
if ( AccountRequest.Operation.Create.equals( account.getOperation() ) ) {
// Ideally we should first check to see if the account already exists.
// As written, this just assumes it does not.
statement = connection.prepareStatement( "insert into users (login,first,last,role,status) values (?,?,?,?,?)" );
statement.setString ( 1, (String) account.getNativeIdentity() );
statement.setString ( 2, getAttributeRequestValue(account,"first") );
statement.setString ( 3, getAttributeRequestValue(account,"last") );
statement.setString ( 4, getAttributeRequestValue(account,"role") );
statement.setString ( 5, getAttributeRequestValue(account,"status") );
statement.executeUpdate();
result.setStatus( ProvisioningResult.STATUS_COMMITTED );
} else if ( AccountRequest.Operation.Modify.equals( account.getOperation() ) ) {
// Modify account request -- change role
PreparedStatement statement = connection.prepareStatement( "update users set role = ? where login = ?" );
statement.setString ( 2, (String) account.getNativeIdentity() );
if ( account != null ) {
AttributeRequest attrReq = account.getAttributeRequest("role");
if ( attrReq != null && ProvisioningPlan.Operation.Remove.equals(attrReq.getOperation()) ) {
statement.setNull ( 1, Types.NULL );
statement.executeUpdate();
} else {
statement.setString(1,attrReq.getValue());
statement.executeUpdate();
}
}
result.setStatus( ProvisioningResult.STATUS_COMMITTED );
} else if ( AccountRequest.Operation.Delete.equals( account.getOperation() ) ) {
PreparedStatement statement = connection.prepareStatement( (String) application.getAttributeValue( "account.deleteSQL" ) );
statement.setString ( 1, (String) account.getNativeIdentity() );
statement.executeUpdate();
result.setStatus( ProvisioningResult.STATUS_COMMITTED );
} else if ( AccountRequest.Operation.Disable.equals( account.getOperation() ) ) {
// Disable, not supported.
} else if ( AccountRequest.Operation.Enable.equals( account.getOperation() ) ) {
// Enable, not supported.
} else if ( AccountRequest.Operation.Lock.equals( account.getOperation() ) ) {
// Lock, not supported.
} else if ( AccountRequest.Operation.Unlock.equals( account.getOperation() ) ) {
// Unlock, not supported.
} else {
// Unknown operation!
}
}
catch( SQLException e ) {
result.setStatus( ProvisioningResult.STATUS_FAILED );
result.addError( e );
}
finally {
if(statement != null) {
statement.close();
}
}
}
}
}
return result;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,91 @@
---
id: sap-buildmap-rule
title: SAP BuildMap Rule
pagination_label: SAP BuildMap Rule
sidebar_label: SAP BuildMap Rule
sidebar_class_name: sapBuildMapRule
keywords: ["cloud", "rules", "sap"]
description:
This rule gathers additional attributes from SAP systems to
build accounts. This rule is implemented using SAP's Java Connector (JCo)
framework provided by a supplied SAP connection.
slug: /docs/rules/connector-rules/sap-buildmap-rule
tags: ["Rules"]
---
## Overview
This rule gathers additional attributes from SAP systems to build accounts.
This rule is implemented using SAP's Java Connector (JCo) framework provided by a supplied SAP connection.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| object | sailpoint.object.Attributes | Reference to a SailPoint attributes object (basically a map object with some added convenience methods) that holds the attributes that have been built up by the default connector implementation. The rule should modify this object to change, add, or remove attributes from the map. |
| connector | sailpoint.connector.SAPInternalConnector | Reference to the current SAP connector. |
| state | java.util.Map | Map that can be used to store and share data between executions of this rule during a single aggregation run. |
| application | sailpoint.object.Application | Attribute value for the identity attribute before the rule runs. |
| schema | sailpoint.object.Schema | Reference to the schema object for the delimited file source being read. |
| destination | com.sap.conn.jco.JCoDestination | Connected and ready-to-use SAP destination object that can be used to call BAPI function modules and call to SAP tables. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SAPBuildMap">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SAPBuildMap">
<Description> This example SAP Build Map rule constructs an Initials attribute from the first character of the FirstName and LastName attributes and changes the name of the InitDate attribute to HireDate. </Description>
<Source><![CDATA[
import java.util.HashMap;
// Create initials
String firstName = object.get("FirstName");
String lastName = object.get("LastName");
String initials = "";
if ( firstName != null && firstName.length() > 0 ) {
char letter = firstName.charAt(0);
letter = Character.toUpperCase(letter);
initials = letter + ".";
}
if ( lastName != null && lastName.length() > 0 ) {
letter = lastName.charAt(0);
letter = Character.toUpperCase(letter);
initials += letter + ".";
}
object.put("Initials", initials);
object.put("HireDate", object.remove("InitDate"));
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,266 @@
---
id: sap-provisioning-modify-rule
title: SAP HR Provisioning Modify Rule
pagination_label: SAP HR Provisioning Modify Rule
sidebar_label: SAP HR Provisioning Modify Rule
sidebar_class_name: sapHRProvisioningModifyRule
keywords: ["cloud", "rules", "sap"]
description:
This rule performs SAP HR modification operations during
provisioning. This rule is typically used for attribute sync to custom SAP HR
attributes.
slug: /docs/rules/connector-rules/sap-provisioning-modify-rule
tags: ["Rules"]
---
## Overview
This rule performs SAP HR modification operations during provisioning.
This rule is typically used for attribute sync to custom SAP HR attributes.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------- | ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| application | sailpoint.object.Application | Reference to the application object. |
| schema | sailpoint.object.Schema | Reference to the application schema. |
| destination | com.sap.conn.jco.JCoDestination | Connected and ready-to-use SAP destination object that can be used to call BAPI function modules and call to SAP tables. |
| plan | sailpoint.object.ProvisioningPlan | Provisioning plan containing the provisioning request(s). |
| request | sailpoint.object.ProvisioningPlan.AbstractRequest | AccountRequest being processed. It is always null for this global rule. It is only set for SapHrOperationProvisioning. |
| connector | sailpoint.connector.SAPHRConnector | Application connector being used for the operation. |
## Output
| Argument | Type | Purpose |
| -------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| result | sailpoint.object.ProvisioningResult | ProvisioningResult object containing the provisioning request's status (success, failure, retry, etc.). |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SapHrOperationProvisioning">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="SapHrOperationProvisioning">
<Description>
This rule is used by the SAP HR connector for provisioning of the data.
</Description>
<Source><![CDATA[
import sailpoint.object.*;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.object.ProvisioningPlan.ObjectOperation;
import sailpoint.object.ProvisioningPlan.AccountRequest.Operation;
import sailpoint.tools.Util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.HashMap;
import com.sap.conn.jco.AbapException;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import sailpoint.connector.ConnectorException;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoParameterField;
import com.sap.conn.jco.JCoParameterFieldIterator;
import com.sap.conn.jco.JCoParameterList;
import com.sap.conn.jco.JCoStructure;
import com.sap.conn.jco.JCoTable;
import com.sap.conn.jco.JCoContext;
// subtype values for email , Telephone or system user name
String SUBTYPE_EMAIL = "0010"; //Sub info type for email address
String SUBTYPE_PHONE= "0020"; //Sub info type for telephone number
String SUBTYPE_SY_USERNAME= "0001"; //Sub info type for sy-username which can be mapped to SAMAccountName of AD
ProvisioningResult result = new ProvisioningResult();
//This function will modify the email address , Telephone or system user name if recieved in the plan
public void doProvision() throws Exception {
List<AccountRequest> accReqList = plan.getAccountRequests();
String accNativeIdentity = null;
String endDateStr = "", beginDateStr = "";
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
if (!Util.isEmpty(accReqList)) {
for( AccountRequest accountReq : accReqList ) {
result.setStatus( ProvisioningResult.STATUS_COMMITTED );
accNativeIdentity = accountReq.getNativeIdentity();
// For update operation only Email,Telephone,SY-UNAME atrribute are supported
AttributeRequest emailAttr = accountReq.getAttributeRequest("Email");
AttributeRequest phoneAttrib = accountReq.getAttributeRequest("Telephone");
AttributeRequest syUserAttrib = accountReq.getAttributeRequest("System user name (SY-UNAME)");
HashMap beginEndDateList = getCommunicationData( accNativeIdentity );
//Finding the email attribute in provisioning plan and trying to modify the account's email id
if ( null != emailAttr ) {
if(null !=beginEndDateList && beginEndDateList.containsKey("emailBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("emailBegin"));
endDateStr = formatter.format(beginEndDateList.get("emailEnd"));
}
modifyCommunicationData(accNativeIdentity, emailAttr.getValue(), SUBTYPE_EMAIL,beginDateStr,endDateStr);
}
//Finding the Telephone attribute in provisioning plan and trying to modify the account's phone
if ( null != phoneAttrib ) {
if(null !=beginEndDateList && beginEndDateList.containsKey("phoneBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("phoneBegin"));
endDateStr = formatter.format(beginEndDateList.get("phoneEnd"));
}
modifyCommunicationData(accNativeIdentity, phoneAttrib.getValue(), SUBTYPE_PHONE,beginDateStr,endDateStr);
}
//Finding the system user name attribute in provisioning plan and trying to modify the account's System User Name
if ( null != syUserAttrib) {
if(null !=beginEndDateList && beginEndDateList.containsKey("syUserBegin")) {
beginDateStr = formatter.format(beginEndDateList.get("syUserBegin"));
endDateStr = formatter.format(beginEndDateList.get("syUserEnd"));
}
modifyCommunicationData(accNativeIdentity,syUserAttrib.getValue(), SUBTYPE_SY_USERNAME,beginDateStr,endDateStr);
}
}
}
}
// This function will get the communication details about a given employee
// In this example the email, Telephone and system user name begin and end date will be retrieved
public HashMap getCommunicationData( String id ) throws Exception {
HashMap commAttrsList = new HashMap();
JCoFunction getCommDetail = connector.getFunction(destination, "BAPI_EMPLCOMM_GETDETAILEDLIST");
getCommDetail.getImportParameterList().setValue("EMPLOYEENUMBER", id);
getCommDetail.getImportParameterList().setValue("TIMEINTERVALLOW", new Date());
getCommDetail.getImportParameterList().setValue("TIMEINTERVALHIGH", new Date());
try {
getCommDetail.execute(destination);
} catch (Exception e) {
connector.checkForExceptions(getCommDetail);
throw new Exception(e);
}
JCoTable commTable = getCommDetail.getTableParameterList().getTable("COMMUNICATION");
if ( commTable != null ) {
int rows = commTable.getNumRows();
for (int i = 0; i < rows; i++) {
commTable.setRow(i);
String commType = commTable.getString("SUBTYPE");
commAttrsList = getDateData(commTable, commAttrsList, commType);
}
}
return commAttrsList;
}
// function captures the begin date and end date
public HashMap getDateData(JCoTable commTable, HashMap commAttrsList, String commType) {
Date validBegDate = commTable.getDate("VALIDBEGIN");
Date validEndDate = commTable.getDate("VALIDEND");
if ( validBegDate != null && validEndDate != null ) {
if (commType.equals(SUBTYPE_EMAIL)) {
commAttrsList.put("emailBegin", validBegDate);
commAttrsList.put("emailEnd", validEndDate);
} else if (commType.equals(SUBTYPE_PHONE)) {
commAttrsList.put("phoneBegin", validBegDate);
commAttrsList.put("phoneEnd", validEndDate);
}else if (commType.equals(SUBTYPE_SY_USERNAME)) {
commAttrsList.put("syUserBegin", validBegDate);
commAttrsList.put("syUserEnd", validEndDate);
}
}
return commAttrsList;
}
/**Function modifies the email address , Telephone number and System user name of SAP HR record.
If Email or Phone is present(assigned) then used BAPI_EMPLCOMM_CHANGE
If Email or Phone is not present(assigned) then used BAPI_EMPLCOMM_CREATE
* @param userId
* @param parValue
* @param type
* @param begDate
* @param endDate
* @throws ConnectorException
*/
private void modifyCommunicationData( String userId, String parValue, String type,String begDate,String endDate ) throws ConnectorException {
JCoFunction jcoFunctionObject;
if (begDate.length() > 1 ) { //If date is alreday present then use BAPI_EMPLCOMM_CHANGE to modify data
jcoFunctionObject = connector.getFunction(destination,"BAPI_EMPLCOMM_CHANGE");
} else { //If date is not present then use BAPI_EMPLCOMM_CREATE to add data
jcoFunctionObject = connector.getFunction(destination,"BAPI_EMPLCOMM_CREATE");
}
// BAPI locks the record for processing
JCoFunction functionEnqueue = destination.getRepository().getFunction("BAPI_EMPLOYEE_ENQUEUE");
functionEnqueue.getImportParameterList().setValue("NUMBER", userId);
if ( functionEnqueue == null )
throw new RuntimeException("BAPI_EMPLOYEE_ENQUEUE not found in SAP.");
// BAPI to modify Communication data - email and phone
if ( jcoFunctionObject == null )
throw new RuntimeException("BAPI_EMPLCOMM_CHANGE not found in SAP.");
String returnPersonnelID = null;
jcoFunctionObject.getImportParameterList().setValue("EMPLOYEENUMBER", userId); // Personal Number
jcoFunctionObject.getImportParameterList().setValue("SUBTYPE", type); // SubType 0010/0020 - Email/Phone
jcoFunctionObject.getImportParameterList().setValue("VALIDITYBEGIN", begDate); // Begin Date
jcoFunctionObject.getImportParameterList().setValue("VALIDITYEND", endDate); // End Date
jcoFunctionObject.getImportParameterList().setValue("COMMUNICATIONID", parValue); // Email Address to modify
// BAPI unlocks the record after processing
JCoFunction functionDequeue = destination.getRepository().getFunction("BAPI_EMPLOYEE_DEQUEUE");
functionDequeue.getImportParameterList().setValue("NUMBER", userId);
if ( functionDequeue == null )
throw new RuntimeException("BAPI_EMPLOYEE_DEQUEUE not found in SAP.");
try {
// executing Bapis
JCoContext.begin(destination);
functionEnqueue.execute(destination);
jcoFunctionObject.execute(destination);
functionDequeue.execute(destination);
} catch (ConnectorException e) {
throw e;
} finally {
JCoContext.end(destination);
}
}
doProvision();
return result;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,160 @@
---
id: webservices-after-provisioning-rule
title: Web Services After Operation Rule
pagination_label: Web Services After Operation Rule
sidebar_label: Web Services After Operation Rule
sidebar_class_name: webServicesAfterOperationRule
keywords: ["cloud", "rules", "webservices"]
description:
This rule calculates attributes after a web-service operation call.
slug: /docs/rules/connector-rules/webservices-after-provisioning-rule
tags: ["Rules"]
---
## Overview
This rule calculates attributes after a web-service operation call.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ----------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| application | sailpoint.object.Application | Application whose data file is being processed. |
| processedResponseObject | List<Map<String, Object>> | List of map (account/group). The map contains a key, the identityAttribute of the application schema, and a value, all the account/group attributes (schema) passed by the connector after parsing the respective API response. |
| requestEndPoint | sailpoint.connector.webservices.EndPoint | Current request information. It contains the header, body, context url, method type, response attribute map, successful response code. |
| restClient | sailpoint.connector.webservices.WebServicesClient | WebServicesClient (HttpClient) object that enables the user to call the Web Services API target system. |
| rawResponseObject | String | String object that holds the raw response returned from the target system, which can be in JSON or XML form. |
## Output
| Argument | Type | Purpose |
| ------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| updatedAccountOrGroupList | java.util.Map | `Map` object returned from the After Operation Rule. It may contain any or all of the following: an updated list of account / group resource objects, identified by key `data`/ attribute values to be updated into application by the connector state map identified by key `connectorStateMap`. Each resource (account/group) object is of type `Map`, which contains the **key-value** pair. The **key** represents the schema attribute name, and the **value** represents the account/group attribute value. |
## Template
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceAfterOperationRule">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
## Example
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceAfterOperationRule">
<Description>This rule is used by the Web Services connector after performing any operation like testconnection, aggregation etc.</Description>
<Source><![CDATA[
import connector.common.JsonUtil;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import javax.net.ssl.HttpsURLConnection;
import java.io.BufferedReader;
import java.io.PrintStream;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import sailpoint.tools.GeneralException;
Map updatedMapInfo = new HashMap();
List list = new ArrayList();
ArrayList<String> Roles = new ArrayList<String>();
Map response = (Map) JsonUtil.toMap(rawResponseObject);
int RoleSize = 0;
String newName;
List Finallist = new ArrayList();
List workspace = new ArrayList();
log.error("RULES response at start" + response);
if (response.get("data") != null) {
list = (ArrayList) response.get("data");
for(int d = 0; d < list.size(); d++ ){
Map responseMap = (Map) list.get(d);
if (responseMap.get("attributes") != null) {
Map newmap = new HashMap();
Map data = (Map) responseMap.get("attributes");
newmap.put("firstName", data.get("firstName"));
newmap.put("lastName",data.get("lastName"));
newmap.put("displayName",data.get("displayName"));
newmap.put("userName",data.get("userName"));
newmap.put("email",data.get("email"));
if (data.get("workspaceMemberships") != null) {
ArrayList Workspacedetail = (ArrayList) data.get("workspaceMemberships");
for (int i = 0; i < Workspacedetail.size(); i++) {
Map work = (Map) Workspacedetail.get(i);
for (int w = 0; w < work.size(); w++) {
if (work.get("workspaceName") != null) {
workspace.add(work.get("workspaceName"));
Roles = (ArrayList) work.get("workspaceRoles");
for (int r = 0; r < Roles.size(); r++) {
if (Roles.get(r) != null) {
newName = Roles.get(r).toString() + " - " + work.get("workspaceName");
if(newName != null) {
Roles.set(r, newName);
newmap.put("workspaceRoles", Roles);
}
}
}
}
break;
}
}
}
Finallist.add(newmap);
}
}
}
log.error("RULES newmap at end" + newmap);
log.error("RULES Finallist at end" + Finallist);
log.error("RULES processedResponseObject Before is " + processedResponseObject);
updatedMapInfo.put("data", Finallist);
log.error("RULES updatedMapInfo is " + updatedMapInfo);
return updatedMapInfo;
log.error("RULES processedResponseObject after is " + processedResponseObject);
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,145 @@
---
id: webservices-before-provisioning-rule
title: Web Services Before Operation Rule
pagination_label: Web Services Before Operation Rule
sidebar_label: Web Services Before Operation Rule
sidebar_class_name: webServicesBeforeOperationRule
keywords: ["cloud", "rules", "webservices"]
description:
This rule calculates attributes before a web-service operation call.
slug: /docs/rules/connector-rules/webservices-before-provisioning-rule
tags: ["Rules"]
---
## Overview
This rule calculates attributes before a web-service operation call.
## Execution
- **Connector Execution** - This rule executes within the virtual appliance. It
may offer special abilities to perform connector-related functions, and it may
offer managed connections to sources.
- **Logging** - Logging statements are viewable within the ccg.log on the
virtual appliance, and they are viewable by SailPoint personnel.
![Rule Execution](../img/connector_execution.png)
## Input
| Argument | Type | Purpose |
| ---------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| application | sailpoint.object.Application | Application whose data file is being processed. |
| provisioningPlan | sailpoint.object.ProvisioningPlan | Provisioning plan used to update the payload of the http request. The provisioning plan has an account request that defines the operation to be performed on the account. An account request can contain multiple attributes requests. Each attribute request represents an operation on a single account attribute. This argument enables the user to update the body/payload or URL attributes of an endpoint object using the provisioningPlan information. |
| requestEndPoint | sailpoint.connector.webservices.EndPoint | Current request information. It contains the header, body, context url, method type, response attribute map, and successful response code. |
| restClient | sailpoint.connector.webservices.WebServicesClient | WebServicesClient (HttpClient) object that enables the user to call the Web Services API target system. |
| oldResponseMap | java.util.Map | Response object returned from earlier endpoint configuration of the same operation type, like Account Aggregation, Get Object, etc. |
## Output
| Argument | Type | Purpose |
| -------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| EndPoint / Map | sailpoint.connector.webservices.EndPoint / sailpoint.connector.webservices.Map | The rule allows the user to return the endpoint object (requestEndPoint) or a map. The map can hold **updatedEndPoint** and **connectorStateMap** keys where the value expected are **Endpoint** (requestEndPoint) and **connectorStateMap** object respectively. The **connectorStateMap** object is a map that contains a key and a value for the attribute that must be updated in the application by the rule. |
```xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceBeforeOperationRule">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
```
```java
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceBeforeOperationRule">
<Description>This rule is used by the Web Services connector before performing any operation like testconnection, aggregation etc.</Description>
<Source><![CDATA[
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import connector.common.JsonUtil;
import connector.common.Util;
import sailpoint.connector.webservices.EndPoint;
import sailpoint.connector.webservices.WebServicesClient;
import sailpoint.object.Application;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
Map body = requestEndPoint.getBody();
String jsonBody = (String) body.get("jsonBody");
log.info("Rule - Modify Body: running");
try {
Map jsonMap = JsonUtil.toMap(jsonBody);
if (jsonMap != null) {
Object roleEntry = jsonMap.get("webSiteAndRole");
String role = "";
if (roleEntry != null && roleEntry instanceof ArrayList) {
ArrayList rolesArray = (ArrayList) roleEntry;
if (rolesArray.size() > 0) {
role = (String) rolesArray.get(0);
}
} else if (roleEntry != null) {
role = (String) roleEntry;
}
jsonMap.remove("webSiteAndRole");
jsonMap.put("webSiteAndRole", role);
log.info("Rule - Modify Body: setting webSiteAndRole = " + role);
String webID = "";
if (provisioningPlan != null) {
log.info("Rule - Modify Body: plan is not null");
for (AccountRequest accReq : Util.iterate(provisioningPlan.getAccountRequests())) {
log.info("Rule - Modify Body: iterating over account requests");
for (ProvisioningPlan.AttributeRequest attReq : Util.iterate(accReq.getAttributeRequests())) {
log.info("Rule - Modify Body: iterating over attribute requests");
String attrName = attReq.getName();
String value = null;
if (attrName != null && "webId".equalsIgnoreCase(attrName)) {
webID = (String) attReq.getValue();
log.info("Rule - Modify Body: setting webID = " + webID);
}
}
}
} else {
log.info("Rule - Modify Body: plan is null");
}
if (!"".equals(webID)) {
jsonMap.put("webID", webID);
}
// Add in any other missing fields that are required
if (!jsonMap.containsKey("webLogonEmail")) {
jsonMap.put("webLogonEmail", "");
}
if (!jsonMap.containsKey("taxID")) {
jsonMap.put("taxID", "");
}
if (!jsonMap.containsKey("taxIdType")) {
jsonMap.put("taxIdType", "");
}
if (!jsonMap.containsKey("actorLogonId")) {
jsonMap.put("actorLogonId", "");
}
String finalBody = JsonUtil.render(jsonMap);
body.put("jsonBody", finalBody);
requestEndPoint.setBody(body);
}
} catch (Exception ex) {
log.error("Rule - Modify Body: " + ex);
}
return requestEndPoint;
]]></Source>
</Rule>
```

View File

@@ -0,0 +1,619 @@
---
id: rule-utility
title: Using IDNRuleUtil as a Wrapper for Common Rule Operations
pagination_label: IdentityNow Rule Utility
sidebar_label: IdentityNow Rule Utility
sidebar_position: 2
sidebar_class_name: ruleUtility
keywords: ["rule", "utility"]
description: Using IDNRuleUtil as a Wrapper for Common Rule Operations
slug: /docs/rules/rule-utility
tags: ["Rules"]
---
## Overview
Use this guide to learn how to configure searchable account attributes
within IdentityNow and then leverage them within the IDNRuleUtil wrapper class
when searching accounts for attributes such as uniqueness checks. There are also
methods in the IDNRuleUtil wrapper class you can use without the additional
searchable attributes.
Search attributes allow you to search across accounts and sources to determine
whether a specific attribute value is being used in your IdentityNow environment.
There are three critical components involves with working with searchable
attributes:
- [Configuration of search attributes within IdentityNow](#configuration-of-search-attributes-within-identitynow)
- Seed data for accounts already aggregated into the system.
- Ensure attribute promotion happens for new/changed accounts that are
aggregated.
- [Create rules that can be used to query the newly created attribute values](#create-rules-that-can-be-used-to-query-the-newly-created-attribute-values)
- [Implement rules within the Create Profile section of each source an account is being provisioned for](#implement-rules-within-the-create-profile-section-of-each-source-for-which-an-account-is-being-provisioned)
## Configuration of Search Attributes within IdentityNow
When you are planning to implement search attributes, it is important that you consider the way
new accounts' values will be generated and which attributes should be used
as references.
You need the following information to create search attributes:
- IDs for sources that will be searched.
- Attribute name for each source that will be searched (such as mail, email,
emailAddress).
- Unique name for the new attribute that will become common to all accounts in
the account search configuration (e.g., newMail, newEmail, newEmailAddress).
- Display name for the new attribute configuration.
The following example shows how to create a new attribute with the
[Search Attributes API](/idn/api/beta/create-search-attribute-config):
Your company has two sources. The first is Active Directory, and the second is
Workday. When the system aggregates new accounts, the company wants to query
IdentityNow to see whether an email address already exists. If the email address is
not in use, you can assign it to the new account. If it is in use, you can
iterate on the email address value (add a 1 for example). You can then query
IdentityNow once more to see whether your incremented email address is in use. You can
repeat this procedure until you have determined that an email address is unique.
The following information is necessary to create your search attribute:
- IDs for sources that will be searched:
- Active Directory: `4028112837fe14c70177fe1955e9032c`
- Workday: `4028812877fa18c72177fs195baa0341`
- Attribute name on each source that will be searched (such as mail, email,
emailAddress):
- Active Directory: `mail`
- Workday: `emailAddress`
- Unique name for the new attribute that will become common to all accounts in
the account search configuration (e.g., newMail, newEmail, newEmailAddress):
- `promotedEmailAddress`
- Display name for the new attribute configuration:
- `Promoted Email Address`
### Create the New Search Attribute in IdentityNow
To call the APIs for search attributes, you need a personal access
token and the name of your tenant to provide with the request. To retrieve a
personal access token, see
[Personal Access Tokens](../../../api/authentication.md#personal-access-tokens).
To get the name of your tenant, see
[Finding Your Organization Tenant Name](../../../api/getting-started.md#find-your-tenant-name)
Doing so creates an account search configuration for the two sources/attributes
specified. All new/changed accounts that are aggregated have this new
attribute(“promotedEmailAddress”) created in the account schema and the value of
the attribute(“mail” or “emailAddress”), depending on the source, is promoted
to that new attribute.
```bash
curl --location -g --request POST 'https://{tenant}.api.identitynow.com/beta/accounts/search-attribute-config' \
--header 'Authorization: Bearer {token}' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "promotedEmailAddress",
"displayName": "Promoted Email Address",
"applicationAttributes":
{
"4028112837fe14c70177fe1955e9032c": "mail",
"4028812877fa18c72177fs195baa0341": "emailAddress"
}
}'
```
:::caution
Aggregation only processes new and/or changed accounts for many sources.
If an account is unchanged, an aggregation will not seed the new attribute or its value for this account.
Therefore, it is mandatory that a non-optimized aggregation be performed when an account
search configuration is created/modified for each source involved in that configuration.
:::
If this source has already been aggregated before the account search
configuration was created, a non-optimized aggregation must now be performed
to seed the new attribute data for all existing accounts.
At this point, the configuration exists to promote attributes on any new/changed
account that comes into IdentityNow. These attributes and their associated
values are stored for use in custom rules. Each account that exists on either of
these sources will now have a new attribute called “promotedEmailAddress”. _The
value of this attribute will be the value of `mail` if it is the Active
Directory Source or `emailAddress` if it is the Workday source._
## Create Rules that Can Be Used to Query the Newly Created Attribute values
To access the promoted attribute data mentioned in the above section, you can use library
methods that have been implemented to allow access to that data. There are two
methods that have been implemented:
```java
/**
* Count the accounts that match the searchable attribute and value.
*
* @param sourceIds The list of application IDs that represent the sources of the data.
* @param attributeName The name of the searchable account attribute. The name parameter is required.
* @param operation The operation to use when matching, it will either be Operation.Equal OR Operation.StartsWith
* @param values The value of that searchable attribute to math. The value parameter is required.
*
* @return The number of accounts that match the parameters provided.
*/
public int attrSearchCountAccounts(List<String> sourceIds, String attributeName, String operation, List<String> values)
```
```java
/**
* Get the identity name for the account matching the specified criteria.
*
* @param sourceIds The list of application IDs that represent the sources of the data.
* @param attributeName The name of the searchable account attribute. The name parameter is required.
* @param operation The operation to use when matching. It will either be Operation.Equal OR Operation.StartsWith.
* @param values The value of that searchable attribute to math. The value parameter is required.
*
* @return The name of the identity that matched the account that match the parameters provided.
*/
public String attrSearchGetIdentityName(List<String> sourceIds, String attributeName, String operation, List<String> values)
```
Each of these utility library methods are loaded into the context that is
available from within your custom rule. It can be accessed by appending the
prefix “idn.” to the method call.
Example: You want to use the promoted attribute data to determine an email address's uniqueness
before using it to provision a new account to one of the
sources involved in the account search configuration. You can call these methods
to determine that uniqueness.
```java
import sailpoint.object.*;
import java.util.*;
import sailpoint.rule.*;
import org.apache.commons.lang.StringUtils;
List SOURCE_IDS = new ArrayList(Arrays.asList(new String[]{"4028112837fe14c70177fe1955e9032c","4028812877fa18c72177fs195baa0341"}));
String PROMOTED_ATTR_NAME = "promotedEmailAddress";
String SEARCH_OP = "StartsWith"; //Can also use "Equals"
List SEARCH_VALUES = new ArrayList(Arrays.asList(new String[]{"jc@sailpoint.com"}));
//return matching accounts
return idn.attrSearchCountAccounts(SOURCE_IDS, PROMOTED_ATTR_NAME, SEARCH_OP, SEARCH_VALUES));
//In the event that the earlier call returns non-zero values, it is certain
//that an email value is already in use. If it is required to
//know which identity owns the account with this value, you can call this method:
//idn.attrSearchGetIdentityName(SOURCE_IDS, PROMOTED_ATTR_NAME, SEARCH_OP, SEARCH_VALUES));
```
:::info
Note that there are two method calls within the earlier example rule.
:::
Calling the _`idn.attrSearchCountAccounts()`_ method with both example source
IDs causes a search of all accounts for a value
“promotedEmailAddress=jc@sailpoint.com”. The search returns the count of accounts
containing that attribute value pair.
If _`idn.attrSearchCountAccounts()`_ returns non-zero, it may be
useful to determine which identity owns the account(s) containing that value. The
_`idn.attrSearchGetIdentityName()`_ method will return that identity name.
## Implement Rules within the Create Profile Section of Each Source for an Acount is Being Provisioned For
Create Profile can be found at **Admin** > **Connections** > **Source** >
`SourceName` > **Accounts** > **Create Profile**
You can invoke rules in different ways, but one of the most common
implementations involves binding it to the Create Profile. This results in
the rule's being used to generate/check the values used during new account
provisioning.
When a `Generator` is selected for the `distinguishedName` attribute, a rule that invokes the provided library methods can be selected.
This is an example of such a scenario:
Through a lifecycle state change, an account needs to be provisioned to an
Active Directory source.
When the provisioning plan is created, the rule that generates the value for
`distinguishedName` is called. The rule invokes the library methods mentioned
earlier to determine the uniqueness of the attribute. In this case it may do the following:
Call _`idn.attrSearchCountAccounts()`_ to determine whether any other accounts are
using first.last as a distinguishedName. If a count of 1 or more is returned,
the call can be retried with first.last+1. The call is repeated until a zero is
returned. At that point, the value is unique and can be used. The value is
returned to the calling rule.
In some cases where a non zero value is returned, it may be useful to know
which identity owns the account that value belongs to. To find
out this information, call _`idn.attrSearchGetIdentityName()`_ to determine the
identity in question.
## IdnRuleUtil.java Descriptors
:::caution
Both the normal SailPoint context passed into the Beanshell rule
evaluation and the new IdnRuleUtil referenced here include an
"Identity" class:
The SailPoint context Identity class is provided via `sailpoint.object.Identity`
The IdnRuleUtil Identity class is provided via `sailpoint.rule.Identity` When
referencing an Identity class, you must be explicit as to which Identity class
you are using to avoid a namespace conflict. For example:
:::
```java
sailpoint.object.Identity identity = plan.getIdentity();
String sAMAccountName = identity.getAttribute("adUsername");
sailpoint.rule.Identity foundIdentity = idn.getIdentityById("uid");
String email = foundIdentity.getAttribute("email");
```
The below section provides a full accounting of the methods available to rule
writers using the IdnRuleUtil class:
```java
/**
* Utility class containing methods customers can use within rules to perform common tasks.
* IdnRuleUtil is available in rules as "idn" variable, e.g. "idn.countAccounts("someAppId")".
* This utility class allows you to abstract out the use of SailPointContext in rules so you can one day not pass a
* context to the rule at all.
*/
import sailpoint.object.Application;
import sailpoint.object.Attributes;
import sailpoint.object.Filter;
import sailpoint.object.Link;
import sailpoint.object.LinkExternalAttribute;
import sailpoint.object.ManagedAttribute;
import sailpoint.object.QueryOptions;
import sailpoint.rule.Account;
import sailpoint.rule.ManagedAttributeDetails;
import sailpoint.rule.RuleObjectFactory;
import sailpoint.tools.GeneralException;
import sailpoint.tools.Util;
class IdnRuleUtil {
/**
* Determines whether an account currently exists on an application using the native identity.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @return True if the account exists, false otherwise.
* @throws GeneralException wrapping underlying DB related errors.
*/
boolean accountExistsByNativeIdentity(String applicationName, String nativeIdentity)
/**
* Determines if an account currently exists on an application using the display name.
*
* @param applicationName The application name.
* @param displayName The account's display name.
* @return True if the account exists, false otherwise.
* @throws GeneralException wrapping underlying DB related errors.
*/
boolean accountExistsByDisplayName(String applicationName, String displayName)
/**
* Gets an account on an application using the native identity.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @return The account or null if not found. If more than one is found, the first
* account in the exists is returned.
* @throws GeneralException wrapping underlying DB related errors
*/
Account getAccountByNativeIdentity(String applicationName, String nativeIdentity)
/**
* Gets an account on an application using the display name.
*
* @param applicationName The application name.
* @param displayName The account's display name.
* @return The account or null if not found. If more than one is found, the first
* account in the exists is returned.
* @throws GeneralException wrapping underlying DB related errors.
*/
Account getAccountByDisplayName(String applicationName, String displayName)
/**
* Get the first account for the application and identityName and return the first account's native identity.
*
* @param applicationName The application name.
* @param identityName The identity name.
* @return The first link's nativeIdentity.
*
* @throws GeneralException wrapping underlying DB related errors.
*/
public String getFirstAccountNativeIdentity(String applicationName, String identityName)
/**
* Counts the number of accounts on an application.
*
* @param applicationName The application name.
* @return The total number of accounts.
* @throws GeneralException wrapping underlying DB related errors.
*/
int countAccounts(String applicationName)
/**
* Gets the value of an attribute from an account on an application.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or null if the attribute does not exist.
* @throws GeneralException wrapping underlying DB related errors.
*/
Object getRawAccountAttribute(String applicationName, String nativeIdentity, String attribute)
/**
* Gets the value of an attribute from an account on an application.
*
* @param account The account on the application.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or null if the attribute does not exist.
*/
Object getRawAccountAttribute(Account account, String attribute)
/**
* Gets the string value of an attribute from an account on an application.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or null if the attribute does not exist.
* @throws GeneralException wrapping underlying DB related errors.
*/
String getAccountAttribute(String applicationName, String nativeIdentity, String attribute)
/**
* Gets the string value of an attribute from an account on an application.
*
* @param account The account on the application.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or null if the attribute does not exist.
*/
String getAccountAttribute(Account account, String attribute)
/**
* Gets the boolean value of an attribute from an account on an application.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or false if the attribute does not exist.
* @throws GeneralException wrapping underlying DB related errors.
*/
boolean getAccountAttributeBool(String applicationName, String nativeIdentity, String attribute)
/**
* Gets the boolean value of an attribute from an account on an application.
*
* @param account The account on the application.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or false if the attribute does not exist.
*/
boolean getAccountAttributeBool(Account account, String attribute)
/**
* Count the accounts that match the searchable attribute and value.
*
* @param sourceIds The list of application IDs that represent the sources of the data.
* @param attributeName The name of the searchable account attribute. The name parameter is required.
* @param operation The operation to use when matching. It will either be Operation.Equal OR Operation.StartsWith.
* @param values The list of values of the searchable attribute to match. The values parameter is required.
*
* @return The number of accounts matching the parameters provided.
* @throws IllegalStateException wrapping underlying errors
*/
int attrSearchCountAccounts(List<String> sourceIds, String attributeName, String operation, List<String> values)
/**
* Get the identity name for the account matching the specified criteria.
*
* @param sourceIds The list of application IDs that represent the sources of the data
* @param attributeName The name of the searchable account attribute. The name parameter is required.
* @param operation The operation to use when matching. It will either be Operation.Equal OR Operation.StartsWith.
* @param values The list of values of the searchable attribute to match. The values parameter is required.
*
* @return The name of the Identity that matched the account, matching the parameters provided.
* @throws IllegalStateException wrapping underlying errors
*/
String attrSearchGetIdentityName(List<String> sourceIds, String attributeName, String operation, List<String> values)
/**
* Gets the int value of an attribute from an account on an application.
*
* @param applicationName The application name.
* @param nativeIdentity The account's native identity.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or zero if the attribute does not exist.
* @throws GeneralException wrapping underlying DB related errors.
*/
int getAccountAttributeInt(String applicationName, String nativeIdentity, String attribute)
/**
* Gets the int value of an attribute from an account on an application.
*
* @param account The account on the application.
* @param attribute The name of the attribute to retrieve.
* @return The attribute value or zero if the attribute does not exist.
*/
int getAccountAttributeInt(Account account, String attribute)
/**
* Finds the ManagedAttribute description by provided sourceId/name/value/type.
*
* @param sourceId The sourceId used to query the ManagedAttribute.
* @param name The name of the attribute used to query the ManagedAttribute.
* @param value The value of the attribute used to query the ManagedAttribute.
* @param type The type of attribute used to query the ManagedAttribute (see enum ManagedAttribute.Type).
* Defaults to Entitlement (if null provided).
* @return ManagedAttribute's description if found or else null.
* @throws GeneralException wrapping underlying DB related errors.
*/
String getManagedAttributeDescription(String sourceId, String name, String value, ManagedAttribute.Type type)
/**
* Finds the ManagedAttribute by sourceId/name/value/type and returns its details in ManagedAttributeDetails model.
*
* @param sourceId The sourceId used to query the ManagedAttribute.
* @param name The name of the attribute used to query the ManagedAttribute.
* @param value The value of the attribute used to query the ManagedAttribute.
* @param type The type of attribute used to query the ManagedAttribute (see enum ManagedAttribute.Type).
* Defaults to Entitlement (if null provided).
* @return ManagedAttributeDetails if found or else null.
* @throws GeneralException wrapping underlying DB related errors.
*/
public ManagedAttributeDetails getManagedAttributeDetails(String sourceId, String name, String value, ManagedAttribute.Type type)
/**
* Fetch an identity by the internal ID.
*
* @param id The ID to use when fetching an identity object
* @return A DTO representing the Identity. It will throw if the identity is not found.
*/
public sailpoint.rule.Identity getIdentityById(String id) ...
/**
* Find and return the users that match the incoming attributeName, operation, value ordered by
* the specified sortAttribute.
*
* @param attributeName The attribute to be searched. It must be searchable and non-null.
* @param operation The operation to be used when searching. It only allows equals and StartsWith.
* @param value The value to match. It must be non-null.
* @param sortAttribute The attribute to be used when sorting.
* Default ordering is on uid if it is not specified and this also must be searchable.
* Sort is always be in ascending order.
*
* @return The list of users matching the passed in parameters. The max number of returned values is limited to 50.
*
* @throws IllegalStateException when attribute provided is not searchable,
* when the operation is not StartsWith or Equals,
* the sortAttribute is not searchable,
* or if there are issues during the search.
*
* @see #EQUALS_FILTER
* @see #STARTS_WITH_FILTER
*/
public List<sailpoint.rule.Identity> findIdentitiesBySearchableIdentityAttribute(String attributeName, String operation,
String value, String sortAttribute)
/**
* Count and return the number of users matching the incoming attributeName, operation and value.
*
* @param attributeName The attribute to be searched. It must be searchable and non-null.
* @param operation The operation to be used when searching. It only allows equals and StartsWith.
* @param value The value to match. It must be non-null.
*
* @return The number of identities matching the parameters.
*
* @throws IllegalStateException when attribute provided is not searchable,
* when the operation is not StartsWith or Equals,
* or if there are issues during the count operation.
*
* @see #EQUALS_FILTE
* @see #STARTS_WITH_FILTER
*/
public int countIdentitiesBySearchableIdentityAttribute(String attributeName, String operation, String value)
}
```
## Example Usage
### Get an Entitlement Description
```java
//IdnRuleUtil is available in rules as the "idn" variable, which you can use the same way you can currently use context.
/*
* In Before Provisioning rules (where this will likely be used), the source being provisioned to
* is passed in by the "application" variable. You can use this to get sourceId using application.getId().
* e.g. String sourceId = application.getId();
*/
String entitlementDescription = idn.getManagedAttributeDescription(sourceId, attributeName, attributeValue, Type.Entitlement);
```
### Check whether an accountID is Unique
```java
//IdnRuleUtil is available in rules as the "idn" variable, which you can use the same way you can currently use context.
/*
* In Attribute Generator rules (where this will likely be used), the source being provisioned to
* is passed in by the "application" variable. You can use this to get applicationName using application.getName().
* e.g. String applicationName = application.getName();
*/
boolean exists = idn.accountExistsByNativeIdentity(applicationName, nativeIdentity);
```
### Get the Name of the Identity Matching a Specific Account Search Result
```java
//IdnRuleUtil is available in rules as the "idn" variable, which you can use the same way you can currently use context.
String identityName = idn.attrSearchGetIdentityName(sourceIdsAsList, attributeName, Operation.Equal, valuesToMatchAsList);
```
### Get Multiple Attributes from the First Account Retreived From a Source
```java
//IdnRuleUtil is available in rules as the "idn" variable, which you can use the same way you can currently use context.
//Account objects are used with the import statement import sailpoint.rule.Account;
Account acct = idn.getFirstAccount("HR [source]", identity.getName());
Map acctAttrs = acct.getAttributes();
String firstName = acctAttrs.get("First Name");
String lastName = acctAttrs.get("Last Name");
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -0,0 +1,254 @@
---
id: rules
title: Rules
pagination_label: Rules
sidebar_label: Rules
sidebar_position: 2
sidebar_class_name: rules
keywords: ["rules"]
description: Documentation for rule development in IdentityNow.
slug: /docs/rules
tags: ["Rules"]
---
## Overview
In SailPoint solutions, rules serve as a flexible configuration framework
implementers can leverage to preform complex or advanced configurations. Though
rules allow some advanced flexibility, you must take special considerations when
you are deciding to implement rules.
## Rule Execution
IdentityNow is a multi-tenant cloud solution, and its architecture varies differently
from other SailPoint products like IdentityIQ. Therefore, the way rules execute within
IdentityNow reflects the architectural design considerations the platform was built on.
These considerations determine the rule's limitations.
There are two primary places where you can execute rules:
- **Cloud Execution** - These rules are executed in the IdentityNow multi-tenant
cloud.
- **Connector Execution** - These rules are executed on the on-premise
IdentityNow virtual appliance.
![Rule Execution](./img/rule_execution.png)
**Cloud-Executed Rules** or **Cloud Rules** typically only perform a
specific function, such as calculating attribute values.
Many of these rules may be able to query the IdentityNow
data-model in a read-only fashion, but they do not have the ability to
commit transactions, save objects, etc.
Because these rules execute in a multi-tenant cloud environment, they have a restricted context,
and they are closely scrutinized to ensure that they execute in an efficient and secure manner.
For more details, see [Cloud Rules](./cloud-rules/index.md).
**Connector-Executed Rules** or **Connector Rules** are rules executed
in the IdentityNow virtual appliance, and they are often an extension connector itself.
The rules are commonly used for performing complex connector-related functions,
so they are specific to only certain connectors. Because these rules execute in the virtual appliance,
they do not have access to query the IdentityNow data model or fetch information from
IdentityNow. They rely instead on contextual information sent from IdentityNow.
Connector-executed rules may also have managed connections supplied in their
contexts to support querying end systems or sources. Though you may use these
managed connections, you cannot make making additional connections or call-outs.
For more details, see the [Connector Rules](./connector-rules/index.md).
## Support Considerations
Though IdentityNow shares some common functionality with other SailPoint
products like IdentityIQ, the same rules are not necessarily supported,
nor do they necessarily execute the same way or with the same context and variables.
SailPoint recommends that you become familiar with which rules execute with which
products, as well as the nuances in their execution contexts.
From a SailPoint support perspective, rules are considered configurations.
SailPoint supports the underlying platform but not the rule configurations themselves.
Any problems with the way rules are implemented or run over time are the responsibilities
the customer or implementer must manage. SailPoint's IdentityNow Expert Services need hours to
cover any rule configuration work (e.g., creating rules, best practices reviews,
application to your IdentityNow environment, and promotion between sandbox &
prod environments). Contact your Customer Success Manager with any questions.
While rules allow some advanced flexibility, you must consider these support implications
when you are deciding whether to implement rules. Consider rule usage a last resort, and
use IdentityNow features instead whenever you can.
## Rule Guidelines
- **Supported Rules**
- You must use one of the Supported Rules defined in
[Supported Cloud Rules](./cloud-rules/index.md#supported-cloud-rules) and
[Supported Connector Rules](./connector-rules/index.md#supported-connector-rules).
You must also annotate the rule with the correct type.
- Adhere to the rule's purpose as defined in Supported Rules.
Do not use the rule differently from its intended purpose.
- The rules must use only available SailPoint product features, and they must
not make unsupported API calls.
- **Logging**
- Use logging statements sparingly but informatively. Do not make unnecessary
logging calls.
- Do not use `System.out` statements to output data. Internal log aggregators do not pick up these statements.
- If you want rules to log statements, use `log.debug()`, `log.info()`,
`log.warn()`, or `log.error()` statements.
- When you are logging, do not log full object serialization to logs. Calls to
`.toXml()` or similar methods are prohibited.
- Logging of sensitive data is prohibited.
- Do not declare your own loggers in the rule.
- **Execution**
- Do not spawn any additional threads in the rule.
- Connections to systems other than through provided connection contexts are
strictly prohibited.
- Do not call out to external sources, files, services, APIs, etc. unless that
is a connectors purpose. Avoid using file system object manipulation like
opening temp files or spooling to text or CSV files. This can cause
unforeseen issues when connections are leaked or improperly used.
- When you are using conditional execution, do not leave any dead or inaccessible
code. All methods that return values should be able to return a value.
- **Error Handling**
- Use proper error handling including `try { ... }` , `catch { ... }` and
`finally { ... }` blocks to allow exceptions to propagate as intended. This
is especially true of connector-executed rules.
- Do not assume that objects are always available. They can be null. Make sure
that you have proper null checks to prevent Null Pointer Exceptions (NPEs).
- **Security**
- Implement appropriate security measures in rules to ensure proper
handling of user information and prevent its unauthorized use, disclosure,
or access by third parties.
- Logging of sensitive data is prohibited, and it will cause the rule to be rejected.
- Do not include test values, passwords, keys, or sensitive values in the rule
code.
- **Performance**
- Rules should be as performant as possible to achieve the task at hand.
- Be careful with iterative rules execution. Heavily iterative rules will
have greater performance scrutiny.
- Do not iterate over lists of objects like accounts or identities. Doing so
causes cache bloat. Use a projection query wherever possible to find the data
you need, and then return the values you want. If you are unsure, ask
[SailPoint Expert Services](https://www.sailpoint.com/services/professional/#contact-form).
## Rule Code Restrictions
The following code fragments are not allowed in any SailPoint
[Cloud Rules](./cloud-rules/index.md) or
[Connector Rules](./connector-rules/index.md). Any usage of these will be
blocked in the system.
```java
context.
.prepare()
.getJdbcConnection()
.getConnection()
.isClosed()
.setUserName()
.getUserName()
.impersonate()
.setScopeResults()
.getScopeResults()
.getConfiguration()
.encrypt()
.decrypt()
.authenticate()
.sendEmailNotification()
.runRule()
.runScript()
.startTransaction()
.commitTransaction()
.rollbackTransaction()
.getObjectById()
.getObjectByName()
.getObject()
.lockObjectById()
.lockObjectByName()
.lockObject()
.unlockObject()
.getUniqueObject()
.getObjects()
.search()
.update()
.countObjects()
.removeObjects()
.attach()
.decache()
.clearHighLevelCache()
.getReferencedObject()
.enableStatistics()
.printStatistics()
.reconnect()
.setPersistenceOptions()
.getPersistenceOptions()
.setProperty()
.importObject()
.notify()
.notifyAll()
.reconnect()
.removeObject()
SailpointFactory
.toXml()
System.out.
System.err.
Runnable
Thread
public static
.printStackTrace
XMLObjectFactory
Log4j
Logger.getLogger
```
Note that the earlier code fragments are not allowed within
[connector-executed rules](./connector-rules/index.md#supported-connector-rules)
because they are not valid at the connector level. They will, for a short time, still
be allowed for pre-existing [cloud-executed rules](./cloud-rules/index.md) as a
review exception. However, any new rules using these constructs will be returned
to the submitter, and the submitter will be asked to rewrite the rule, using the
[IDN Rule Utility](./idn_rule_utility.md) helper methods instead:
- context
- .getObjectById()
- .getObjectByName()
- .getObject()
- .search()
- .countObjects()
## Other Rules
While IdentityNow shares some common functionality with other SailPoint
products like IdentityIQ, the same rules are not necessarily supported,
nor do they necessarily execute the same way. SailPoint recommends that you become familiar with
which rules execute with which products, as well as the nuances in their execution
contexts. IdentityNow considers any other rules not mentioned in the Cloud-Executed Rules or
Connector-Executed Rules sections to be unsupported.
## Deprecated Rules
The following rules have been deprecated in IdentityNow. SailPoint recommends
using supported product functionality instead of these rules:
- **Certification Exclusion Rules** - Use configurable certification campaign
filters instead.
- **Identity Selector Rules** - Use role standard assignment criteria instead.
- **Integration Rules** - Use
[Before Provisioning](./cloud-rules/before_provisioning_rule.md) rules instead.

View File

@@ -18,10 +18,10 @@ export default function NotFound() {
<h1 className="hero__title">
Page Not Found
</h1>
<img height="60%" src="img/not-found/codey.png"/>
<p>
If you think this document should exist, <a href="https://developer.sailpoint.com/discuss/docs-request" target="_blank" rel="noopener noreferrer">let us know</a>.
Our docs and API specifications have recently movedcheckout the navbar at the top of this page to find their new home. If you can't find the document you're looking for, <a href="https://developer.sailpoint.com/discuss/docs-request" target="_blank" rel="noopener noreferrer">let us know</a>.
</p>
<img height="60%" src="img/not-found/codey.png"/>
</div>
</div>
</main>

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