OpenDJ: LDAP Controls

OpenDJ LogoLDAP controls are a standard mechanism for extending basic LDAP operations. For example, you can use a control to ask the LDAP server to sort search results before returning them, or to return search results a few at a time.

OpenDJ directory server supports a fairly long list of controls. Let’s take a look at three of them.

“Only do this if…”

The Assertion Control tells the directory server only to process the operation if a specified assertion is true for the target entry. You can specify the assertion as a filter to match.

As an example, let’s replace Babs Jensen’s street address, but only if it is the one we are expecting. Notice the assertion filter passed to the ldapmodify request. If Babs’s street address is not “500 3rd Street”, the request does not have an effect:

$ ldapmodify 
> --port 1389 
> --bindDN uid=kvaughan,ou=people,dc=example,dc=com 
> --bindPassword bribery 
> --assertionFilter "(street=500 3rd Street)"
dn: uid=bjensen,ou=people,dc=example,dc=com
changetype: modify
replace: street
street: 33 New Montgomery Street

Processing MODIFY request for uid=bjensen,ou=people,dc=example,dc=com
MODIFY operation successful for DN uid=bjensen,ou=people,dc=example,dc=com

“Make the modification, and shut up”

The Permissive Modify Control is handy when you want to make a modification no matter what. It lets you add an attribute that already exists, or delete one that is already gone without getting an error.

As an example, let’s make sure user.0 is a member of a big static group. It doesn’t matter whether user.0 was already a member, but if not, we want to make sure user.0 is added to the group.

$ ldapmodify 
>  --port 1389 
>  --bindDN uid=user.1,ou=people,dc=example,dc=com 
>  --bindPassword password 
>  --control 1.2.840.113556.1.4.1413
dn: cn=Static,ou=Groups,dc=example,dc=com
changetype: modify
add: member
member: uid=user.0,ou=people,dc=example,dc=com

Processing MODIFY request for cn=Static,ou=Groups,dc=example,dc=com
MODIFY operation successful for DN cn=Static,ou=Groups,dc=example,dc=com

“Delete the children, too”

The Subtree Delete Control lets you delete an entire branch of entries.

As an example, let’s delete ou=Groups,dc=example,dc=com and any groups underneath. The user doing this needs an access to use the tree delete control, as in aci: (targetcontrol="1.2.840.113556.1.4.805") (version 3.0; acl "Tree delete"; allow(all) userdn ="ldap:///uid=user.1,ou=people,dc=example,dc=com";).

$ ldapdelete 
>  --port 1389 
>  --bindDN uid=user.1,ou=people,dc=example,dc=com 
>  --bindPassword password 
>  --deleteSubtree 
>  ou=Groups,dc=example,dc=com
Processing DELETE request for ou=Groups,dc=example,dc=com

DELETE operation successful for DN ou=Groups,dc=example,dc=com

As mentioned above, OpenDJ directory server supports many LDAP controls. So does OpenDJ LDAP SDK. If you want to use one in your application, see the Dev Guide chapter on Working With Controls.

OpenDJ directory server & groups

OpenDJ Logo When you think about groups in general, you realize there are different ways to define groups.

You can define a group by:

  • Specifying attributes that all members have in common (“All the software developers in Grenoble”).
  • Listing the members (“Alice, Bob, Carol”).
  • Using a mix of both (all the software developers in Grenoble, plus Alice, Bob, and Carol).

Notice that when you define a group by attributes of its members, the size of the definition is not a function of the size of the group. “All the software developers in Grenoble” remains the same size, even if the number of software developers in Grenoble varies.

Also notice that when you define a group by listing its members, the size of the definition depends mainly on the size of the group. “Alice, Bob, Carol” is about half the size of “Alice, Bob, Carol, Dan, Elena, Francis.”

OpenDJ directory server has groups of each of these types.

  • OpenDJ represents groups as directory entries. The group entry’s objectClass tells you what type of group it is.
  • Dynamic groups work by specifying attributes that all members have in common. They identify members by LDAP URLs, as in memberUrl: ldap:///ou=Developers,ou=People,dc=example,dc=com??sub?l=Grenoble. This is like specifying members by LDAP search, as in ldapsearch --baseDN ou=Product Development,ou=People,dc=example,dc=com "(l=Grenoble)".
    Dynamic group entries have objectClass: groupOfUrls. Dynamic group entries generally remain small even when they have lots of members.
  • Static groups list each member. Static group entries can have several object classes in OpenDJ, including groupOfNames, groupOfUniqueNames, and groupOfEntries.
    For groups with objectClass: groupOfNames and objectClass: groupOfEntries the member attribute is member, as in

    member: uid=Alice,ou=People,dc=example,dc=com
    member: uid=Bob,ou=People,dc=example,dc=com
    member: uid=Carol,ou=People,dc=example,dc=com
    member: cn=Grenoble Developers,ou=Groups,dc=example,dc=com

    As you would expect, static group entries get larger as you add members.

    You can nest groups, too, by adding a group as a member of a group. (For instance, the last member in the example is the Grenoble Developers group.)

    When you delete an entry or rename an entry, you no longer want it referenced in static groups. OpenDJ has a referential integrity plugin to handle this.

  • When you look up a dynamic group in OpenDJ what you get is the memberUrl value. This is fine if you are ready to use the LDAP URL, but not so great if you just wanted a list of the member entries. OpenDJ therefore provides what are called virtual static groups. Virtual static groups have OpenDJ look up the members of a dynamic group, and then return the list when you read the entry.

Checking group membership

In general, avoid reading and writing whole static group entries, because static groups can be large. Why read an entire 1-million-member static group entry over the network when all you want is to do is check membership for one or two entries?

To make it easy to check group membership, OpenDJ provides a virtual attribute, isMemberOf. If you explicitly request isMemberOf with a search, the values OpenDJ returns are the DNs of groups the entry belongs to. Reading isMemberOf is the recommended way to look up group membership.

Updating static groups

You can update a large OpenDJ static group without reading the group, and without checking membership beforehand. Use the Permissive Modify control (--control 1.2.840.113556.1.4.1413).

If you have an application that needs notification of changes to groups, OpenDJ has you covered there as well. Instead of polling group entries, you can use the external change log mechanism. The external change log is related to directory replication.

Where to go from here

This discussion of OpenDJ groups only scratches the surface. To dig a bit deeper, have a look at these sections in the documentation: