Examples of workflows
This section presents grant workflow examples featuring workflow nodes. For detailed information on each node, refer to Workflow nodes.
This section covers the following example workflows:
Application grant workflow
In this example, an administrator wants to create an application grant workflow that:
-
Requires the manager to approve the request.
-
If approved, check what line of business (LOB) the application is in.
-
Based on the LOB, the workflow requires a separate approver to approve the request.
Assumptions
-
Each application has an application owner. You populate this value for each target application.
-
You create an application glossary attribute LOB, and populate the LOB for each application. For this scenario, the LOBs are:
-
Sales
-
Finance
-
Human Resources
-
-
Your end users have a manager assigned to them. An administrator populates this property and isn’t modifiable by the end user.
Example
![governance orch example app workflow](../_images/governance-orch-example-app-workflow.png)
-
1 Using an Approval node, the manager of the end user must approve the request.
-
2 If approved, a Script node checks the application glossary attribute
lineOfBusiness
(LOB), and sets the outcome based on the LOB of the application. Based on the outcome, the Switch node evaluates the LOB.Click to display LOB script
var content = execution.getVariables(); var requestId = content.get('id'); var requestObj = null; var appId = null; var appGlossary = null; var lob = null; try { requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); appId = requestObj.application.id; } catch (e) { logger.info("Validation failed: Error reading application grant request with id " + requestId); } try { appGlossary = openidm.action('iga/governance/application/' + appId + '/glossary', 'GET', {}, {}); lob = appGlossary.lineOfBusiness; execution.setVariable("lob", lob); } catch (e) { logger.info("Could not retrieve glossary with appId " + appId + " from application grant request ID " + requestId); }
-
3 If the LOB is:
-
sales
— An Approval node requires members of the roleSales App Approver
to approve the request. -
finance
— An Approval node requires members ot the foleFinance App Approver
to approve the request. -
humanResources
— An Approval node requires members of the roleHuman Resources App Approver
to approve the request. -
null
— An Approval node requires the application owner to approve the request.
-
-
4 If the required approvals are met, a Script node runs a validation check.
Click to display App Grant Validation script
logger.info("Running application grant request validation"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; var applicationId = null; var app = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); applicationId = requestObj.application.id; } catch (e) { failureReason = "Validation failed: Error reading request with id " + requestId; } // Validation 1 - Check application exists if (!failureReason) { try { app = openidm.read('managed/alpha_application/' + applicationId); if (!app) { failureReason = "Validation failed: Cannot find application with id " + applicationId; } } catch (e) { failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message; } } // Validation 2 - Check the user does not already have application granted // Note: this is done at request submission time as well, the following is an example of how to check user's accounts if (!failureReason) { try { var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]); user.effectiveApplications.forEach(effectiveApp => { if (effectiveApp._id === applicationId) { failureReason = "Validation failed: User with id " + requestObj.user.id + " already has effective application " + applicationId; } }) } catch (e) { failureReason = "Validation failed: Unable to check effective applications of user with id " + requestObj.user.id + ". Error message: " + e.message; } } if (failureReason) { logger.info("Validation failed: " + failureReason); } execution.setVariable("failureReason", failureReason);
If any Approval node has the
Reject
outcome, a Script node denies the request.Click to display Reject Request script
logger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); logger.info("Execution Content: " + content); var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
5 If the If/Else node outcome is:
-
validationSuccess
— A Script node provisions the application to the end user.Click to display Auto Provisioning script
logger.info("Auto-Provisioning"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); logger.info("requestObj: " + requestObj); } catch (e) { failureReason = "Provisioning failed: Error reading request with id " + requestId; } if(!failureReason) { try { var request = requestObj.request; var payload = { "applicationId": request.common.applicationId, "startDate": request.common.startDate, "endDate": request.common.endDate, "auditContext": {}, "grantType": "request" }; var queryParams = { "_action": "add" } logger.info("Creating account: " + payload); var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams); } catch (e) { failureReason = "Provisioning failed: Error provisioning account to user " + request.common.userId + " for application " + request.common.applicationId + ". Error message: " + e.message; } var decision = {'status': 'complete', 'decision': 'approved'}; if (failureReason) { decision.outcome = 'not provisioned'; decision.comment = failureReason; decision.failure = true; } else { decision.outcome = 'provisioned'; } var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); }
-
validationFailure
— A Script node doesn’t provision the application to the end user.Click to display Validation Failure script
var content = execution.getVariables(); var failureReason = content.get('failureReason'); var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true, 'decision': 'approved'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
Entitlement grant workflow
In this example, an administrator wants to create an entitlement grant workflow that:
-
Requires an entitlement owner to approve the request.
-
If approved, check if the entitlement is marked as privileged.
-
If the entitlement is privileged or null, the workflow requires an additional approver, the end user’s manager, to approve the request.
Assumptions
-
Each entitlement has an entitlement owner.
-
You create a boolean entitlement glossary attribute ,
isPrivileged
. For each entitlement, this attribute is populated. -
Your end users have a manager assigned to them. An administrator populates this property and isn’t modifiable by the end user.
Example
![governance orch example entitlement workflow](../_images/governance-orch-example-entitlement-workflow.png)
-
1 An Approval node requires the entitlement owner to approve the request.
-
2 A Script node checks the value of the entitlement glossary attribute
isPrivileged
and sets outcomes.Click to display the Entitlement Privileged script
var content = execution.getVariables(); var requestId = content.get('id'); var requestObj = null; var entId = null; var entGlossary = null; var entPriv = null; //Check entitlement exists and grab entitlement info try { requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); entId = requestObj.assignment.id; } catch (e) { logger.info("Validation failed: Error reading entitlement grant request with id " + requestId); } //Check glossary for entitlement exists and grab glossary info try { entGlossary = openidm.action('iga/governance/resource/' + entId + '/glossary', 'GET', {}, {}); entPriv = entGlossary.isPrivileged; execution.setVariable("entPriv", entPriv); } catch (e) { logger.info("Could not retrieve glossary with entId " + entId + " from entitltment grant request ID " + requestId); }
A switch node routes outcomes based off the script. If the outcome is:
-
privileged
ornull
— An additional Approval node requires the end user’s manager to approve the request. -
notPrivileged
— An additional approval isn’t required.
-
-
3 If the required approvals are met, a Script node runs a validation check.
Click to display the Entitlement Grant Validation script
logger.info("Running entitlement grant request validation"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; var applicationId = null; var assignmentId = null; var app = null; var assignment = null; var existingAccount = false; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); applicationId = requestObj.application.id; assignmentId = requestObj.assignment.id; } catch (e) { failureReason = "Validation failed: Error reading request with id " + requestId; } // Validation 1 - Check application exists if (!failureReason) { try { app = openidm.read('managed/alpha_application/' + applicationId); if (!app) { failureReason = "Validation failed: Cannot find application with id " + applicationId; } } catch (e) { failureReason = "Validation failed: Error reading application with id " + applicationId + ". Error message: " + e.message; } } // Validation 2 - Check entitlement exists if (!failureReason) { try { assignment = openidm.read('managed/alpha_assignment/' + assignmentId); if (!assignment) { failureReason = "Validation failed: Cannot find assignment with id " + assignmentId; } } catch (e) { failureReason = "Validation failed: Error reading assignment with id " + assignmentId + ". Error message: " + e.message; } } // Validation 3 - Check the user has application granted if (!failureReason) { try { var user = openidm.read('managed/alpha_user/' + requestObj.user.id, null, [ 'effectiveApplications' ]); user.effectiveApplications.forEach(effectiveApp => { if (effectiveApp._id === applicationId) { existingAccount = true; } }) } catch (e) { failureReason = "Validation failed: Unable to check existing applications of user with id " + requestObj.user.id + ". Error message: " + e.message; } } // Validation 4 - If account does not exist, provision it if (!failureReason) { if (!existingAccount) { try { var request = requestObj.request; var payload = { "applicationId": applicationId, "startDate": request.common.startDate, "endDate": request.common.endDate, "auditContext": {}, "grantType": "request" }; var queryParams = { "_action": "add" } logger.info("Creating account: " + payload); var result = openidm.action('iga/governance/user/' + request.common.userId + '/applications' , 'POST', payload,queryParams); } catch (e) { failureReason = "Validation failed: Error provisioning new account to user " + request.common.userId + " for application " + applicationId + ". Error message: " + e.message; } } } if (failureReason) { logger.info("Validation failed: " + failureReason); } execution.setVariable("failureReason", failureReason);
If any Approval node has the
Reject
outcome, a Script node denies the request.Click to display Reject Request script
logger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); logger.info("Execution Content: " + content); var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
4 If the If/else node outcome is:
-
validationFlowSuccess
— A Script node provisions the application to the end user.Click to display Auto Provisioning script
logger.info("Auto-Provisioning"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); logger.info("requestObj: " + requestObj); } catch (e) { failureReason = "Provisioning failed: Error reading request with id " + requestId; } if(!failureReason) { try { var request = requestObj.request; var payload = { "entitlementId": request.common.entitlementId, "startDate": request.common.startDate, "endDate": request.common.endDate, "auditContext": {}, "grantType": "request" }; var queryParams = { "_action": "add" } var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams); } catch (e) { failureReason = "Provisioning failed: Error provisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + e.message; } var decision = {'status': 'complete', 'decision': 'approved'}; if (failureReason) { decision.outcome = 'not provisioned'; decision.comment = failureReason; decision.failure = true; } else { decision.outcome = 'provisioned'; } var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); }
-
validationFlowFailure
— A Script node doesn’t provision the application to the end user.Click to display Validation Failure script
var content = execution.getVariables(); var failureReason = content.get('failureReason'); var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true, 'decision': 'approved'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
Role grant workflow
In this example, an administrator wants to create a role grant workflow that:
-
Checks the risk level of the role.
-
Based on the risk level, separate approvals are required. Specifically, if the risk level is
high
, send two approvals, in parallel, to the end user’s manager and the role owner.
Assumptions
-
Each role has a role owner.
-
You create a role glossary attribute (string with enumerated value),
riskLevel
, that has the following values:-
low
-
medium
-
high
For each role, this attribute is populated.
-
-
Your end users have a manager assigned to them. An administrator populates this property and isn’t modifiable by the end user.
Example
![governance orch example role workflow](../_images/governance-orch-example-role-workflow.png)
-
1 A Script node checks the value of the role glossary attribute
riskLevel
and sets outcomes.Click to display risk level script
var content = execution.getVariables(); var requestId = content.get('id'); var requestObj = null; var roleId = null; var roleGlossary = null; var riskLevel = null; try { requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); riskId = requestObj.risk.id; } catch (e) { logger.info("Validation failed: Error reading role grant request with id " + requestId); } try { roleGlossary = openidm.action('iga/governance/role/' + roleId + '/glossary', 'GET', {}, {}); riskLevel = roleGlossary.riskLevel; execution.setVariable("riskLevel", riskLevel); } catch (e) { logger.info("Could not retrieve glossary with roleId " + roleId + " from role grant request ID " + requestId); }
-
2 A Switch node determines the path to take based off the Script node.
-
3 If the risk level is:
-
low
— An Approval node requires either the role owner or the end user’s manager to approve the request. -
medium
— An Approval node requires the role owner to approve the request.
-
-
4 If the risk level is
high
ornull
then:-
A Switch node sends two approval tasks in parallel.
-
An Approval node requires the role owner to approve the request.
-
An Approval node requires the end user’s manager to approve the request.
-
A closing Switch node waits for both approvals before proceeding to provision the role.
-
-
5 If the required approvals are met, a Script node runs a validation check.
Click to display the Role Grant Validation script
logger.info("Running role grant request validation"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; var roleId = null; var role = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); roleId = requestObj.role.id; } catch (e) { failureReason = "Validation failed: Error reading request with id " + requestId; } // Validation 1 - Check role exists if (!failureReason) { try { role = openidm.read('managed/alpha_role/' + roleId); if (!role) { failureReason = "Validation failed: Cannot find role with id " + roleId; } } catch (e) { failureReason = "Validation failed: Error reading role with id " + roleId + ". Error message: " + e.message; } } if (failureReason) { logger.info("Validation failed: " + failureReason); } execution.setVariable("failureReason", failureReason);
If any Approval node has the
Reject
outcome, a Script node denies the request.Click to display Reject Request script
logger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); logger.info("Execution Content: " + content); var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
6 If the If/else node outcome is:
-
validationFlowSuccess
— A Script node provisions the application to the end user.Click to display Auto Provisioning script
logger.info("Auto-Provisioning"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); logger.info("requestObj: " + requestObj); } catch (e) { failureReason = "Provisioning failed: Error reading request with id " + requestId; } if(!failureReason) { try { var request = requestObj.request; var payload = { "roleId": request.common.roleId, "startDate": request.common.startDate, "endDate": request.common.endDate, "auditContext": {}, "grantType": "request" }; var queryParams = { "_action": "add" } var result = openidm.action('iga/governance/user/' + request.common.userId + '/roles' , 'POST', payload,queryParams); } catch (e) { failureReason = "Provisioning failed: Error provisioning role to user " + request.common.userId + " for role " + request.common.roleId + ". Error message: " + e.message; } var decision = {'status': 'complete', 'decision': 'approved'}; if (failureReason) { decision.outcome = 'not provisioned'; decision.comment = failureReason; decision.failure = true; } else { decision.outcome = 'provisioned'; } var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); }
-
validationFlowFailure
— A Script node doesn’t provision the application to the end user.Click to display Validation Failure script
var content = execution.getVariables(); var failureReason = content.get('failureReason'); var decision = {'outcome': 'not provisioned', 'status': 'complete', 'comment': failureReason, 'failure': true, 'decision': 'approved'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
Role remove workflow
In this example, an administrator wants to create a workflow that:
-
Handles a normal role removal access request.
-
Includes a context check for administrator-submitted requests.
-
If the context check passes, the workflow skips the approval task process and runs auto-approval and auto-deprovisioning scripts.
Assumptions
-
Each role has a role owner.
-
Notification settings and email templates exist.
-
Make sure to catch any error/failure conditions.
Example
![governance workflow example role removal](../_images/governance-workflow-example-role-removal.png)
-
1 The Script node invokes the APIs and checks the context. If the context is
admin
orcertification
, it skips the manual approval process.Click to display request context check script
var content = execution.getVariables(); var requestId = content.get('id'); var context = null; var skipApproval = false; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); if (requestObj.request.common.context) { context = requestObj.request.common.context.type; if (context === 'admin' || context === 'certification') { skipApproval = true; } } } catch (e) {} logger.info("Context: " + context); execution.setVariable("context", context); execution.setVariable("skipApproval", skipApproval);
-
2 The Approval node assigns an approval task to users and roles. The node chains tasks in conjunction with a Switch node to implement serial or parallel flows.
Click to display the approval task properties
Item Description Name
Approval Task
Approvers
Two options are available:
-
Add users and roles manually, such as
Role Owner
and defineApprover
type-
Approve
-
Reject
-
Reassign
-
Modify
-
Comment
-
-
Define users using a script:
Expiration Settings
Options are:
-
Reject request
-
Reassign request
-
Do nothing
Notification Settings
Options are:
-
Assignment notification and email template, such as
requestAssigned
. -
Reassignment notification and email template, such as
requestReassigned
. -
Assignee reminders and email template, such as
requestReminder
.-
Sends every number of time period, such as
3 day(s)
.
-
-
Escalation notifications and email template, such as
requestEscalated
.-
Send everny number of day(s), such as
5 day(s)
. -
Send to
Send escalation to
toUser
, and selectUser
.
-
-
Expiration notification and email template, such as
requestExpired
.-
Send: number of days before expiration.
-
-
-
3 Invokes the auto-approval script if
scriptApproval
is true.Click to display auto-approval script
var content = execution.getVariables(); var requestId = content.get('id'); var context = content.get('context'); var queryParams = { "_action": "update" } try { var decision = { "decision": "approved", "comment": "Request auto-approved due to request context: " + context } openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); } catch (e) { var failureReason = "Failure updating decision on request. Error message: " + e.message; var update = {'comment': failureReason, 'failure': true}; openidm.action('iga/governance/requests/' + requestId, 'POST', update, queryParams); }
-
4 Runs a
RejectRequest
script whenApproval task
node returns areject
.Click to display
RejectRequest
scriptlogger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); logger.info("Execution Content: " + content); var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
-
5 Run Auto Deprovisioning script.
Click to display the auto deprovisioning script
logger.info("Auto-Deprovisioning"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); logger.info("requestObj: " + requestObj); } catch (e) { failureReason = "Deprovisioning failed: Error reading request with id " + requestId; } if(!failureReason) { try { var request = requestObj.request; var payload = { "roleId": request.common.roleId, "startDate": request.common.startDate, "endDate": request.common.endDate, "auditContext": {}, "grantType": "request" }; var queryParams = { "_action": "remove" } var result = openidm.action('iga/governance/user/' + request.common.userId + '/roles' , 'POST', payload,queryParams); } catch (e) { failureReason = "Deprovisioning failed: Error deprovisioning role to user " + request.common.userId + " for role " + request.common.roleId + ". Error message: " + e.message; } var decision = {'status': 'complete', 'decision': 'approved'}; if (failureReason) { decision.outcome = 'not provisioned'; decision.comment = failureReason; decision.failure = true; } else { decision.outcome = 'provisioned'; } var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); }
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
Violation workflow
In this example, an administrator creates a workflow that:
-
Processes a single violation task.
-
If the violation outcome is
Remediate
, it remediates the violation, validates the result, and removes the entitlements. -
If the violation outcome is
Allow
, it creates an exception. -
If the violation outcome is
expiration
, it goes to a manual decision via the Fulfillment node. -
If the end user tasked with the manual fulfillment approves of the various outcomes, the workflow is complete.
-
If the end user tasked with the manual fulfillment denies the resulting outcomes, the workflows calls a reject requests script, and loops back for another manual confirmation.
Example
![governance workflow example violation](../_images/governance-workflow-example-violation.png)
-
1 The Violation node routes the violation to the appropriate outcome. Options are:
Remediate
,Allow
, andExpiration
. -
2 The Remediate Violation Script node gets the context information for the violation and sets the
remediationResponse
.Click to display Remediate Violation script
logger.info("Remediating violation"); var content = execution.getVariables(); var violationId = content.get('id'); var remediation = content.get('remediation'); logger.info("Remediating violation - violationId: " + violationId + ', remediation payload: ' + remediation); var remediationContent = null; var remediationResponse = openidm.action('iga/governance/violation/' + violationId + '/remediate', 'POST', remediation); logger.info("Remediating response: " + remediationResponse); remediationContent = remediationResponse.decision.remediation; execution.setVariable("remediation", remediationContent);
-
3 The Remediate Violation IF/ELSE node routes successful validations to an auto remove script node and validation failures to a failure handling node.
-
4 The Remove Grants Auto script node removes the entitlement grants that caused the violation.
Click to display Auto Remove Entitlement Grants script
logger.info("Removing grants automatically"); var content = execution.getVariables(); var violationId = content.get('id'); var failureReason = null; var phaseName = content.get('phaseName'); var violationObj; logger.info("Removing entitlement grants for violation " + violationId + " with phase name " + phaseName); try { violationObj = openidm.action('iga/governance/violation/lookup/' + violationId, 'GET', {}, {}); } catch (e) { failureReason = "Removing entitlement grants failed: Error reading violation with id " + violationId + ". Error message: " + e.message; } if (!failureReason) { var remediation = violationObj.decision.remediation; var failedDeprovisioning = false; var deprovisionedIds = []; for(var grant of violationObj.violatingAccess) { if (!remediation.grantIds.includes(grant.compositeId)) { continue; } var userId = violationObj.user.id; logger.info("Removing entitlement grant: " + grant.compositeId + ", user: " + userId + ", violation: " + violationId); try { var payload = { entitlementId: grant.assignment.id }; logger.info('Payload to remove grant: ' + JSON.stringify(payload)); var queryParams = { "_action": "remove" } var result = openidm.action('iga/governance/user/' + userId + '/entitlements', 'POST', payload,queryParams); execution.setVariables(result); logger.info("Deprovisioned " + grant.assignment.id + " successfully, user " + userId + + ", violation: " + violationId); deprovisionedIds.push(grant.compositeId); } catch (e) { failureReason = failureReason + ". Removing grants failed: Error deprovisioning entitlement" + grant.assignment.id + " from user. Error message: " + e.message + "."; failedDeprovisioning = true; } } if (!failedDeprovisioning) { openidm.action('iga/governance/violation/' + violationId + '/remediation/status/complete', 'POST', {}); } else { failureReason = failureReason + ". Grants removed: " + deprovisionedIds; } } if (failureReason) { var update = { 'comment': failureReason }; openidm.action('iga/governance/violation/' + violationId + '/comment', 'POST', update, {}); }
-
5 The Allow Violation script node logs the information. If a failure arises, Identity Governance posts the failure with the reason.
Click to display Allow Violation script node
logger.info("Allowing violation"); var content = execution.getVariables(); var violationId = content.get('id'); var phaseName = content.get('phaseName'); logger.info("Violation to be allowed: " + violationId + " with phase name " + phaseName); var failureReason = null; try { var allowResponse = openidm.action('iga/governance/violation/' + violationId + '/allow', 'POST', {}); logger.info("Violation " + violationId + " was allowed successfully.");} catch (e) { failureReason = "Failed allowing violation with id " + violationId + ". Error message: " + e.message; } if (failureReason) { var update = { "comment": failureReason }; try { openidm.action('iga/governance/violation/' + violationId + '/phases/' + phaseName + '/comment', 'POST', update, {}); } catch (e) { openidm.action('iga/governance/violation/' + violationId + '/comment', 'POST', update, {}); } }
-
6 The Fulfillment node requests a manual completion of the task by an authorized end user, typically during review time. If successful, the task is fulfilled and the workflow is complete.
-
7 The Reject Request script node retrieves the
requestID
, logs the rejection, and sends a reject request.Click to display Reject Request script
logger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); logger.info("Execution Content: " + content); var requestIndex = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var decision = {'outcome': 'denied', 'status': 'complete', 'decision': 'rejected'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams);
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
User create event workflow - send email
In this example, an administrator creates a workflow that:
-
Sends an email notification to the new user when a user create event occurs.
-
Also, copies their manager if present.
Example
![governance workflow example user create event send email](../_images/governance-workflow-example-user-create-event-send-email.png)
-
1 The Script node sends email to the new user and cc’s to the user’s manager.
Click to display send email script
logger.info("Running user create event role workflow - send email"); var content = execution.getVariables(); var requestId = content.get('id'); // Read event user information from request object try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var userObj = requestObj.request.common.blob.after; var userDisplayName = userObj.givenName + " " + userObj.sn + " (" + userObj.userName + ")"; var body = { subject: "New user created: " + userDisplayName, to: userObj.mail, body: "New user created: " + userDisplayName + ".", object: {} }; if (userObj && userObj.manager && userObj.manager.mail) { body.cc = userObj.manager.mail }; openidm.action("external/email", "send", body); } catch (e) { logger.info("Unable to send new user creation email"); } // Update event request as final var decision = {'status': 'complete', 'outcome': 'fulfilled', 'decision': 'approved'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed.");
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
User create event workflow - catalog lookup
In this example, In this example, an administrator creates a workflow that:
-
Submits a request to add the
Data Analyst
andSecurity
roles to a newly created user when a user create event occurs. -
Looks up the two roles in the catalog.
Example
![governance workflow example user create event catalog lookup](../_images/governance-workflow-example-user-create-event-catalog-lookup.png)
-
1 The Script node looks up two roles in the catalog. If the roles are present in the catalog, the script generates a request for roles.
Click to display
Submit Request for Roles
scriptlogger.info("Running user create event role workflow"); var content = execution.getVariables(); var requestId = content.get('id'); var failureReason = null; var userObj = null; var userId = null; // Read event user information from request object try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); userObj = requestObj.request.common.blob.after; userId = userObj.userId; } catch (e) { failureReason = "Validation failed: Error reading request with id " + requestId; } // Define roles to request var roleNames = [ "Data Analyst", "Security" ]; // Look up roles in catalog var operand = []; for (var index in roleNames) { operand.push({operator: "EQUALS", operand: { targetName: "role.name", targetValue: roleNames[index] }}) } var body = { targetFilter: {operator: "OR", operand: operand}}; var catalog = openidm.action("iga/governance/catalog/search", "POST", body); var catalogResults = catalog.result; // Define request catalogs key var catalogBody = []; for (var idx in catalogResults) { var catalog = catalogResults[idx]; catalogBody.push({type: "role", id: catalog.id}) } // Define request payload var requestBody = { priority: "low", accessModifier: "add", justification: "Request submitted on user creation.", users: [ userId ], catalogs: catalogBody }; // Create requests try { openidm.action("iga/governance/requests", "POST", requestBody, {_action: "create"}) } catch (e) { failureReason = "Unable to generate requests for roles"; } // Update event request as final var decision = failureReason ? {'status': 'complete', 'outcome': 'cancelled', 'decision': 'rejected', 'comment': failureReason, 'failure': true} : {'status': 'complete', 'outcome': 'fulfilled', 'decision': 'approved'}; var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed.");
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |
User create event workflow - request two roles
In this example, In this example, an administrator creates a workflow that:
-
Submits a separate request to add two roles to the newly created user. The script is triggered when a user create event occurs.
Example
![governance workflow example user create event request roles](../_images/governance-workflow-example-user-create-event-request-roles.png)
-
1 The Script node gets a user ID from the event request and returns the user object.
Click to display
Get User ID from event request
scriptlogger.info("Get User Id From Event Request: UserCreateEventWithSteps"); var content = execution.getVariables(); var requestId = content.get('id'); // Read event user information from request object try { var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); var userObj = requestObj.request.common.blob.after; execution.setVariable("userId", userObj.userId); } catch (e) { execution.setVariable("failureState", "Validation failed: Error reading request with id " + requestId); }
-
2 The Script node makes a call to create the request. The payload contains two catalog IDs for the
Data Analyst
andSecurity
roles.Click to display
Submit request for roles
scriptlogger.info("Submit Role Requests: UserCreateEventWithSteps"); var content = execution.getVariables(); var userId = content.get('userId'); var failureState = content.get('failureState'); // Define request payload if (!failureState) { var requestBody = { priority: "low", accessModifier: "add", justification: "Request submitted on user creation: UserCreateEventWithSteps.", users: [ userId ], catalogs: [ { type: "role", id: "b9224b9ae535c9eab3f493dc206ac689dc9f6733b417d0def37f8969bef3e95dad7c812e4585056f698c7b3eb15c970dfa939eca8217741af187978359af13df"}, { type: "role", id: "e7ec51656c6f5ca297d82772a681e3069d8a7c24c04f15afaa8060856e17ad6e76f88bdeb635d4dc8c3d8faa462f376189322e85df379ae0721fcb2d28d1a222"} ] }; // Create requests try { openidm.action("iga/governance/requests", "POST", requestBody, {_action: "create"}) } catch (e) { execution.setVariable("failureState", "Unable to generate requests for roles"); } }
-
3 The Script node completes the request.
Click to display
Finalize request
scriptlogger.info("Finalize Request: UserCreateEventWithSteps"); var content = execution.getVariables(); var requestId = content.get('requestId'); var failureState = content.get('failureState'); if (!failureState) { try { // Update event request as final var decision = {'status': 'complete', 'outcome': 'fulfilled', 'decision': 'approved'} var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); } catch (e) { execution.setVariable("failureState", "Unable to finalize request."); } }
-
4 The Script node handles any failures.
Click to display
Failure handler
scriptlogger.info("Failure Handler: UserCreateEventWithSteps"); var content = execution.getVariables(); var requestId = content.get('requestId'); var failureReason = content.get('failureReason'); // Update event request as final if (failureReason) { var decision = {'status': 'complete', 'outcome': 'cancelled', 'decision': 'rejected', 'comment': failureReason, 'failure': true} var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); }
The User create event workflow - send email, User create event workflow - catalog lookup, and User create event workflow - request two roles examples present
User create
event workflows. However, you can also adjust the workflows forUser update
events. For example, in theUser create
examples, the user object returns the current or after state of the user:var userObj = requestObj.request.common.blob.after
Update events also have access to the before (or pre-update) state by referencing the object, which you can also use in your scripts.
var userObj = requestObj.request.common.blob.before
Download the JSON file for this workflow here. For information on how to import or export workflows, refer to Workflow UI canvas. |