How to make groups requestable from an application while group aggregation based on some condition

Hi all,

I am writing this post to talk about the group refresh rule, which might be useful for a couple of people. The requirement is that there is one LDAP application called ABP, which contains accounts and groups. The stakeholders’ request is to assign the owners to the group, as shown below.

  1. When SailPoint is pulling groups from the ABP application and finds the owner value for the group, then make it requestable and set the owner for the group. And if the owner is there in the ABP application for the groups, but if we don’t find the user in SailPoint, then make a workgroup backup owner.
  2. Besides this, there are multiple containers (configured in the application) from which SailPoint is pulling groups into IIQ. So while reading, we are only supposed to make requestable groups that are coming from certain containers.

The below code works if you put it in the group refresh rule of the application. And run the group aggregation. If you want, you can update or alter the code according to your requirements later.

Group Refresh Rule:

  import java.util.HashMap;
  import java.util.List;

  import sailpoint.object.Custom;
  import sailpoint.object.Filter;
  import sailpoint.object.Identity;
  import sailpoint.object.QueryOptions;


  //Check if entitlementValue is present in included groups list
  boolean isIncludedGroup(String entitlementValue)
  {
    log.error("Starting isIncludedGroup method");
    boolean isIncluded = false;

    Custom customData = context.getObject(Custom.class, "BPK-ABP-Groups-CNs");
    HashMap includedMap = null;
    if (customData != null) 
    {
      includedMap = customData.getAttributes().getMap();
      List includedList = null;
      if(null != includedMap)
      {
        includedList = includedMap.get("Included_CNs");
        if(null != includedList && includedList.size()>=1)
        {
          for(String listValue : includedList)
          {
            if(entitlementValue.contains(listValue))
            {
              isIncluded = true;
              log.error(entitlementValue +" is included and requestable");
              break;
            }
          }
        }else
        {
          log.error("BPK-ABP-Groups-CNs has no List of included CNs");
        }
      }else
      {
        log.error("BPK-ABP-Groups-CNs has no Map of included CNs");
      }

    }
    log.error("Ending isIncludedGroup method");
    return isIncluded;
  }

  try 
  {
    log.error("Entering into Group Aggregation Refresh Rule of ABP");

    String owner = accountGroup.getAttribute("owner");
    log.error("value of the owner is: "+owner);
    String entValue = accountGroup.getValue();

    if(null != owner && null != entValue)
    {
      boolean found = isIncludedGroup(entValue);

      if(found)
      {
        Filter f1 = Filter.eq("userID", owner);
        QueryOptions ops = new QueryOptions();
        ops.addFilter(f1);

        List listOfIdentities = context.getObjects(Identity.class, ops);

        String name = null;

        if (null != listOfIdentities && listOfIdentities.size()>=1) 
        {
          Identity identity = listOfIdentities.get(0);
          name = identity.getName();
          log.error("name of the owner is: "+name);
        }

        if(name != null)
        {
          log.error("This group is requestable and it is true:");
          accountGroup.setRequestable(true);
          accountGroup.setOwner(context.getObjectByName(Identity.class,name));
          log.error("Requestable is true");
        }
        else
        {
          log.error("We did not find the owner value of the group in SailPoint, but added workgorup (ABP Group Owners) as owner: "+entValue);
          accountGroup.setRequestable(true);
          accountGroup.setOwner(context.getObjectByName(Identity.class,"BPK-ABP-Group-Owners"));
          log.error("Requestable is true");
        }
      }
      else
      {
        log.error("As per requirements the is non requestable because it is excluded group: "+entValue);
        accountGroup.setRequestable(false);
      }

    }
    else
    {
      log.error("We did not find the owner value from native application: "+owner);
      accountGroup.setRequestable(false);
    }

    log.error("Exit from Group Aggregation Refresh Rule of ABP");

  } catch (Exception e) {
    System.err.println("Exception occured at: "+e);
  }

Custom Object:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Custom PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Custom name="BPK-ABP-Groups-CNs">
  <Attributes>
    <Map>
      <entry key="Included_CNs">
        <value>
          <List>
            <String>cn=groups,cn=accounts</String>
            <String>cn=roles,cn=accounts</String>
            <String>cn=privilege,cn=accounts</String>
          </List>
        </value>
      </entry>
    </Map>
  </Attributes>
</Custom>

Workgroup:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Identity PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Identity name="BPK-ABP-Group-Owners" workgroup="true">
  <Attributes>
    <Map>
      <entry key="displayName" value="ABP Group Owners"/>
    </Map>
  </Attributes>
  <Description>This workgroup is used to act as owners for access requests made by people for the ABP application. If the owner of the group is missed, then these people will be received.</Description>
  <Owner>
    <Reference class="sailpoint.object.Identity" name="spadmin"/>
  </Owner>
  <Preferences>
    <Map>
      <entry key="workgroupNotificationOption">
        <value>
          <WorkgroupNotifationOption>Both</WorkgroupNotifationOption>
        </value>
      </entry>
    </Map>
  </Preferences>
</Identity>

If you want, you can update or alter the code according to your requirements later.

5 Likes

Note that you need to disable optimization if you change the logic here, because IIQ will ignore the group object if it hasn’t changed.

I think we need to be very careful with these type of customization . Also i feel we should think of some other approach , the main challenges i see with this types are these custom code check will trigger of for all groups . so i case if you have application with million of entitlements , time to aggregation will increase drastically .

I think goof matrix would be checking time took with and without custom code .

1 Like

Hi @vishal_kejriwal1 , I agree; a feasible approach would be to implement an independent system such as a Service Application/Plugin.

Agree with you :+1:t2:
Happy learning !!

Yes, Obvious thing. We have to do.

Thank you all for responding. It’s all depends on application, it’s behaviour and requirements and how you can tackle this.