Temporal entitlement grant workflow example
Identity Governance supports temporal workflows, which let you schedule when a user’s access begins and ends. For example, you can grant a contractor access to an application that starts on their first day and automatically ends when their contract expires.
To build these time-based workflows, you use the Wait node to pause the workflow until the specified start or end date has been established.
Administrators need to carry out the following task:
Example
Task: Create a workflow with the Wait node
Create a new workflow called Basic Entitlement Grant Temporal.
-
1 Use a Script node to perform a context check for the request.
Click to display the request context check script
var content = execution.getVariables(); var requestId = content.get('id'); var context = null; var enableWait = false; var enableEndWait = false; var skipApproval = false; try { // Read request object var requestObj = openidm.action('iga/governance/requests/' + requestId, 'GET', {}, {}); if (requestObj.request.common.context) { context = requestObj.request.common.context.type; if (context == 'admin') { skipApproval = true; } } if (requestObj.request.common.startDate){ enableWait = true; } if (requestObj.request.common.endDate){ enableEndWait = true; } } catch (e) { logger.info("Request Context Check failed " + e.message); } logger.info("Context: " + context); execution.setVariable("context", context); execution.setVariable("enableWait", enableWait); execution.setVariable("enableEndWait", enableEndWait); execution.setVariable("skipApproval", skipApproval); -
2 Use an IF/ELSE node to set the context gateway.
-
3 Use a Script node to run an auto approval.
Click to display the auto approval script
var content = execution.getVariables(); var requestId = content.get('id'); var context = content.get('context'); var skipApproval = content.get('skipApproval'); var queryParams = { "_action": "update" } try { var decision = { "decision": "approved", } if(skipApproval){ decision.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 If a manual approval is required, use an Approval node for the entitlement owner to approve the request.
-
5 Using a Switch node to check if the request has a specified start date.
-
6 If a future start date exists, use a Wait node to pause the workflow until that date is reached.
-
7 If the Approval node has the
Rejectoutcome, use a Script node to deny the request.Click to display the reject request script
logger.info("Rejecting request"); var content = execution.getVariables(); var requestId = content.get('id'); // Complete request as rejected 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); -
8 Use a Script node to run 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 the account doesn't 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) { var err = e.javaException; err = JSON.parse(err.detail); var message = err && err.body ? err.body.response : e.message; failureReason = "Validation failed: Error provisioning new account to user " + request.common.userId + " for application " + applicationId + ". Error message: " + message; } } } if (failureReason) { logger.info("Validation failed: " + failureReason); } execution.setVariable("failureReason", failureReason); -
9 Use the If/Else node to process validation success or failure.
-
10 Use the Script node to provision the entitlement.
Click to provision the entitlement
logger.info("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, "auditContext": {}, "grantType": "request", "requestId": requestObj.id, }; var queryParams = { "_action": "add" } var result = openidm.action('iga/governance/user/' + request.common.userId + '/entitlements' , 'POST', payload,queryParams); } catch (e) { var err = e.javaException; err = JSON.parse(err.detail); var message = err && err.body ? err.body.response : e.message; failureReason = "Provisioning failed: Error provisioning entitlement to user " + request.common.userId + " for entitlement " + request.common.entitlementId + ". Error message: " + message; } var decision = {'status': 'complete', 'decision': 'approved'}; if (failureReason) { decision.outcome = 'not provisioned'; decision.comment = failureReason; decision.failure = true; execution.setVariable('enableEndWait', false); } else { decision.outcome = 'provisioned'; } var queryParams = { '_action': 'update'}; openidm.action('iga/governance/requests/' + requestId, 'POST', decision, queryParams); logger.info("Request " + requestId + " completed."); } -
11 Use the Script node to process the entitlement grant validation failure.
Click to view the script for the entitlement grant validation failure
var content = execution.getVariables(); var requestId = content.get('id'); 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); -
12 Use a switch node to check if there’s an end date. If there’s an end date, run a removal request. If there’s no end date, complete the workflow.
-
13 Use a Script node to create a removal request.
Click to process the removal request
logger.info("Create Removal Request"); 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 = "Create Removal Request failed: Error reading request with id " + requestId; } if(!failureReason){ try{ var request = requestObj.request; var newRequestPayload = { "common":{ "context": { "type": "admin" }, "entitlementId": request.common.entitlementId, "userId": request.common.userId, "endDate": request.common.endDate, "justification": "Request submitted automatically to remove access granted by request: " + requestId } }; var queryParam = { '_action': "publish" } openidm.action('iga/governance/requests/entitlementRemove', 'POST', newRequestPayload, queryParam) }catch(e){ logger.warn('Create Removal Request failed to create') } }
|
Download the JSON file for this workflow here. Learn more about importing or exporting workflows in workflow editor canvas. |