четверг, 18 декабря 2008 г.

 

Embedded LDAP

Today, I've tried to setup some embedded LDAP server for my automated integration testing. First of all, since my language is java, I need pure Java Ldap Server implementation. There are two main alternatives: Apache DS and OpenDS.
Some guys from Inter LDAP declared that Apache DS is better, but they've choosen Open LDAP because it support some not-frequently-used-feature like extended control. I had no intention to use advanced feaures, so I've choosen Apache DS because it had better documentation, set of plugins for eclipse and (the main reason) I've used it before as standalone server.

First of all, I've read some blogs from Apache DS team:

  1. http://cwiki.apache.org/DIRxSRVx11/42-using-apacheds-for-unit-tests.html

  2. http://directory.apache.org/apacheds/1.0/embedding-apacheds-as-a-web-application.html

  3. http://cwiki.apache.org/DIRxSRVx11/41-embedding-apacheds-into-an-application.html



The compilation of blogs above released into folowing embeddable server code:


import java.io.File;
import java.util.HashSet;

import org.apache.directory.server.core.*;
import org.apache.directory.server.core.entry.ServerEntry;
import org.apache.directory.server.core.partition.Partition;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmIndex;
import org.apache.directory.server.core.partition.impl.btree.jdbm.JdbmPartition;
import org.apache.directory.server.ldap.LdapService;
import org.apache.directory.server.protocol.shared.SocketAcceptor;
import org.apache.directory.server.protocol.shared.store.LdifFileLoader;
import org.apache.directory.server.xdbm.Index;

public class ApacheLDAPServer {

private LdapService ldapService;
private DirectoryService directoryService;
private Partition partition;
int port = 9389;

private static ApacheLDAPServer instance;

public static ApacheLDAPServer getInstance() {
if (instance == null) {
instance = new ApacheLDAPServer();
}
return instance;
}

private ApacheLDAPServer() {
}


public void start() throws Exception {
directoryService = new DefaultDirectoryService();
directoryService.setAllowAnonymousAccess(true);
directoryService.setAccessControlEnabled(false);
//directoryService.setExitVmOnShutdown(false);
directoryService.setShutdownHookEnabled( false );
directoryService.getChangeLog().setEnabled(false);

File workdir = new File(System.getProperty("java.io.tmpdir"), "apache-ds");
workdir.delete();
workdir.mkdirs();
directoryService.setWorkingDirectory(workdir);

partition = addPartition("testPartition", "c=RU");
addIndex("objectClass", "ou", "uid");

SocketAcceptor socketAcceptor = new SocketAcceptor(null);

ldapService = new LdapService();
ldapService.setIpPort(port);
ldapService.setSocketAcceptor(socketAcceptor);
ldapService.setDirectoryService(directoryService);

directoryService.startup();
ldapService.start();
}


public void applyLdif(File ldifFile) throws Exception {
new LdifFileLoader(directoryService.getAdminSession(), ldifFile, null).execute();
}



public void stop() throws Exception {
ldapService.stop();
directoryService.shutdown();
}


/**
* Add a new partition to the server
*
* @param partitionId The partition Id
* @param partitionDn The partition DN
* @return The newly added partition
* @throws Exception If the partition can't be added
*/
private Partition addPartition( String partitionId, String partitionDn ) throws Exception
{
Partition partition = new JdbmPartition();
partition.setId( partitionId );
partition.setSuffix( partitionDn );
directoryService.addPartition( partition );

return partition;
}


/**
* Add a new set of index on the given attributes
*
* @param partition The partition on which we want to add index
* @param attrs The list of attributes to index
*/
public void addIndex(String... attrs )
{
HashSet<Index<?, ServerEntry>> indexedAttributes = new HashSet<Index<?, ServerEntry>>();

for ( String attribute:attrs )
{
indexedAttributes.add( new JdbmIndex<String,ServerEntry>( attribute ) );
}

((JdbmPartition)partition).setIndexedAttributes( indexedAttributes );
}

public int getPort() {
return port;
}

}



Now we can use it in integration unit tests:


@BeforeClass
public static void oneTimeSetUp() throws Exception {

ApacheLDAPServer.getInstance().start();
ApacheLDAPServer.getInstance().applyLdif(
new File("target/test-classes/ldap/ldap-init.ldif"));
ApacheLDAPServer.getInstance().applyLdif(
new File("target/test-classes/ldap/ldap-fill-local.ldif"));
}

@AfterClass
public static void oneTimeTearDown() throws Exception {

ApacheLDAPServer.getInstance().stop();
}



Here is sample LDIF file that is needed for initialization:


dn: m-oid=1.2.3.4.5.6.1, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwIPAddress
m-oid: 1.2.3.4.5.6.1
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6.2, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwNAI
m-oid: 1.2.3.4.5.6.2
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6.3, ou=attributeTypes, cn=core, ou=schema
objectClass: metaAttributeType
objectClass: metaTop
objectClass: top
m-description: Sample attribute
m-equality: caseIgnoreMatch
m-name: bwMIN
m-oid: 1.2.3.4.5.6.3
m-ordering: caseIgnoreOrderingMatch
m-substr: caseIgnoreSubstringsMatch
m-syntax: 1.3.6.1.4.1.1466.115.121.1.44

dn: m-oid=1.2.3.4.5.6, ou=objectClasses, cn=core, ou=schema
objectClass: metaObjectClass
objectClass: metaTop
objectClass: top
m-description: Template scartel entry
m-must: bwIPAddress
m-must: bwMIN
m-must: bwNAI
m-name: bwMobileNodeSession
m-oid: 1.2.3.4.5.6
m-supobjectclass: top

dn: c=RU
objectClass: country
objectClass: top
c: RU

dn: bwIpAddress=0.0.0.150 , c=RU
objectClass: bwMobileNodeSession
objectClass: top
bwipaddress: 0.0.0.150
bwmin: 00-02-9A-00-00-10
bwnai: 00-02-9A-00-00-10


I use Maven for project management so it's pretty easy to add all needed libraries. However, blogs above maven configs are suitable only for Apache DS 1.5.5 which is not yet released (on this moment). I made my own dependency list for 1.5.4 and here it is:


<!-- Apache DS dependencies -->
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-all</artifactId>
<version>1.5.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.mina</groupId>
<artifactId>mina-core</artifactId>
<version>0.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.mina</groupId>
<artifactId>mina-filter-ssl</artifactId>
<version>0.9.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-core</artifactId>
<version>1.5.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>


So, this is a simpliest configuration for embedded java ldap server. You can add additional dependencies to support Kerberos authentication, other network protocols and so on. In 1.5.5 you only need to add apacheds-all module and maven will download all other stuff through transitive dependencies.

Ярлыки:


Комментарии:
Thank you, It was very helpful for me.

When I implement the LDAP integration tests I have used your tutorial. In this configuration everything works fine except change listeners.
When I tried to set change listener on some LDAP object from client side I got exception on server side and lost connection. For this purpose I had to use EventService on the server side.

Best regards to you.
 
Thanks you, Ridus. I'm glad this post was helpful.
 
It is very useful information. Thanks for sharing with us.

OrangeHRM LDAP Integeration Module

 

Отправить комментарий

Подпишитесь на каналы Комментарии к сообщению [Atom]





<< Главная страница

This page is powered by Blogger. Isn't yours?

Подпишитесь на каналы Сообщения [Atom]