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!

Populating Active Directory from OpenLDAP

Presentation

This article describes the creation of a connector which synchronizes data from OpenLDAP to Active Directory.

It has been done under Linux Ubuntu 8.10, with source code from LSC v1.1. It will not use IDE like Eclipse or Netbeans. Everything will be done through the console, and the graphical components from AntInstaller (graphics can be turned off, text mode is available).

Prepare your environment

Internet connection

Since LSC makes a strong use of Maven, you need a working Internet connection to resolve all dependencies. If you are behind a proxy, please refer to Maven documentation: http://maven.apache.org/guides/mini/guide-proxies.html

Java tools

As described in Requirements, you need Java developers' tools to create a new connector. Here are those used in this tutorial:

  • SUN JDK 1.5.0_16
  • Maven 2.0.9
  • Ant 1.7.1

Connector directory

To start a new connector, you have to download the LSC sample, as a starting point. Get the latest LSC-sample archive from here.

Decompress the archive and rename it for your project:

$ tar xjf lsc-sample-1.1.1.tar.bz2
$ mv lsc-sample-1.1.1 lsc-myName-openldap2ad

Then create a package with maven, at least to check all dependencies are filled:

$ cd lsc-myName-openldap2ad/
$ mvn package

This should have downloaded some files, and created lsc-sample-1.1.1.jar in the target/ directory.

Start LDAP directories

To build the connector, LSC will parse source and destination schemas through LDAP connections, so you have to start OpenLDAP and Active Directory, and be sure to have LDAP access to them.

Connection to Active Directory requires a user account, with read rights on the schema. This user account can be used next for synchronization, with read and write access to data.

Build your connector

Launch the wizard

The LSC generation wizard will guide you through main configuration settings and will parse source and destination schemas to create Java objects corresponding to LDAP objectClasses.

The easiest way to do this is using the graphical wizard.

However, if you don't want to use it, you can use the following command to generate classes, and then edit directory properties in etc/lsc.properties. Only use this command if you don't want to use the graphical wizard! Otherwise, read on.

$ ant lsc::_generator \
-Dgenerator.parameters="-f '$PWD/etc' -dir ../../src/impl/java -doc 'dstObjectClass' \
-name taskName -ldap2ldap -soc 'srcObjectClass'" 

If you're still here, you chose the graphical method. Good. Launch the wizard from your connector directory:

$ ant lsc::generateWizard

Then all the work is done in 10 steps!

Step 1

Welcome screen. Click on Next.

Step 2

LSC presentation. Click on Next.

Step 3

LSC license. Click on Accept.

Step 4

Connector type screen:

  • Task type to generate: here we want an LDAP to LDAP connector, so we choose Directory to directory.
  • Task name: a name that pleases you. It's common to choose the name of the main objectClass of target entries. Here this will be user.
  • Path to generate files: by default in your connector directory. We love the default value, so we keep it.

Step 5

Source directory properties:

  • Source directory authentication mode: we choose Simple bind.
  • LDAP server URL: a standard LDAP URI. Do not forget the trailing slash. We choose ldap://localhost:389/.
  • Naming context root DN: the data suffix. We choose dc=lsc-project,dc=org.
  • ObjectClass of entries from source directory: main source objectClass. Other objectClasses (as values of a search filter) can be added later. We choose inetOrgPerson.

Step 6

If you chose Simple bind in Step 5, provide information on the identity used to bind to the source directory:

  • Principal DN: for example cn=Directory Manager,dc=lsc-project,dc=org.
  • Password: for example secret.

Step 7

Target directory properties:

  • Source directory authentication mode: we choose Simple bind.
  • LDAP server URL: a standard LDAP URI. Do not forget the trailing slash. We choose ldap://lng-pdc.linagora.lan:389/.
  • Naming context root DN: the data suffix. We choose dc=linagora,dc=lan.
  • ObjectClass of entries from target directory: main target objectClass. Other objectClasses (as values of a search filter) can be added later. We choose user.

Step 8

If you chose Simple bind in Step 7, provide information on the identity used to bind to the target directory:

  • Principal DN: for example cn=LSC,dc=linagora,dc=lan.
  • Password: for example linagora.

Step 9

