Friday, August 26, 2016

Pulling users and groups from LDAP into Apache Syncope 2.0.0

A previous tutorial showed how to synchronize (pull) users and roles into Apache Syncope 1.2.x from an LDAP backend (Apache Directory). Interacting with an LDAP backend appears to be a common use-case for Apache Syncope users. For this reason, in this tutorial we will cover how to pull users and groups (previously roles) into Apache Syncope 2.0.0 from an LDAP backend via the Admin Console, as it is a little different from the previous 1.2.x releases.

1) Apache DS

The basic scenario is that we have a directory that stores user and group information that we would like to import into Apache Syncope 2.0.0. For the purposes of this tutorial, we will work with Apache DS. The first step is to download and launch Apache DS. I recommend installing Apache Directory Studio for an easy way to create and view the data stored in your directory.

Create two new groups (groupOfNames) in the default domain ("dc=example,dc=com") called "cn=employee,ou=groups,ou=system" and "cn=boss,ou=groups,ou=system". Create two new users (inetOrgPerson) "cn=alice,ou=users,ou=system" and "cn=bob,ou=users,ou=system". Now edit the groups you created such that both alice and bob are employees, but only alice is a boss. Specify "sn" (surname) and "userPassword" attributes for both users.

2) Pull data into Apache Syncope

The next task is to import (pull) the user data from Apache DS into Apache Syncope. Download and launch an Apache Syncope 2.0.x instance. Make sure that an LDAP Connector bundle is available (see here).

a) Define a 'surname' User attribute

The inetOrgPerson instances we created in Apache DS have a "sn" (surname) attribute. We will map this into an internal User attribute in Apache Syncope. The Schema configuration is quite different in the Admin Console compared to Syncope 1.2.x. Select "Configuration" and then "Types" in the left hand menu. Click on the "Schemas" tab and then the "+" button associated with "PLAIN". Add "surname" for the Key and click "save". Now go into the "AnyTypeClasses" tab and edit the "BaseUser" item. Select "surname" from the list of available plain Schema attributes. Now the users we create in Syncope can have a "surname" attribute.

b) Define a Connector

The next thing to do is to define a Connector to enable Syncope to talk to the Apache DS backend. Click on "Topology" in the left-hand menu, and on the ConnId instance on the map. Click "Add new connector" and create a new Connector of type "net.tirasa.connid.bundles.ldap". On the next tab select:
  • Host: localhost
  • TCP Port: 10389
  • Principal: uid=admin,ou=system
  • Password: <password>
  • Base Contexts: ou=users,ou=system and ou=groups,ou=system
  • LDAP Filter for retrieving accounts: cn=*
  • Group Object Classes: groupOfNames
  • Group member attribute: member
  • Click on "Maintain LDAP Group Membership".
  • Uid attribute: cn
  • Base Context to Synchronize: ou=users,ou=system and ou=groups,ou=system
  • Object Classes to Synchronize: inetOrgPerson and groupOfNames
  • Status Management Class: net.tirasa.connid.bundles.ldap.commons.AttributeStatusManagement
  • Tick "Retrieve passwords with search".
Click on the "heart" icon at the top of tab to check to see whether Syncope is able to connect to the backend resource. If you don't see a green "Successful Connection" message, then consult the logs. On the next tab select all of the available capabilities and click on "Finish".

c) Define a Resource

Next we need to define a Resource that uses the LDAP Connector.  The Resource essentially defines how we use the Connector to map information from the backend into Syncope Users and Groups. Click on the Connector that was created in the Topology map and select "Add new resource". Just select the defaults and finish creating the new resource. When the new resource is created, click on it and add some provisioning rules via "Edit provision rules".

Click the "+" button and select the "USER" type to create the mapping rules for users. Click "next" until you come to the mapping tab and create the following mappings:

