Logiplex - Managing Multiple Applications with One Group

In large organizations, it’s common to encounter multiple applications or application instances that rely on Active Directory (AD) groups for membership. When on-boarding these applications to SailPoint IIQ, Logiplex is a suitable utility available within the SailPoint community. It allows applications to be on-boarded as individual applications linked to AD groups, facilitating access requests, certification, and reporting.

Standard Logiplex Rule
The standard Logiplex rule identifies unique groups for applications. However, in cases where multiple application instances use the same group but need to be represented as separate applications, a modified split rule is required.

Modified Split Rule

The modified split rule works with a customization rule to create multiple application links for the same group, as specified in a custom object. It also creates separate entitlement catalog objects for each application, ensuring that the group description displays correctly for each sub-application.

Here’s a code snippet demonstrating the modified split rule:

import org.apache.log4j.Logger;
import sailpoint.tools.Util;
import sailpoint.object.ResourceObject;
import sailpoint.object.Custom;
import sailpoint.object.Identity;

Logger logger = Logger.getLogger("com.rule.logiplexSplit");
>> public List resolveApplication(String name) {
    List appList = new ArrayList();
    if (Util.isNotNullOrEmpty(name)) {
        //custom object contains groups and application name as key value pair
		Custom customObject = context.getObjectByName(Custom.class, "_Logiplex_Custom");
        if (customObject != null) {
            HashMap hashMap = customObject.getAttributes().getMap();
			logger.debug(" hashMap " + hashMap);
            for (Map.Entry m: hashMap.entrySet()) {
                String groups = m.getKey();
				logger.debug(" groups from map is " + groups);
				List listofGroup = new ArrayList();
				listofGroup = Util.csvToList(groups);
				logger.debug(" listofGroup " + listofGroup);
				logger.debug(" name to match is " + name);
                    if (listofGroup.contains(name)) {
							logger.debug("^^^^^^^^^^^^^^^^^^^ Group found " + name);
							String[] values = m.getValue().split(",");
							if (values.length > 0) {
								logger.debug("^^^^^^^^^^^^^^^^^^^ Application returned " + Arrays.toString(values));
								appList.addAll(Arrays.asList(values));
							} else if (!m.getValue().isEmpty()) {
								logger.debug("^^^^^^^^^^^^^^^^^^^ Application returned " + m.getValue());
								appList.add(m.getValue());
							} else {
								logger.debug("^^^^^^^^^^^^^^^^^^^ Application returned empty value");
							}
							break;
                    }
                }
        }
    }
    if (null == appList || appList.isEmpty()) 
	{
        logger.debug("not matched is----------  " + application.getName());
    }
    return appList;
}
String applicationName = application.getName();
Map map = new HashMap();
if ("account".equals(object.getObjectType())) {
    List groups = object.getStringList("groups");
    //logger.debug("******** Groups are ******* " + groups);
    if (groups != null && !groups.isEmpty()) {
        Map groupMap = new HashMap();
        groupMap = util.updateListMap(groupMap, applicationName, null);
        for (String group: groups) {
            logger.debug(" +++++++++ " + " sending group name to resolve " + group);
			List appNames = resolveApplication(group);
            for (String appName: appNames) {
                if (Util.isNotNullOrEmpty(appName)) {
                    groupMap = util.updateListMap(groupMap, appName.trim(), group);
                }
            }
        }
        logger.debug("Group Map " + groupMap);
        Set keys = groupMap.keySet();
        if (!keys.isEmpty()) {
            for (String key: keys) {
                List appGroups = groupMap.get(key);
                ResourceObject cloneObject = object.deepCopy(context);
                if (!Util.isEmpty(appGroups)) {
                    cloneObject.put("groups", appGroups);
					cloneObject.put("description", "Aggregated with logiplex application aggregation");
                } else {
					//removing this will take groups off from main azure ad account, that may result in existing role assignment issues
                    //cloneObject.remove("memberOf");
                }
                map.put(key, cloneObject);
            }
        } else {
            map.put(applicationName, object);
        }
    } else {
        map.put(applicationName, object);
    }
} 
else if ("group".equals(object.getObjectType())) {
	String nativeIdentity = object.getIdentity();
	List appnamesList= resolveApplication(nativeIdentity);
	
	if (!Util.isEmpty(appnamesList)) 
	{
		for (String appName : appnamesList) 
		{
			ResourceObject cloneGrpObject = object.deepCopy(context);
			map.put(appName, cloneGrpObject);
		}
		//ResourceObject cloneGrpObject = object.deepCopy(context);
		map.put(applicationName, object);
	}
	else
	{
		map.put(applicationName, object);
	}
}else {
    map.put(applicationName, object);
}
return map;

With this modified split rule, you can effectively manage multiple applications that use the same AD group but need to be distinct in SailPoint IIQ.

For more information, visit the Logiplex community or refer to the following URL: https://community.sailpoint.com/t5/Professional-Services/PSLabs-LogiPlex-Connector/ta-p/172304

2 Likes

Hi @abhishek_chowdhury

Would you mind to put ``` on the line before and on a line after the end of the code?

This will make the code way better readable :slight_smile:

Thanks,

– Remold

2 Likes

Hi @abhishek_chowdhury,

Another question regarding your rule :wink:

In your code you are referring to a function in a util class: util.updateListMap

Is it possible to share this function?

Thanks in advance,

– Remold

It is included in the logiplex source file and I got reference of how to use this from the sample of logiplex code. Attaching the logiplex source file it for the refernece
LogiPlexConnector.java (136.4 KB)

1 Like

This is cool, however i always wonder what is the difference between Logiplex and logical connector, I mean we can always achieve similar usecase with logical connector as well.

Would you please let me know the cons of implementing AD based applications in Logical application.

Logical is very performance intensive,that’s one of the biggest drawback i have faced, it used to take forever to finish agg. (atleast in older versions of IIQ). Logiplex is quite fast comapred to it.

I am aware for aggregation it has problem with performance, for this we have removed aggregation completely and have added refresh identity step in workflow itself to refresh logical Application to identityName, which added the link to the user profile after request is provisioned in the AD Group.

1 Like

good to know it works for your use case

1 Like

yes, but i would like to understand more on the real difference between these 2 connectors and best use cases where either of them are suitable respectively. anyway thanks or the rule its helpful.

Hi @dheerajk27,

From the logiplex documentation:

The Logical Connector has a number of performance drawbacks: it requires information to be aggregated and then iterates over identities to find suitable matches. This is often a very time-consuming task. The LogiPlex Connector tries to overcome these issues by processing logical applications on the fly, during aggregation. This approach allows the use of performance-enhancing connector features like partitioning, optimized aggregation and delta aggregation.

A possible downside of the LogiPlex Connector is that it may in some cases be a little harder to set up than a standard Logical Connector. Furthermore, the LogiPlex Connector is less suitable for combining information from multiple tiers, although the aggregation split rule can be used to perform side lookups.

– Remold

2 Likes

Hi @Remold

Apart from the Aggregation challenges in Logical Application, Is there any other drawback you know of from your experience.

Below is one recommendation from SailPoint so just want to know as I may have more than 100 logical applications with single tier pointing to only one AD Connection and I`m not aggregating but using refresh task daily to link the logical application.

1 Like