Share all details about your problem, including any error messages you may have received.
We have a requirement to create different logical applications based on certain AD groups membership(identified using naming convention pattern or hardcoded names of the ad groups). Eg. If User A’s AD account is a member of any of the Group A1, A2,A3 then he should have Application A. We want to have some segregation / grouping of people that will allow us to have better governance which will in turn allow us to manage certifications using these new apps so that the respective certifiers can take the action and the provisioning should be triggered on the actual AD application. Also these applications will also help with reports and dashboards.
I’m currently going through the Logical, Multiplex and Logiplex connector documents to understand which would fit better for these requirements.
Thanks for your response, I’m going through the document, the question i have is would using the Adaptor mode in the Logiplex make sense or the classic?
Its up to you , but i would say Adaptor Mode . You won’t have to onboard one more application to drive the functionality . Just put couple of rules and you are all set .
I tried configuring in Adaptor mode, the application was generated, however, the new sub application generated did not have any accounts as such, how do i make it show accounts? Also i noticed that the sub application did not have any configuration details, ou details, schema attributes etc. What all do i need to copy for my requirements?
Hi @menno_pieters - I have been trying to use Logiplex in Adapter mode for AD application.
I’ve updated the AD application connector class to logiplex and add the masterconnector and the split rule details for the app. The sub application gets generated when i run aggregation for this AD app but it doesn’t show any accounts under the sub applications.
When i tried the classic mode setup - existing AD app(master), logiplex (main app) configured the same split rule on the main app and ran aggregation for main app it generate the sub applications and it also show the accounts under the sub apps.
The only thing i can think of is that our AD app has only these feature strings “MANAGER_LOOKUP, SEARCH, UNSTRUCTURED_TARGETS, AUTHENTICATE” as the provisioning is handled by another webservices app that we have and it uses provisioning config using which all the provisioning requests sent to AD are routed to this webservices app.
Could the missing feature strings be causing issues in Adapter mode? or is there something else I’m missing?
The ‘PROVISIONING’ or provisoning integration flag shouldn’t be related to missing sub-accounts. I’m not sure what’s going on, but most often the issue is with the split rule.
Thanks for your reply, I was able to get past the issue, it seems like it was due to partitioning enabled in the account aggregation task. I have noticed that when partitioning is enabled there are lot of weird behaviors, like some times no accounts are showing up under the generated apps, some times applications itself don’t get generated. As soon as I disabled partitioning it started to work fine.
Are you aware about any issues with partitioning? Below is my split rule, please let me know if you see any issues.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule language="beanshell" name="SplitRule" type="ResourceObjectCustomization">
<Description>This rule is configured on the application and is called after the connector has build a ResourceObject from the native application data.
Initially designed for non-rule based connectors to add SPPrivileged flag to an object, but could be used to do any transformations.</Description>
<Signature returnType="ResourceObject"/>
<Source><![CDATA[
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import sailpoint.object.Custom;
import sailpoint.api.SailPointContext;
import sailpoint.object.Application;
import sailpoint.object.Filter;
import sailpoint.object.ManagedAttribute;
import sailpoint.object.ResourceObject;
import sailpoint.services.standard.connector.LogiPlexConnector.LogiPlexUtil;
import sailpoint.tools.GeneralException;
import sailpoint.tools.Util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Log logger = LogFactory.getLog("xxx.xx.xxx.xx.xx");
logger.info("Starting SPLIT Rule");
Custom custom = context.getObjectByName(Custom.class, "MyCustomObj");
Map customMap = custom.get("Active Directory").get("LogiplexingList");
public String resolveApplication(String name) {
logger.info("Entering resolveApplication");
if (Util.isNotNullOrEmpty(name)) {
logger.info("name: " + name);
String lname = name.toLowerCase();
logger.info("lname: " + lname);
if(customMap != null){
System.out.println("2");
for (String key : customMap.keySet()) {
String appNameCustom = key;
Map entryMap = customMap.get(appNameCustom);
String searchValue = entryMap.get("searchValue");
String searchFilter = entryMap.get("searchFilter");
logger.info("searchValue -- "+searchValue);
logger.info("searchFilter -- "+searchFilter);
if ("startswith".equalsIgnoreCase(searchFilter) && lname.startsWith(searchValue)) {
return " " + appNameCustom;
} else if ("contains".equalsIgnoreCase(searchFilter) && lname.contains(searchValue)) {
return " " + appNameCustom;
} else if ("equals".equalsIgnoreCase(searchFilter) && lname.equals(searchValue)) {
return " " + appNameCustom;
}
}
}
}
logger.info("Exiting resolveApplication method");
return application.getName();
}
String applicationName = application.getName();
logger.info("applicationName: " + applicationName);
Map map = new HashMap();
if ("account".equals(object.getObjectType())) {
logger.info("Processing account object type");
List groups = object.getStringList("memberOf");
logger.info("groups: " + groups);
if (groups != null && !groups.isEmpty()) {
Map groupMap = new HashMap();
groupMap = util.updateListMap(groupMap, applicationName, null);
logger.info("groupMap: " + groupMap);
for (String group: groups) {
String appName = resolveApplication(group);
logger.info("appName: " + appName);
if (Util.isNotNullOrEmpty(appName)) {
groupMap = util.updateListMap(groupMap, appName, group);
}
}
Set keys = groupMap.keySet();
logger.info("keys: " + keys.toString());
if (!keys.isEmpty()) {
for (String key: keys) {
logger.info("key: " + key);
List appGroups = groupMap.get(key);
logger.info("appGroups: " + appGroups);
ResourceObject cloneObject = object.deepCopy(context);
if (!Util.isEmpty(appGroups)) {
cloneObject.put("memberOf", appGroups);
} else {
cloneObject.remove("memberOf");
}
map.put(key, cloneObject);
}
} else {
map.put(applicationName, object);
}
} else {
map.put(applicationName, object);
}
} else if ("group".equals(object.getObjectType())) {
logger.info("Processing group object type");
String nativeIdentity = object.getIdentity();
logger.info("nativeIdentity: " + nativeIdentity);
String appName = resolveApplication(nativeIdentity);
logger.info("appName: " + appName);
map.put(appName, object);
logger.info("map: " + map);
} else {
logger.info("Processing other object type");
map.put(applicationName, object);
logger.info("map: " + map);
}
logger.info("Ending SPLIT Rule");
return map;
]]></Source>
</Rule>