How to create multi-level approval for Access Request

Hi community, I am new to development for multi-level approval for access request. May I know if there is any sample rule/workflow that I should write to initiate this. For example, just having 2 levels of approval for an access request for entitlements.

Thank you.

You can try “Approval Assignment Rule”. You might find it in ExampleRules.pdf

1 Like

Hi @anloh , if you want two level approval like 1st level manager and 2nd level Application Owner, just modify the variables in the " LCM Provisioing" workflow.

<Variable initializer="serial" input="true" name="approvalMode"/>
<Variable initializer="manager, owner" input="true" name="approvalScheme"/>

When user raises an request, first it will go the manager, after aproval it will go to the App Owner, after aproval then the account will get provisioned.

2 Likes

Hi @anloh

You can create a Approval Assigment Rule based in the following example code

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule  language="beanshell"  name="Approval Assingment Rule" type="ApprovalAssignment">
  <Signature returnType="null">
    <Inputs>
      <Argument type="log">
        <Description>
The log object associated with the SailPointContext.
</Description>
      </Argument>
      <Argument type="context">
        <Description>
A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
</Description>
      </Argument>
      <Argument type="approvals">
        <Description>
List of approvals generated by the approvalScheme, maybe null if there were no
          approvals enabled.
</Description>
      </Argument>
      <Argument type="approvalSet">
        <Description>
Representation of the cart, also found on the approvals generated by the
          default schemes.
</Description>
      </Argument>
    </Inputs>
    <Returns>
      <Argument type="approvals">
        <Description>
Return a lIst of Workflow.Approval objects that should be included during the approval process.
</Description>
      </Argument>
    </Returns>
  </Signature>
  <Source>
  import sailpoint.object.*;
  import sailpoint.workflow.IdentityApprovalGenerator;
  import sailpoint.tools.xml.XMLObjectFactory;

  Map approvalMap = new HashMap();
  String extraLevelApproval;

  for (ApprovalItem item : approvalSet.getItems()) {
    String itemAppName = item.getApplicationName();
    String itemDisplayName = item.getDisplayName();
    String itemOperation = item.getAttribute("operation");
    String itemName = item.getName();
    String itemValue = null;
    Object itemValueObj =  item.getValue();
    

    if (itemValueObj!=null){
      
      // Multi-value check
      if (itemValueObj instanceof String){
        itemValue = (String) itemValueObj;
      } else{
        itemValue = itemValueObj.get(0);
      }
      
      // Check if role and operation
      if ( null != itemDisplayName &amp;&amp; itemDisplayName.equalsIgnoreCase("Role") &amp;&amp; null != itemOperation &amp;&amp; itemOperation.equalsIgnoreCase("RoleAdd")) {
        
        if (itemValue != null &amp;&amp; !itemValue.isEmpty()) { 
          
          String roleName = itemValue;
          Bundle role = context.getObjectByName(Bundle.class, roleName);
          
          // Checking for additional approvals
          if (null != role &amp;&amp; null != role.getExtendedAttribute("extraLevelApprovals") &amp;&amp; !role.getExtendedAttribute("extraLevelApprovals").isEmpty()){
            
            if (null != role.getExtendedAttribute("extraLevelApprovals") &amp;&amp; !role.getExtendedAttribute("extraLevelApprovals").isEmpty() ){
              
              List extralevellist = Arrays.asList(role.getExtendedAttribute("extraLevelApprovals").split(","));
              
              for (String approver: extralevellist){
                
                ApprovalSet newSet = approvalMap.get(approver);
                if (newSet == null){
                  newSet = new ApprovalSet();
                }
                newSet.add(XMLObjectFactory.getInstance().clone(item, context));
                approvalMap.put(approver, newSet);
              }
            }  
          }
        }
      }
    }
  } 

  // Generate the approval list from the approval map
  IdentityApprovalGenerator iag = new IdentityApprovalGenerator(wfcontext);
  List newApprovals = iag.buildApprovalsFromMap(approvalMap, "approval map");

  if (newApprovals != null) {
    approvals.addAll(newApprovals);
  }

  return approvals;

  </Source>
</Rule>
4 Likes

Hi @anloh . Did any of these replies solve your question? If so, can you please mark the solution? Thanks!

Can you provide details on the requirement as there can be multiple scenarios in assocation to 2 level approval process.
In general, you’ll need to look at approvalScheme and approvalMode variables in the LCM provisioning workflow.
You’ll also need an approval assignment rule to update the approvals in case you need to set a custom approver for a step.
The approval assignment rule need to handle the various approval scenarios.
You can read more about LCM provisioning and the subprocesses in this technical white paper.

Hi @ismaelmoreno1,

Quick question, the in signature the returnType is set to be “null”, shouldn’t the type be “Object” as the rule would be returning approvals ?
<Signature returnType="null">

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.