mirror of
https://github.com/LukeHagar/developer.sailpoint.com.git
synced 2025-12-06 12:27:46 +00:00
Merge branch 'main' into feature/upgrade-open-api-generator
This commit is contained in:
5
.firebaserc
Normal file
5
.firebaserc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"default": "developer-community-site"
|
||||||
|
}
|
||||||
|
}
|
||||||
54
.github/bot.yml
vendored
54
.github/bot.yml
vendored
@@ -38,11 +38,59 @@ labelPRBasedOnFilePath:
|
|||||||
- navbar.js
|
- navbar.js
|
||||||
Plugins:
|
Plugins:
|
||||||
- plugins.js
|
- 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 ########################################################################################################
|
##### Greetings ########################################################################################################
|
||||||
# Comment to be posted to welcome users when they open their first PR
|
# Comment to be posted to welcome users when they open their first PR
|
||||||
firstPRWelcomeComment: >
|
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
|
# Comment to be posted to congratulate user on their first merged PR
|
||||||
firstPRMergeComment: >
|
firstPRMergeComment: >
|
||||||
@@ -50,4 +98,4 @@ firstPRMergeComment: >
|
|||||||
|
|
||||||
# Comment to be posted to on first time issues
|
# Comment to be posted to on first time issues
|
||||||
firstIssueWelcomeComment: >
|
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! 🙌
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ concurrency:
|
|||||||
group: "pages"
|
group: "pages"
|
||||||
cancel-in-progress: true
|
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
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
|
|||||||
19
.github/workflows/firebase-hosting-pull-request.yml
vendored
Normal file
19
.github/workflows/firebase-hosting-pull-request.yml
vendored
Normal 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
|
||||||
35
.github/workflows/test-build.yml
vendored
35
.github/workflows/test-build.yml
vendored
@@ -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
|
|
||||||
@@ -7,12 +7,13 @@ const darkCodeTheme = require("prism-react-renderer/themes/dracula");
|
|||||||
const footer = require("./footer");
|
const footer = require("./footer");
|
||||||
const navbar = require("./navbar");
|
const navbar = require("./navbar");
|
||||||
const plugins = require("./plugins");
|
const plugins = require("./plugins");
|
||||||
|
const baseUrl = process.env.BASE_URL ?? '/';
|
||||||
|
|
||||||
/** @type {import('@docusaurus/types').Config} */
|
/** @type {import('@docusaurus/types').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
title: "SailPoint Developer Community",
|
title: "SailPoint Developer Community",
|
||||||
url: "https://developer.sailpoint.com",
|
url: "https://developer.sailpoint.com",
|
||||||
baseUrl: "/developer.sailpoint.com/",
|
baseUrl,
|
||||||
favicon: "img/SailPoint-Logo-Icon.ico",
|
favicon: "img/SailPoint-Logo-Icon.ico",
|
||||||
onBrokenLinks: "warn",
|
onBrokenLinks: "warn",
|
||||||
onBrokenMarkdownLinks: "warn",
|
onBrokenMarkdownLinks: "warn",
|
||||||
|
|||||||
10
firebase.json
Normal file
10
firebase.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"hosting": {
|
||||||
|
"public": "build",
|
||||||
|
"ignore": [
|
||||||
|
"firebase.json",
|
||||||
|
"**/.*",
|
||||||
|
"**/node_modules/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ module.exports = [
|
|||||||
docsPluginId: "idn",
|
docsPluginId: "idn",
|
||||||
config: {
|
config: {
|
||||||
idn_v3: {
|
idn_v3: {
|
||||||
specPath: "static/idn-api/sailpoint-api.v3.yaml",
|
specPath: "static/api-specs/idn/sailpoint-api.v3.yaml",
|
||||||
outputDir: "products/idn/api/v3",
|
outputDir: "products/idn/api/v3",
|
||||||
sidebarOptions: {
|
sidebarOptions: {
|
||||||
groupPathsBy: "tag",
|
groupPathsBy: "tag",
|
||||||
@@ -49,7 +49,7 @@ module.exports = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
idn_beta: {
|
idn_beta: {
|
||||||
specPath: "static/idn-api/sailpoint-api.beta.yaml",
|
specPath: "static/api-specs/idn/sailpoint-api.beta.yaml",
|
||||||
outputDir: "products/idn/api/beta",
|
outputDir: "products/idn/api/beta",
|
||||||
sidebarOptions: {
|
sidebarOptions: {
|
||||||
groupPathsBy: "tag",
|
groupPathsBy: "tag",
|
||||||
@@ -66,7 +66,7 @@ module.exports = [
|
|||||||
docsPluginId: "iiq",
|
docsPluginId: "iiq",
|
||||||
config: {
|
config: {
|
||||||
iiq: {
|
iiq: {
|
||||||
specPath: "static/iiq-api/swagger.json",
|
specPath: "static/api-specs/iiq/swagger.json",
|
||||||
outputDir: "products/iiq/api",
|
outputDir: "products/iiq/api",
|
||||||
sidebarOptions: {
|
sidebarOptions: {
|
||||||
groupPathsBy: "tag",
|
groupPathsBy: "tag",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ id: event-triggers
|
|||||||
title: Event Triggers
|
title: Event Triggers
|
||||||
pagination_label: Event Triggers
|
pagination_label: Event Triggers
|
||||||
sidebar_label: Event Triggers
|
sidebar_label: Event Triggers
|
||||||
sidebar_position: 2
|
sidebar_position: 3
|
||||||
sidebar_class_name: eventTriggers
|
sidebar_class_name: eventTriggers
|
||||||
keywords: ["event", "triggers", "webhooks"]
|
keywords: ["event", "triggers", "webhooks"]
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -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
|
see what is possible! This documentation assumes that you are a current customer
|
||||||
or partner and already have access to the IdentityNow application.
|
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
|
Looking to become a partner? If you are interested in becoming a partner, be it
|
||||||
an ISV or Channel/Implementation partner,
|
an ISV or Channel/Implementation partner,
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
189
products/idn/docs/identity-now/rules/cloud-rules/generic_rule.md
Normal file
189
products/idn/docs/identity-now/rules/cloud-rules/generic_rule.md
Normal 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
151
products/idn/docs/identity-now/rules/cloud-rules/index.md
Normal file
151
products/idn/docs/identity-now/rules/cloud-rules/index.md
Normal 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:
|
||||||
|
- `&` should be `&`
|
||||||
|
- `<` should be `<`
|
||||||
|
- `>` 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.
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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")
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
| Argument | Type | Purpose |
|
||||||
|
| ----------- | ---------------------------- | ---------------------------------------------------------------------------------------------- |
|
||||||
|
| col | java.util.List | Ordered list of the column names from the file’s 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>
|
||||||
|
```
|
||||||
281
products/idn/docs/identity-now/rules/connector-rules/index.md
Normal file
281
products/idn/docs/identity-now/rules/connector-rules/index.md
Normal 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 rule’s 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` - Rule’s 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
@@ -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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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>
|
||||||
|
```
|
||||||
619
products/idn/docs/identity-now/rules/idn_rule_utility.md
Normal file
619
products/idn/docs/identity-now/rules/idn_rule_utility.md
Normal 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");
|
||||||
|
```
|
||||||
BIN
products/idn/docs/identity-now/rules/img/cloud_execution.png
Normal file
BIN
products/idn/docs/identity-now/rules/img/cloud_execution.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
BIN
products/idn/docs/identity-now/rules/img/connector_execution.png
Normal file
BIN
products/idn/docs/identity-now/rules/img/connector_execution.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
BIN
products/idn/docs/identity-now/rules/img/rule_execution.png
Normal file
BIN
products/idn/docs/identity-now/rules/img/rule_execution.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
254
products/idn/docs/identity-now/rules/index.md
Normal file
254
products/idn/docs/identity-now/rules/index.md
Normal 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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**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 connector’s 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.
|
||||||
@@ -18,10 +18,10 @@ export default function NotFound() {
|
|||||||
<h1 className="hero__title">
|
<h1 className="hero__title">
|
||||||
Page Not Found
|
Page Not Found
|
||||||
</h1>
|
</h1>
|
||||||
<img height="60%" src="img/not-found/codey.png"/>
|
|
||||||
<p>
|
<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 moved—checkout 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>
|
</p>
|
||||||
|
<img height="60%" src="img/not-found/codey.png"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user