Installation progress screen. Click on Generate. Your LDAP connections should be available now (the wizard will read the schemas).

Step 10

Installation complete. Click on Exit.

If not successful, check the Requirements, or ask for help on the mailing lists.

Compile generated code

The wizard has generated your connector source code. You can check its compilation:

$ ant lsc::compile-app

This should succeed:

BUILD SUCCESSFUL

Warning: Attributes with - in their name are currently ignored (cf. http://tools.lsc-project.org/issues/show/31). Support will be added in version 1.2.

Check your source and destination attributes

The wizard has generated all code to manipulate source attributes from the provided source objectClass (inetOrgPerson), and destination attributes from the provided destination objectClass (user).

The wizard does not manage objectClasses that inherit from the source objectClasses, or other auxiliary objectClasses, but of course your source entry can contain other attributes than those provided with the source objectClass.

So you could add these attributes by editing the source object:

$ vi src/impl/java/org/lsc/objects/inetOrgPerson.java

Just copy/paste one existing attribute source code to create your own:

  • Declare a private variable:
    • List for a multivalued attribute
    • String for a monovalued attribute
  • Create a getter
  • Create a setter

Save and check your code by running:

$ ant lsc::compile-app

Remark: Flat files (in src/impl/java/org/lsc/objects/flat/) are used only for db2ldap connector, so you can remove them.

Warning: you may encounter a bug if source and destination objectClasses are different (see http://tools.lsc-project.org/issues/show/32). In that case, comment the objectClass.add() function from the source object code (e.g. src/impl/java/org/lsc/objects/inetOrgPerson.java) and use syncoptions to force objectClass values (see below).

Set up configuration

Some connector configuration was already done by the wizard, you can see it here:

$ vi etc/lsc.properties

All configuration parameters are described in LSC Configuration.

Connection

These parameters should be the ones used in the wizard. When deploying your connector you will certainly change them to production values.

To manage Active Directory Paged Results Control (which enables to return more than 1000 entries), add:

dst.java.naming.ldap.pageSize = 1000

As we want to act on the password (the attribute unicodePwd), we must use an SSL connection to Active Directory (password modification is not allowed on a clear connection).

The steps are:

Task

You can have multiple tasks in your connector (identified by the lsc.taskname value). In this tutorial, we have only one task, named user.

You have to update the configuration written by the wizard to list all source and destination attributes you want to synchronize, set the destination DN creation rule and select the pivot attributes, that will link a source entry to a destination entry.

For example, we want to link the source entry to the destination entry saying that source uid value is equal to destination uid value:

lsc.tasks.user.srcService.filterId = (&(objectClass=inetOrgPerson)(uid={uid}))
lsc.tasks.user.srcService.pivotAttrs = uid

lsc.tasks.user.dstService.filterId = (&(objectClass=user)(sAMAccountName={uid}))
lsc.tasks.user.dstService.pivotAttrs = uid

Warning: you have to put objectClass in lsc.tasks.user.dstService.attrs but be sure to remove it from lsc.tasks.user.srcService.attrs.

We will also define how the target DN is built. Let's choose that the target DN is composed from the source's attribute cn and the destination branch ou=users,dc=linagora,dc=lan.

The suffix dc=linagora,dc=lan is already configured in dn.real_root, so we only have to set up this configuration to build the DN:

lsc.tasks.user.dn = "cn=" + srcBean.getAttributeValueById("cn") + ",ou=users"

Synchronization options

This is the last configuration part, but not the least, because we will now describe all our synchronization rules.

In this tutorial, we plan to use these rules:

Source attribute Destination attribute Rule
cn cn =
sn sn =
uid uid =
- objectClass user/person/organizationalPerson/top
uid sAMAccountName =
uid userPrincipalName uid + ”@linagora.lan”
- userAccountControl Set as “Normal account”
- pwdLastSet Force password change on creation
- unicodePwd “changeit”

These rules are applied through syncoptions:

# Synchronization options
lsc.syncoptions.user = org.lsc.beans.syncoptions.PropertiesBasedSyncOptions
lsc.syncoptions.user.default.action = F

# Direct link - no need to specify syncoptions
# uid <- uid
# cn <- cn (done with DN generation)
# sn <- sn

# objectClass <- top/user/person/organizationalperson
lsc.syncoptions.user.objectClass.action = F
lsc.syncoptions.user.objectClass.force_value = \
"top";"user";"person";"organizationalPerson"

# sAMAccountName <- uid
lsc.syncoptions.user.sAMAccountName.create_value = \
srcBean.getAttributeValueById("uid")

# userPrincipalName <- uid + "@linagora.lan"
lsc.syncoptions.user.userPrincipalName.force_value = \
srcBean.getAttributeValueById("uid") + "@linagora.lan"

# userAccountControl
lsc.syncoptions.user.userAccountControl.create_value = \
AD.userAccountControlSet( "0", [AD.UAC_SET_NORMAL_ACCOUNT])

# pwdLastSet <- 0 to force user to change password on next connection
lsc.syncoptions.user.pwdLastset.create_value = "0"

# unicodePwd <- "changeit" at creation (requires SSL connection to AD)
lsc.syncoptions.user.unicodePwd.create_value = AD.getUnicodePwd("changeit")

Note: There should be no line breaks after ”=” signs. Any you see here are due to the formatting of this web page, and are marked with a “\” character you should remove.

You can test your synchronization in “dry-run” mode (-n), which means no modification is done on the target directory:

$ ant lsc::synchronize -Dsynchronize.parameters="-f $PWD/etc -c all -s all -n"

Package your application

When your connector is ready, you have to prepare it's deployment. A shell script is available to make a complete archive, including java dependencies, that avoid installing Maven and Ant on the target server.

This script is named make-lsc-archive.sh and is in the src/install directory. You have to edit it to configure the deployment for your needs:

$ vi src/install/make-lsc-archive.sh
#====================================================================
# Configuration
#====================================================================
# Connector name (please provide different names for each connector
# installed on the same machine)
LSCNAME="lsc-my-connector"
# Connector version
LSCVERSION="1.0"
# Target directory to create archive (relative to lsc-sample root)
TGTDIR="target"
# Distribution dir (LSC container in target directory)
LSCDIR=$LSCNAME
DSTDIR=$TGTDIR/$LSCDIR
# Target installation dir (where will be LSC deployed)
INSTDIR="/usr/local/$LSCNAME"
# Target JAVA_HOME dir
INSTJAVAHOME="/usr/java/jdk1.5.0_16"
# Archive name
ARCNAME="$LSCNAME-$LSCVERSION"
# Script name
SCRIPTFILENAME=$LSCNAME
# Other
CFGPATH="etc"
CFGDIR=$DSTDIR/$CFGPATH
BINPATH="bin"
BINDIR=$DSTDIR/$BINPATH
LIBPATH="lib"
LIBDIR=$DSTDIR/$LIBPATH
RSCPATH="$CFGPATH/resources"
RSCDIR=$DSTDIR/$RSCPATH
# Log and cron
LOGDIR="/var/log"
#LOGDIR=$DSTDIR/log
LOGFILE=$LOGDIR/$LSCNAME.log
LOGROTATEFILENAME=$LSCNAME
CRONFILENAME=$LSCNAME

For default installation, just replace LSC_NAME with “lsc-openldap2ad” for example. This will install the connector in /usr/local/lsc-openldap2ad.

Make the archive:

src/install/make-lsc-archive.sh

The connector archive is now in target/ directory, under the name lsc-openldap2ad-1.0.tar.gz.

Install and run

On the target server, just unpack the connector:

$ sudo tar -zxf lsc-openldap2ad-1.0.tar.gz -C /usr/local

Install cronjob and logrotate scripts:

$ sudo cp /usr/local/lsc-openldap2ad/etc/cron.d/lsc-openldap2ad /etc/cron.d
$ sudo cp /usr/local/lsc-openldap2ad/etc/logrotate.d/lsc-openldap2ad /etc/logrotate.d

Now your connector will run every hour, but you can also launch it manually:

$ sudo /usr/local/lsc-openldap2ad/bin/lsc-openldap2ad -s all -c all

A Nagios script is also installed in /usr/local/lsc-openldap2ad/bin/check-lsc.sh, that you can call with a check_ssh service.