The CreatorCon Call for Content is officially open! Get started here.

LDAP Nested Groups

mflora
Kilo Contributor

I am currently working on an integration with Active Directory. Within AD, we are using groups to designate the Assignment Groups within Service-now. This is working just fine as long as, in AD, the members of the groups are individual users. If another AD group is added as a member of this group, we are not able to see the individual user accounts within the nested group.

Does anyone know of a way to have Service-now traverse the nested group members?

Also, there are multiple levels within the nested groups (e.g. groups within groups within groups, etc.).

Any help or suggestions would be greatly appreciated.

Thanks

27 REPLIES 27

Ryan Schmeckpe1
Kilo Contributor

Thanks to everyone who kept adding to this post, DavinBiggs especially.  DavinBiggs's solution did not work at first for our LDAP instance but I was able to modify it to accomplish the same idea without using the filter.  This probably occurred as we are using ED and not AD.

As the filter did not work us, I used a recursive function call to achieve the same effect. 

(function runTransformScript(source, map, log, target /*undefined onStart*/ ) {
        // Base code for this onAfter was found here:
        // https://community.servicenow.com/community?id=community_question&sys_id=b2def2e5db58dbc01dcaf3231f961904
	
	var memberString = '';

	try {
		var groupMembers = [];

		// Get LDAP Server from 'source'
		var ldapServerID = source.sys_import_set.data_source.ldap_target.server.sys_id.toString();

		//Initialise ldapConfig Object with the LDAP Server to be used to retrieve the Group Membership
		var ldapConfig = new GlideLDAPConfig.get(ldapServerID);
		var ldap = ldapConfig.getLDAP();

		var query = '';

		// Ensure this record has a dn to retrieve data against
		if (!JSUtil.nil(source.u_dn)) {
			// Get members against the dn of the Group
			query = 'memberOf=' + source.u_dn;
		}
                var all_users = [];
		var parent_groups = [];
		all_users = build_list(query, ldap, all_users, parent_groups);
		
		// Create caret delimited string of dn's
		memberString = all_users.join('^');
        
		// Use same methodology of adding users to groups as OOB Script
		var group = new GlideLDAPGroups(target, memberString);
		group.setMembers();

	} catch (e) {
		gs.log("LDAPUtilCC: " + e);
	}
})(source, map, log, target);

function build_list(query_string, ldap, parent_groups, uniq_users) {
    var result = ldap.getMatching('', query_string, true, 1000); 
    parent_groups.push(query_string.split("=")[1]); 
    while (record = result.next()) { 
        var dn = JSON.stringify(record.get('dn')).replace(/"/g, '');
        if (dn.search(/^cn=/) > -1) {
            if (parent_groups.indexOf(dn) == -1) { 
                uniq_users = build_list("memberof=" + dn, ldap, parent_groups, uniq_users); 
            } 
        } else { 
            if (uniq_users.indexOf(dn) == -1) {
                uniq_users.push(dn);
            } 
        } 
    }
    return uniq_users;
}

Vishnu V Reddy
Tera Contributor

@Davin Biggs @Ryan Schmeckpeper  I am trying to follow your approach in onAfter script as above. But it seems like my request is timed out at 100 seconds. I am able to import groups and users from AD in other standard ways like data sources and such, but using this script is causing the timeout and hence no response. What do you think is causing the issue?

Any insight will be really helpful.

Thanks!

Davin Biggs
Tera Contributor

@JFox we have an AD of around 3500 user objects, and somewhat fewer Group objects, and it runs fine on that.

How large is your AD?  Do you have lots of nested groups?

In your script, can you identify where the bottleneck is?

Good luck