Friday, August 9, 2013

Apache Syncope tutorial - part III

In the first tutorial on Apache Syncope, we showed how to deploy Syncope to Apache Tomcat, and how to set up MySQL as the internal storage mechanism. In the second tutorial, we showed how to import some users into Syncope from a backend (Apache Derby) database resource. In this tutorial, we will look at synchronizing user and role data from an LDAP backend into Syncope, in this case Apache DS. This tutorial assumes that Syncope is set up as described in tutorial I, and that a Surname attribute has been added to the User attributes in Syncope, as described in tutorial II.

1) Apache DS

The basic scenario is that we have a directory that stores user and role information that we would like to import into Apache Syncope. In the previous tutorial, we only imported User data into Syncope. 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 view the data stored in your directory.

Import the following ldif file into your Apache DS instance. Essentially this describes two users, "cn=alice,ou=users,ou=system" and "cn=bob,ou=users,ou=system", as well as two groups, "cn=employee,ou=groups,ou=system" and "cn=boss,ou=groups,ou=system". Both Alice and Bob are employees, but only Alice is the boss. We will import this user information into Syncope as per tutorial II. However, this time we will go further and import the group information as roles into Syncope. This will enable us to perform authorization checks against Syncope, as will be described in the next tutorial.

2) Synchronize user data into Apache Syncope

The next task is to import (synchronize) the user data from Apache DS into Apache Syncope. See the Syncope wiki for more information on this topic, as well as the following blog post. Launch Apache Syncope as per tutorial I/II.

a) Define a Connector

The first thing to do is to define a Connector. In tutorial I we configured two Connector bundles to use for Syncope, one for a DB backend, and one for an LDAP backend. In this section we select the LDAP Connector, and configure it to connect to the DS instance we have set up above. Go to "Resources/Connectors", and create a new Connector of name "org.connid.bundles.db.ldap". In the "Configuration" 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=*
  • groupObjectClasses: groupOfNames
  • Group member attribute: member
  • 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: org.connid.bundles.ldap.commons.AttributeStatusManagement
  • Tick "Retrieve passwords with search".
In the "Capabilities" tab select the following properties:
  • ONE_PHASE_CREATE
  • ONE_PHASE_UPDATE
  • ONE_PHASE_DELETE
  • SEARCH
  • SYNC
Click on the "helmet" icon in the "Configuration" 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.

b) 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 Roles. Go into the "Resources" tab and select "Create New Resource". In the "Resource Details" tab select:
  • Name: (Select a name)
  • Connector: (Connector display name you have configured previously)
  • Enforce mandatory condition
  • Propagation Primary
  • Propagation Mode (see here): ONE_PHASE
  • Select "LDAPMembershipPropagationActions" for the "Actions class"
The next step is to create User mappings. Click on the "User mapping" tab, and create the following mappings:

Enable "Account Link" and enter "'cn=' + username + ',ou=users,ou=system'", as shown in the screenshot. The next step is to create Role mappings. Click on the "Role mapping" tab, and create the following mapping:

Enable "Account Link" and enter "'cn=' + name + ',ou=groups,ou=system'" as shown in the screenshot.

c) Create a synchronization task

Having defined a Connector and a Resource to use that Connector, with mappings to map User/Role information to and from the backend, it's time to import the backend information into Syncope.  Go to "Tasks" and select the "Synchronization Tasks" tab. Click on "Create New Task". On the "Profile" tab enter:
  • Name: (Select a name)
  • Resource Name: (The Resource name you have created above)
  • Actions Class: LDAPMembershipSyncActions
  • Create new identities
  • Updated matched identities
  • Delete matching identities
  • Status
  • Full reconciliation
Save the task and then click on the "Execute" button. Now switch to the Users tab. You should see the users stored in the backend, and if you edit a user, you should be able to see what roles are associated with the user. In the "Roles" tab, you should see the imported Roles. For example, here are the roles that are associated with the user "Alice":



2 comments:

  1. While Importing the above given LDIF file getting the following error :-

    Error while importing LDIF
    - ENTRY_ALREADY_EXISTS: failed for MessageType : ADD_REQUES
    javax.naming.NameAlreadyBoundException: ENTRY_ALREADY_EXISTS: failed for MessageType : ADD_REQUEST
    Message ID : 11
    Add Request :
    Entry
    dn[n]: ou=interceptors,ou=configuration,ou=system
    objectClass: top
    objectClass: organizationalUnit
    ou: interceptors
    : ERR_250_ENTRY_ALREADY_EXISTS ou=interceptors,ou=configuration,ou=system already exists!
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper.checkResponse(DirectoryApiConnectionWrapper.java:1265)
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper.access$600(DirectoryApiConnectionWrapper.java:109)
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper$6.run(DirectoryApiConnectionWrapper.java:928)
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper.runAndMonitor(DirectoryApiConnectionWrapper.java:1175)
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper.checkConnectionAndRunAndMonitor(DirectoryApiConnectionWrapper.java:1109)
    at org.apache.directory.studio.connection.core.io.api.DirectoryApiConnectionWrapper.createEntry(DirectoryApiConnectionWrapper.java:950)
    at org.apache.directory.studio.ldapbrowser.core.jobs.ImportLdifRunnable.importLdifRecord(ImportLdifRunnable.java:464)
    at org.apache.directory.studio.ldapbrowser.core.jobs.ImportLdifRunnable.importLdif(ImportLdifRunnable.java:272)
    at org.apache.directory.studio.ldapbrowser.core.jobs.ImportLdifRunnable.run(ImportLdifRunnable.java:218)
    at org.apache.directory.studio.connection.core.jobs.StudioConnectionJob.run(StudioConnectionJob.java:109)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

    ENTRY_ALREADY_EXISTS: failed for MessageType : ADD_REQUEST
    Message ID : 11
    Add Request :
    Entry
    dn[n]: ou=interceptors,ou=configuration,ou=system
    objectClass: top
    objectClass: organizationalUnit
    ou: interceptors
    : ERR_250_ENTRY_ALREADY_EXISTS ou=interceptors,ou=configuration,ou=system already exists!

    ReplyDelete
  2. I guess the ldif import doesn't work directly. You can recreate the users and roles pretty easily in Apache DS using the Studio plugin for eclipse.

    ReplyDelete