Home Contact Download
LSC logo
Open source connector to synchronize identities to a LDAP directory from any data source including any database with a JDBC connector, another LDAP server or flat files ...
Download  |  Read more...  |  Get started!

Group membership synchronization

Presentation

LSC can help you to synchronize groups from one directory to another. The problem is that most of the time, group membership is managed by DN (that means the DN of the users are the values of the member attribute of the group entry). Of course each user DN is not the same in the source directory and in the destination directory: so we have to map each user DN for each membership value.

The major real use-case is to synchronize groups from OpenLDAP to Active Directory. This tutorial describes it.

LSC requirement

We will use groupOfUniqueNames as source object and group as destination object, so you have to run LSC wizard to get:

  • org.lsc.objects.groupOfUniqueNames
  • org.lsc.beans.groupBean

The connector will be ldap2ldap.

You should have a first task that synchronizes users from OpenLDAP to AD, in order to make the DN mapping work. See this tutorial to achieve this.

So we will create a second task in the connector to manage groups.

LSC configuration

We suppose that groups are in the “ou=groups” branch in both directories, with the following template for a source group:

dn: cn=group1,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
objectClass: top
cn: group1
description: Service 1
uniqueMember: uid=coudot,ou=users,dc=example,dc=com

So the LSC task definition will be:

#==============================================================================
# Task "group"
#==============================================================================
lsc.tasks = group
lsc.tasks.group.type = ldap2ldap
lsc.tasks.group.bean = org.lsc.beans.groupBean
lsc.tasks.group.object = org.lsc.objects.groupOfUniqueNames

lsc.tasks.group.dn = "cn=" + srcBean.getAttributeValueById("cn") + ",ou=groups"

lsc.tasks.group.srcService = org.lsc.jndi.SimpleJndiSrcService
lsc.tasks.group.srcService.attrs = cn description uniqueMember
lsc.tasks.group.srcService.baseDn = ou=groups
lsc.tasks.group.srcService.filterAll = (objectClass=groupOfUniqueNames)
lsc.tasks.group.srcService.filterId = (&(objectClass=groupOfUniqueNames)(cn={cn}))
lsc.tasks.group.srcService.pivotAttrs = cn

lsc.tasks.group.dstService = org.lsc.jndi.SimpleJndiDstService
lsc.tasks.group.dstService.attrs = cn description member objectClass
lsc.tasks.group.dstService.baseDn = ou=groups
lsc.tasks.group.dstService.filterAll = (objectClass=group)
lsc.tasks.group.dstService.filterId = (&(objectClass=group)(cn={cn}))
lsc.tasks.group.dstService.pivotAttrs = cn

Now we add syncoptions to manage the member attribute. What we want is:

  • For each uniqueMember value (which is a user DN) of the srcBean entry:
    • Find uid value of the user entry on source directory
    • Search corresponding entry in destination directory with the filter (sAMAccountName=$uid)
    • Find DN of the found entry in destination directory
    • Check if this value is not null and push it in member values

We must use LQL to do that (see ScriptableJndiServices javadoc). And as we will use some javascript code, we must change the default delimiter in the configuration file (which is ';').

Here is the correct syntax:

# Synchronization options
lsc.syncoptions.group = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.group.default.action = F
 
# Direct link - no need to specify syncoptions
# cn <- cn
# description <- description
 
# objectClass <- top/group
lsc.syncoptions.group.objectClass.force_value = "top";"group"
 
# member <- uniqueMember
lsc.syncoptions.group.member.delimiter = $
lsc.syncoptions.group.member.force_value = \
    var umembers = \
        srcBean.getAttributeValuesById("uniqueMember").toArray() ; \
    for (var i=0; i<umembers.length; i++ ) { \
        try { \
            umembers[i] = ldap.attribute(ldap.list( "ou=users", \
                "(sAMAccountName=" \
                    + (srcLdap.attribute(umembers[i], 'uid').get(0) \
                    + ")"
                )).get(0), 'distinguishedname').get(0) \
        } catch (e) { \
            umembers[i]=null \
        } \
    } \
    var members = new Array(); \
    var j=0; \
    for (var i=0; i<umembers.length; i++) { \
        if (umembers[i]!=null) members[j++]=umembers[i] \
    } \
    members