7

I'm trying to duplicate a LDAP layout/schema from the field my application has to deal with-and I'm trying to recreate + test it via an automated test with the embeddable UnboundID LDAP server.

The situation it has to deal with is the user schema's 'memberOf' property like Active Directory has...but I'm not quite sure how to add a 'user' class to this ldap in memory.

1) Is this possible? 2) Is there a better strategy? 3) And what in particular should I do? I'm a LDAP newbie.

Below is my nonworking code.

Thanks, Mike Kohout

public class TestOpenLdap2
{
    private InMemoryDirectoryServer server;

    @Before
    public void start() throws Exception
    {
        InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig("dc=com");
        config.addAdditionalBindCredentials("cn=admin,ou=People,dc=example,dc=com", "cred");
        InMemoryListenerConfig listenerConfig = new InMemoryListenerConfig("test", null, 33390, null, null, null);
        config.setListenerConfigs(listenerConfig);
        server = new InMemoryDirectoryServer(config);
        server.startListening();
    }

    @Test
    public void testMemberOf() throws Exception
    {

        addEntry("dn: dc=com", "objectClass: top", "objectClass: domain", "dc: com");

        ObjectClassDefinition oc = new ObjectClassDefinition("10.19.19.78", new String[]{"user"}, "", false, new String[]{"TOP"},
                                                                              ObjectClassType.STRUCTURAL, new String[]{"memberOf"},
                                                                              new String[]{}, new HashMap());
        addEntry("dn: cn=schema2,dc=com", "objectClass: top", "objectClass: ldapSubEntry", "objectClass: subschema", "cn: schema2",
                    "objectClasses:  " + oc.toString());

        addEntry("dn: dc=people,dc=com", "objectClass: top", "objectClass: domain", "dc: people");
        addEntry("dn: dc=groups,dc=com", "objectClass: top", "objectClass: domain", "dc: groups");
        addEntry("dn: cn=test-group,dc=groups,dc=com", "objectClass: groupOfUniqueNames", "cn: test group");
        addEntry("dn: cn=Testy Tester,dc=people,dc=com", "objectClass: Person", "objectClass: user", "objectClass: organizationalPerson", "sn: Tester", "cn: Testy Tester", "memberOf: cn=test-group,dc=groups,dc=com");
    }

    public void addEntry(String... args) throws LDIFException, LDAPException
    {
        LDAPResult result = server.add(args);
        assert (result.getResultCode().intValue() == 0);
        System.out.println("added entry:" + Arrays.asList(args));
    }
JPBlanc
  • 70,406
  • 17
  • 130
  • 175
Michael Kohout
  • 1,073
  • 1
  • 14
  • 26

3 Answers3

7

Anyone who comes across this may be interested to know that the functionality referred to be Neil Wilson has been implemented (at least in com.unboundid:unboundid-ldapsdk:2.3.1) :)

Here is how you might replace the person objectClass with one which contains a userPrincipalName attribute:

dn: cn=schema
changetype: modify
add: attributetypes
attributetypes: ( 1.2.3.4.5.6.7 NAME 'userPrincipalName' DESC 'userPrincipalName as per Active Directory' EQUALITY caseIgnoreMatch SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' )

dn: cn=schema
changetype: modify
delete: objectClasses
objectClasses: ( 2.5.6.6
                 NAME 'person'
                 SUP top
                 STRUCTURAL
                 MUST ( sn $
                        cn )
                 MAY ( userPassword $
                       telephoneNumber $
                       seeAlso $
                       description )
                 X-ORIGIN 'RFC 4519' )

dn: cn=schema
changetype: modify
add: objectClasses
objectClasses: ( 2.5.6.6
                 NAME 'person'
                 SUP top
                 STRUCTURAL
                 MUST ( sn $
                        cn $
                        userPrincipalName )
                 MAY ( userPassword $
                       telephoneNumber $
                       seeAlso $
                       description ) )

Note that the person objectClass must be removed. It is defined as an 'objectClasses' attribute and you must specify the entire definition to reference it. The definition is in the default schema as mentioned by Neil: docs/standard-schema.ldif

I copied the userPrincipalName attribute definition from some Oracle docs which describe how to modify schema elements: http://docs.oracle.com/cd/E12839_01/oid.1111/e10035/ldif_appendix.htm#CHDCCJIG

James Baxter
  • 1,237
  • 9
  • 17
  • 6
    I'm getting an `Unable to add an entry with a DN that is the same as or subordinate to the subschema subentry DN 'cn=schema'` error when I try this, sdk v.2.3.4 – SelimOber Jun 24 '13 at 13:36
5

At present, the in-memory directory server doesn't support online schema changes (i.e., updating the cn=schema entry via LDAP modify operations). That's on my to-do list, but it's not yet implemented.

However, if you just want to customize the schema that the server runs with, then you can simply initialize the server with the schema you want to use. You can create a schema from information in multiple files (and the one the in-memory server uses by default is included in the docs/standard-schema.ldif file, so you can just add a second file with the custom schema elements you want to use).

Neil

Neil Wilson
  • 1,706
  • 8
  • 4
  • Thanks for the info, Neil. How high on the to-do list is this bit of functionality, oh benevolent one? Also, do you specifically mean to initialize it via a call to server.initializeFromLDIF(true, "/tmp/test.ldif")? – Michael Kohout Oct 21 '11 at 15:06
  • It's probably not a huge effort to add this support, with a few concessions (e.g., if you change the syntax / matching rules for a defined attribute type, existing entries with that attribute will still use the old behavior, and incompatible changes to object class definitions may result in some entries that no longer comply with schema). – Neil Wilson Oct 21 '11 at 15:56
  • 1
    Also, to configure a custom schema, use the InMemoryDirectoryServerConfig.setSchema method before starting the server. There are a couple of Schema.getSchema methods that take a set of files that will collectively be used to create a schema. – Neil Wilson Oct 21 '11 at 16:00
  • Yep, i just load my schema up before my tests . see https://github.com/trevershick/ldap-test-utils for the annotations i use and example test. – Trever Shick Feb 05 '13 at 22:01
  • Could you please tale a look https://stackoverflow.com/questions/76779172/inmemorydirectoryserver-allows-to-have-to-2-users-with-the-same-username-how-to – gstackoverflow Jul 27 '23 at 12:59
0

On pure LDAP consideration the behaviour you want to use is called Referencial Integrity and as I can read in LDAP SDK for Java

  • It provides an option to maintain referential integrity for a specified set of attributes for delete and modify DN operations...

I can't help you much this way.

As far Active-Directory is a target, one good thing for testing is to install an ADAM (Active Dirctory Application Mode). It's a free Directory from Microsoft that you can use to duplicate in AD schema and objects. ADAM is a redistribuable that you can even install on Windows XP. To install on Windows Seven you better use LDS (Lightweight directory service). Both uses tools to migrate an AD schema and objects from AD.

JPBlanc
  • 70,406
  • 17
  • 130
  • 175
  • Funny you should mention that-ADAM is actually the client's setup. My big hope was that I could use UnboundID inside unit tests, making it look enough like ADAM so it would be useful for the unit/integration test. – Michael Kohout Oct 21 '11 at 14:51