Click "next" and enable "Use Object Link" and enter "'cn=' + username + ',ou=users,ou=system'". Click "Finish" and "save". Repeat the process above for the "GROUP" type to create a mapping rule for groups as follows:
Similar to creating the user mappings, we also need to enable "Use Object Link" and enter "'cn=' + name + ',ou=groups,ou=system'". Click "Finish" and "save".

d) Create a pull task

Having defined a Connector and a Resource to use that Connector, with mappings to map User/Group information to and from the backend, it's time to import the backend information into Syncope.  Click on the resource and select "Pull Tasks". Create a new Pull Task via the "+" button. Select "/" as the destination realm to create the users and groups in. Choose "FULL_RECONCILIATION" as the pull mode. Select "LDAPMembershipPullActions"  (this will preserve the fact that users are members of a group in Syncope) and "LDAPPasswordPullActions" from the list of available actions. Select "Allow create/update/delete". When the task is created,  click on the "execute" button (it looks like a cogged wheel). Now switch to the "Realms" tab in the left-hand menu and look at the users and groups that have been imported in the "/" realm from Apache DS.


  1. Hello,

    I tried to follow your tutorial, it is pretty much straight forward and easy to use, but somehow I cannot bind syncope to ldap server. I am using ApacheDS 2.0.0-M23 and Apache Syncope 2.0.3 version.
    I receive following error : Connection failure: ConnectorException [OperationNotSupportedException: [LDAP: error code 53 - UNWILLING_TO_PERFORM: Bind failed: Cannot Bind for Dn uid=admin,ou=system]]
    Well, I double checked everything, and all settings looks good. I tried to connect to ldap using JXplorer, using the same settings and it was successful.
    Maybe you could show the right direction how can I resolve it?

  2. Found the answer. The problem is with version 2.0.3. Installed version 2.0.2, and all started to work like a charm.

  3. Could you report the bug to the Syncope mailing list please in case it's a regression?

  4. I did that!

    Concerning your tutorial. I did every single step from it and I'm still unable to pull users from ldap to syncope. After executing pull task I receive FAILURE with following stacktrace :

    15:49:33.239 DEBUG Enter: search(ObjectClass: __ACCOUNT__, null,$2@2ba80eb7, OperationOptions: {ATTRS_TO_GET:[__PASSWORD__,__NAME__,cn,__UID__,__ENABLE__],PAGE_SIZE:100}) Method: search
    15:49:33.244 DEBUG Enter: executeQuery(ObjectClass: __ACCOUNT__, null, org.identityconnectors.framework.impl.api.local.operations.SearchImpl$1@4ebdf2d1, OperationOptions: {ATTRS_TO_GET:[__PASSWORD__,__NAME__,cn,__UID__,__ENABLE__],PAGE_SIZE:100}) Method: executeQuery
    15:49:33.246 WARN Attribute __ENABLE__ of object class __ACCOUNT__ is not mapped to an LDAP attribute Method: getLdapAttribute
    15:49:33.247 DEBUG Searching in [ou=Users,dc=example,dc=org] with filter (&(&(objectClass=top)(objectClass=person)(objectClass=organizationalPerson)(objectClass=inetOrgPerson))(cn=*)) and SearchControls: {returningAttributes=[cn, description, userPassword], scope=SUBTREE} Method: doSearch
    15:49:33.260 WARN Attribute __ENABLE__ of object class __ACCOUNT__ is not mapped to an LDAP attribute Method: getLdapAttribute
    15:49:33.260 DEBUG Exception: Method: executeQuery
    java.lang.IllegalArgumentException: Must be a single value.
    at org.identityconnectors.framework.common.objects.AttributeBuilder.checkSingleValue( ~[connector-framework-]
    at org.identityconnectors.framework.common.objects.AttributeBuilder.getSingleStringValue( ~[connector-framework-]
    at ~[connector-framework-]
    at net.tirasa.connid.bundles.ldap.schema.LdapSchemaMapping.createAttribute( ~[net.tirasa.connid.bundles.ldap-1.5.1.jar:?]

    Any clues?