Identity Cloud

Examples of workflows

This section presents grant workflow examples featuring workflow nodes. For detailed information on each node, refer to Workflow nodes.

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
  • 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 off the outcome, a 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 role Sales App Approver to approve the request.

    • finance — An Approval node requires members ot the fole Finance App Approver to approve the request.

    • humanResources — An Approval node requires members of the role Human 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
  • 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 or null — 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

Example

governance orch example role workflow
  • 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 or null 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.

Copyright © 2010-2024 ForgeRock, all rights reserved.