OpenDJ Cheat Sheet

I love this product. Following is my OpenDJ Cheat Sheet. This is a Work in Progress, but I needed to have it available for my own purposes. Hope others find it useful.

OpenDJ Cheat Sheet

Introduction

The examples below are all done at the command line. Many of the configuration changes shown below can also be done using an LDAP editor like Apache Directory Studio or using an LDIF file and ldapmodify.

When setting up a new OpenDJ server I usually create a system opendj user and group to own the instance. Unfortunately, as a pure Java app OpenDJ has to be run as root in order to listen on standard LDAP ports 389 and 636 (LDAPS). I get around this by using the server’s own firewall to redirect traffic coming in over ports 389 and 636 to ports above 1000 on my server (usually ports 1389 and 1636).

See my Using iptables to redirect LDAP ports for a way to avoid running OpenDJ as root while still serving up access over port 389 and 636.

[root@test1 opendj]# pwd
/opt/opendj
[root@test1 opendj]# ls
ds-user1  OpenDJ-2.4.5.zip
[root@test1 opendj]# chown -R root:opendj ds-user1
[root@test1 opendj]# chmod g+rwx ds-user1
[root@test1 opendj]# chmod -R g+rw ds-user1
[root@test1 opendj]# ls -l
total 17700
drwxrwx--- 18 opendj opendj     4096 Feb 20 18:20 ds-user1
-rw-r--r--  1 opendj opendj   18092296 Mar 21 11:15 OpenDJ-2.4.5.zip
[root@test1 ds-user1]#

Full documentation can be found in the OpenDJ Administration Guide. The documentation is actually quite good, although like most technical doc it could use more “real life” examples. You can never have too many examples.

When using command line utilities you will be making constant reference to the companion Configuration Reference.

The examples given below assume that the $DSHOME environment variable is set to the directory server’s installation path.

OpenDJ dsconfig utility help

The main command line utility used in configuring OpenDJ is dsconfig.

Several levels of help are available from the utility itself.

dsconfig --help

This provides a basic list of help topics.

dsconfig --help-core-server

Provides a more in-depth listing of sub commands and options to be used in managing core server settings.

Note that some options are set by default. For example, the bindDN property (“-D”) is assumed to be “cn=Directory Manager”.

You can avoid having to enter the bindPassword (“-w”) by creating a text file that contains the password in clear text. Having done this you can use the “-j” option to point to that file, for example “-j $HOME/etc/pwd.txt”.

The utility also has a menu driven interactive mode that may be more efficient to use when doing initial setup of a directory server, this can be invoked with:

dsconfig

the utility will prompt for all required information.

Starting and Stopping a Directory Instance

Starting an instance

Execute “$DSHOME/bin/ds-start”.

Stopping an instance

Execute “$DSHOME/bin/ds-stop”.

Getting instance status

$DSHOME/bin/status

Follow the prompts:

[opendj@test1 ~]$ $DSHOME/bin/status

>>>> Specify OpenDS LDAP connection parameters

Administrator user bind DN [cn=Directory Manager]: 

Password for user "cn=Directory Manager": 

          --- Server Status ---
Server Run Status:        Started
Open Connections:         1

          --- Server Details ---
Host Name:                test1.myco.com
Administrative Users:     cn=Directory Manager
Installation Path:        /opt/opendj/ds-user1
Version:                  OpenDJ 2.4.5
Java Version:             1.6.0_30
Administration Connector: Port 5444 (LDAPS)

          --- Connection Handlers ---
Address:Port : Protocol               : State
-------------:------------------------:---------
--           : LDIF                   : Disabled
0.0.0.0:161  : SNMP                   : Disabled
0.0.0.0:1389 : LDAP (allows StartTLS) : Enabled
0.0.0.0:1636 : LDAPS                  : Enabled
0.0.0.0:1689 : JMX                    : Disabled

          --- Data Sources ---
Base DN:     dc=example,dc=com
Backend ID:  userRoot
Entries:     1
Replication: Disabled

[opendj@test1 ~]$ 

Configuring Directory Access and Performance

Making the lookthrough limit unlimited

dsconfig set-global-configuration-prop \
--set lookthrough-limit:0 \
-h localhost \
-p 5444 \
-w ********** \
-X \
-n 

To confirm the change was made use

dsconfig get-global-configuration-prop -h localhost 
-p 5444 -j $HOME/etc/pwd.txt -X -n

Note that in this example I’m using a password file rather than entering it on the command line.

Changing the search entries limit

dsconfig set-global-configuration-prop \
--set size-limit:25000 \
-h localhost \
-p 5444 \
-w ********** \
-X \
-n 

Changing the search time limit

dsconfig set-global-configuration-prop \
--set time-limit:5 m \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X \
-n 

Note the value for the time limit is expressed in minutes. To express it in seconds you would use the value “300 s”. On getting the property value you’ll see that the utility shows it in minutes.

Here again the command uses a password file (“pwd.txt” in the user’s home directory), the hostname has also been left off — leaving the program to default to the installation hostname. This is the minimal syntax allowed, and will be used in the remaining examples.

Turning schema checking on/off

You may need to turn off schema checking to get legacy data loaded into the directory. If you do turn it off, I recommend you turn it back on as soon as practicable. To turn off schema checking:

dsconfig set-global-configuration-prop \
--set check-schema:false \
-p 5444 \ 
-j $HOME/etc/pwd.txt \
-X \
-n 

To turn it back on just change the value of “check-schema” to “true”.

Seeing the state of this value (and others like it) requires invoking the “advanced” option for “get-global-configuration-prop”, thus:

disconfig --advanced set-global-configuration-prop \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X \
-n

Turning syntax checking on/off

Syntax checking was first introduced with Directory Server Enterprise Edition. It did not exist in Netscape/iPlanet/Sun directories prior to version 6. Having it enabled can present a major challenge for an initial data load or in subsequent exchanges of data between different directories.

To turn off syntax checking:

dsconfig set-global-configuration-prop \
--set invalid-attribute-syntax-behavior:warn \
-p 5444 \ 
-j $HOME/etc/pwd.txt \
-X \
-n 
dsconfig set-global-configuration-prop \
--set single-structural-objectclass-behavior:warn \
-p 5444 \ 
-j $HOME/etc/pwd.txt \
-X \
-n 

Note that the first command will allow attributes to be populated with “illegal” values (at least from a strict schema compliance perspective). The second command does the same for situations where multiple structural object classes are added to or exist in an entry.

To turn these “features” back on just change the value for “invalid-attribute-syntax-behavior” and/or “single-structural-objectclass-behavior” to “reject”.

Allowing pre-encrypted passwords

OpenDJ’s default password policy settings will cause it to reject any entry in an LDIF When trying to load an LDIF that includes the standard UUEncoded hash as the value for userPassword. To get around this set the “allow-pre-encoded-passwords” property to “true”.

dsconfig --help-user-management
dsconfig list-password-policies -p 5444 -j $HOME/etc/pwd.txt -X -n
dsconfig get-password-policy-prop \
--policy-name "Default Password Policy" \
--advanced \
-p 5444 -j $HOME/etc/pwd.txt -X -n

Here’s the command that should executed against ALL password policies (the example just gives “Default Password Policy”, the other that is there by default is the “Root Password Policy” that applies to all administrative accounts, including “cn=Directory Manager”):

dsconfig set-password-policy-prop \
--set allow-pre-encoded-passwords:true \
--policy-name "Default Password Policy" \
-p 5444 -j $HOME/etc/pwd.txt -X -n

so the other one you will always be concerned with would go like this:

dsconfig set-password-policy-prop \
--set allow-pre-encoded-passwords:true \
--policy-name "Root Password Policy" \
-p 5444 -j $HOME/etc/pwd.txt -X -n

Creating and modifying indexes

First, to enumerate all indexes:

dsconfig list-local-db-indexes \
--backend-name userRoot \
-p 5444 -j $HOME/etc/pwd.txt \
-X -n

Output for a newly created directory will look something like this:

Local DB Index   : Type    : index-type
-----------------:---------:--------------------
aci              : generic : presence
cn               : generic : equality, substring
ds-sync-conflict : generic : equality
ds-sync-hist     : generic : ordering
entryUUID        : generic : equality
givenName        : generic : equality, substring
mail             : generic : equality, substring
member           : generic : equality
objectClass      : generic : equality
sn               : generic : equality, substring
telephoneNumber  : generic : equality, substring
uid              : generic : equality
uniqueMember     : generic : equality

Creating an index:

dsconfig create-local-db-index \
--backend-name userRoot \
--index-name mycooffice \
--set index-type:substring \
-p 5444 -j $HOME/etc/pwd.txt \
-X -n

Modifying an index:

dsconfig set-local-db-index-prop \
--backend-name userRoot \
--index-name mycooffice \
--set index-type:equality \
-p 5444 -j $HOME/etc/pwd.txt \
-X -n

Rebuilding an index (always required after modifying, or adding a new index type for an already indexed attribute, and must be run sudo root):

$DSHOME/bin/rebuild-index \
-p 5444 -X \
-j $HOME/etc/pwd.txt \
-b dc=example,dc=com \
-i mycooffice \
-t 0

To add additional index types to an index you need to … “add” (rather than “set”) that type:

dsconfig set-local-db-index-prop \
--backend-name userRoot \
--index-name mycooffice \
--add index-type:substring \
-p 5444 -j $HOME/etc/pwd.txt \
-X -n

and then do another rebuild of the index.

Removing:

dsconfig delete-local-db-index \
--backend-name userRoot \
--index-name telexNumber \
-p 5444 -j $HOME/etc/pwd.txt \
-X -n

Rebuilding Degraded Indexes

Sometimes after adding a number of new indexes in bulk, or doing a big data load, the server errors log will indicate that some indexes are in a “degraded” state. This can be alleviated by doing a “rebuild-index –rebuildAll” (see “Dealing with Index Entry Limits” below), but in a directory with over 10,000 entries that might take longer than desired. The other option is to use the “–rebuildDegraded” option to only target the complained about indexes for rebuild:

$DSHOME/bin/rebuild-index \
-p 5444 -X \
-j /home/opendj/etc/pwd.txt \
-b dc=example,dc=com \
--rebuildDegraded \
-t 0

Dealing with index entry limits

DO THIS BEFORE LOADING DATA INTO YOUR DIRECTORY

Index entry limits were first introduced with OpenDS. Basically the same idea as the Netscape/Sun/iPlanet allids threshold (allids has been eliminated from the Red Hat/389 Directory codebase). Except that setting them to unlimited will result in a bad experience for users other than Directory Manager. For some implementations this could present problems. It cannot be set to unlimited due to a bug in the OpenDJ code. Some positive integer larger than 0 needs to be set for it.

The default value can be found here:

dn: ds-cfg-backend-id=userRoot,cn=Backends,cn=config
ds-cfg-index-entry-limit: 100000

The shipping default value is 4000. My own standard procedure after setup is to use an LDIF command file to change this default value to 100000. This is NOT a best practice, but the best I can do in my corporate environment where forcing developers to page their results isn’t an option (even LDAP admins have to answer to a higher power).

The “correct” way to do it is to use the dsconfig command:

dsconfig set-backend-prop \
--backend-name userRoot \
--set index-entry-limit:100000 \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X -n

Whether you modify the value using an LDAP command or with the above command, you must immediately follow with the obligatory “rebuildAll”. It is recommended that these changes be done before loading and indexing significant amounts of data into the directory to avoid a long wait while it is all reindexed (upwards of 24 hours for 50,000 entries — I kid you not):

$DSHOME/bin/rebuild-index \
-p 5444 -X \
-j /home/opendj/etc/pwd.txt \
-b dc=example,dc=com \
--rebuildAll \
-t 0

To get a snapshot of all indexes and their current state (including the number of indexes for each attribute), run this command:

$DSHOME/bin/dbtest list-index-status \
-n userRoot \
-b dc=example,dc=com

Extending the schema

Extending the schema can be done in one of 2 ways: (1) using the gui control-panel to add new attributetypes and objectclasses one by one; or (2) shutting down the directory and replacing the existing 99-user.ldif under $DSHOME/ds-user1/config/schema with one that has the attributetypes and objectclasses you want to add.

The advantage of (1), especially for beginners, is that the gui app checks your syntax and makes it harder to mess things up. Method (2) is best for updates involving many attributetypes and objectclasses, or in setting up a new directory instance with a custom schema already in place on another instance.

Directory Security

Setting up access control instructions

The aci syntax used by OpenDJ is basically the same as that shared by all those in the Netscape/ Sun/ RedHat family, with some exceptions that can be gleaned from the chapter on Configuring Privileges and Access Control in the OpenDJ Administration Guide. That section of the doc is required reading for understanding acis.

I have written a separate article about the pitfalls of the new default access controls located in “cn=Access Handler, cn=config” that ship with OpenDJ because I don’t think their impact will be appreciated by many admins.

Here’s a simple example that prevents anonymous (“anyone”) from reading all but a few attributes (note that a “real” LDIF would terminate each line at 80 characters and indent to indicate line continuation):

aci: (targetattr != "objectclass || uid || cn || sn || givenname ||
 mail || telephonenumber || title || l || st || street || postalcod
 e || c || telephonenumber || facsimiletelephonenumber || companyco
 de || o") (target = "ldap:///ou=People,o=*,dc=example,dc=com") (ve
 rsion 3.0;acl "Anyone access to People";deny(read,compare,search)(
 userdn = "ldap:///anyone");)

Note that the “ldap://anyone” tag used above, although it is often mis-characterized as “anonymous” actually means EVERYONE, and so will apply all users who bind to the directory.

The best way to add and modify acis is to create an LDIF file and use ldapmodify to add or replace. For the above aci the LDIF would look like:

dn: dc=example,dc=com
changetype: modify
add: aci
aci: (targetattr != "objectclass || uid || cn || sn || givenname ||
 mail || telephonenumber || title || l || st || street || postalcod
 e || c || telephonenumber || facsimiletelephonenumber || companyco
 de || o") (target = "ldap:///ou=People,o=*,dc=example,dc=com") (ve
 rsion 3.0;acl "Anyone access to People";deny(read,compare,search)(
 userdn = "ldap:///anyone");)

and the command to create:

ldapmodify -h localhost -p 1389 -D "cn=directory manager" -W -c -f newaci.ldif

Importing data

Data can be imported while the directory is online, or off line. The most often used online method is to use the ldapmodify utility to import LDIF formatted data.

The import-ldif command can also be used to schedule an import while the server remains on line. Use the “-t” option to indicate the time for execution (a value of 0 tells the system to do it immediately).

$DSHOME/bin/import-ldif \
-b dc=example,dc=com \
-n userRoot \
-l /tmp/big.ldif \
-t 20120518230000 \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X 

The -b option tells import-ldif what branch to import. The -n identifies the relevant database backend. The import file is indicated by “-l”.

The off line method is the most efficient to use when performing an initial load of large numbers of entries from LDIF. The import-ldif command is used in such a case.

First stop the directory server with the stop-ds command, then run import-ldif:

$DSHOME/bin/stop-ds

$DSHOME/bin/import-ldif \
-b dc=example,dc=com \
-n userRoot \
-l /tmp/big.ldif

There are several options available when using import-ldif. Some are very useful in doing point restores (that is, restores of particular entries or classes of entries). Here are some of the more important ones:

-F [–clear-backend], used to wipe out the existing entry data and replace with what’s in the import file.

-a [–append], will append what’s in the import file to existing entry data.

-r [–replace-existing], used in conjunction with -a to replace any existing entries with matching entries in the import file.

-S [–skipSchemaValidation], skip schema checking on loading the import file.

-R [–rejectFile], output rejected entries to a file.

-O [–overwrite], overwrite an existing rejects or skip file rather than appending to it.

-B [–excludeBranch], exclude a branch from import.

-c [–isCompressed], the import file is compressed.

-e [–excludeAttribute], exclude an attribute from each entry in the import.

-E [–excludeFilter], exclude entries matching the filter from the import.

-i [–includeAttribute], include an attribute in the entries imported.

-I [–includeFilter], include entries matching the filter in the import.

Exporting data

Data can be exported while the system is on line either by invoking the ldapsearch command and piping the results to a file, or with the export-ldif utility. The “-t” option can be used to indicate the time for execution (a value of 0 tells the system to do it immediately). The “–recurringTask” option allows for scheduling using crontab syntax. Other options can provide e-mail notification of success, or failure. Regular LDIF backups of directory data can be scheduled in this way.

$DSHOME/bin/export-ldif \
-b dc=example,dc=com \
-n userRoot \
-l /tmp/bigbackup.ldif 
-t0 \
--errorNotify ldapadmin@example.com \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X 

The -b option tells export-ldif what branch to import. The -n identifies the relevant database backend. The export file is indicated by “-l”.

Exporting while off line is sometimes the most efficient way to dump a copy of a large directory database. The export-ldif command is also used for this. As with an off line import, the directory server must first be shut down.

$DSHOME/bin/stop-ds

$DSHOME/bin/export-ldif \
-b dc=example,dc=com \
-n userRoot \
-l /tmp/bigbackup.ldif

There are several options available when running export-ldif that can be very helpful, particularly when migrating entries from one system to another. Here are some:

-a [–appendToLDIF], append rather than overwrite an existing LDIF file.

-B [–excludeBranch], exclude a branch from the export.

-c [–compress], compress the export file.

-e [–excludeAttribute], exclude an attribute from each entry in the export.

-E [–excludeFilter], exclude entries matching the filter from the export.

-i [–includeAttribute], include an attribute in the entries exported.

-I [–includeFilter], include entries matching the filter in the export.

-O [–excludeOperational], exclude all operational attributes.

Enabling the attribute uniqueness plugin

This is how you turn on the Attribute Uniqueness Postoperation Plugin, or “UID Unique Attribute” plugin, for short:

dsconfig set-plugin-prop \
--plugin-name "UID Unique Attribute" \
--set enabled:true \
-p 5444 \ 
-j $HOME/etc/pwd.txt \
-X \
-n

While uid uniqueness can be a key ally in maintaining data integrity, preventing the creation of duplicate entries for the same person, for example, you may want to turn it off when doing bulk changes to directory data such as when cloning or synchronizing one directory with another. That’s because the plugin would prevent operations like an LDAP “move”.

Referential Integrity

I originally hesitated to bring this up here, but in the environments where I work referential integrity — specifically making sure that when a user entry is removed from the directory all references to that entry in the LDAP groups the user was a member of — is important. So here’s how to turn it on:

dsconfig set-plugin-prop \
--plugin-name "Referential Integrity" \
--set enabled:true \
-p 5444 \ 
-j $HOME/etc/pwd.txt \
-X \
-n 

Note that having this plugin enabled could impact your entry delete times significantly, so you’ll need to gauge the acceptability of the effect for your own environment (this is the main reason it isn’t turned on by default, and why Oracle makes it so difficult to enable on Oracle Internet Directory).

Directory Replication

Enabling replication

To enable replication, execute the following commands:

. ~/ds-user1.env
$DSHOME/bin/dsreplication enable \
--adminUID admin \
--adminPassword xxxxxxx \
--baseDN "dc=example,dc=com" \
--host1 test1.example.com \
--port1 5444 \
--bindDN1 "cn=directory manager" \
--bindPassword1 xxxxxxx \
--replicationPort1 8989 \
--host2 test2.example.com \
--port2 5444 \
--bindDN2 "cn=directory manager" \
--bindPassword2 xxxxxxx \
--replicationPort2 8989 \
--trustAll \
--no-prompt

Note that this routine includes first sourcing the directory environment.

Initiating replication

. ~/ds-user1.env
$DSHOME/bin/dsreplication initialize-all \
--adminUID admin \
--adminPassword xxxxxxx \
--baseDN "dc=example,dc=com" \
--hostname test1.example.com \
--port 5444 \
--trustAll \
--no-prompt

This will cause the replication partner (in this example the directory on test2) to be initialized from the server on which initialization is being invoked (here test1). The data used will be the data on the initializing server (test1).

A more granular way of doing this is to use “initialize” rather than “initialize-all” (which initializes all currently enabled servers). In doing do you will need to specify “–hostSource”, “–portSource”, “–hostDestination” and “–portDestination”. This latter method is probably the safest in complex replication arrangements.

Monitoring replication

To enumerate an instance’s replicated servers:

dsconfig list-replication-server \
--provider-name "Multimaster Synchronization" \
-p 5444 \
-j $HOME/etc/pwd.txt \
-X -n

The dsreplication command can be invoked to show the current status of replication operations.

dsreplication status \
--adminUID admin \
--adminPassword xxxxxxx \
--hostname test1.example.com \
--port 5444 \
--trustAll 

The following branch off “cn=monitor” can also be queried to learn the current state of replication:

cn=replication,cn=monitor

Disabling Replication

To permanently disable all replication with a node:

. ~/ds-user1.env
sudo $DSHOME/bin/dsreplication disable \
--disableAll \
--hostname test1.example.com \
--port 5444 \
--bindDN "cn=directory manager" \
--adminPassword xxxxxxx \
--trustAll \
--no-prompt

To temporarily disable:

. ~/ds-user1.env
$DSHOME/bin/set-synchronization-provider-prop \
--hostname test1.example.com \
--port 5444 \
--bindDN "cn=directory manager" \
--bindPassword xxxxxxx \
--provider-name "Multimaster Synchronization" \
--set enabled:false \
--trustAll \
--no-prompt

To re-enable after temporarily disabled:

. ~/ds-user1.env
$DSHOME/bin/set-synchronization-provider-prop \
--hostname test1.example.com \
--port 5444 \
--bindDN "cn=directory manager" \
--bindPassword xxxxxxx \
--provider-name "Multimaster Synchronization" \
--set enabled:true \
--trustAll \
--no-prompt

Resetting Administrator Passwords

To reset the password for “cn=Directory Manager”:

1. Use “encode-password” utility to generate a hash of the new password:

encode-password -s SSHA512 -c newpassword

2. Shut down the directory (“stop-ds”).

3. Copy this hash value into $DSHOME/config/config.ldif, overwriting the existing value for “userpassword”:

dn: cn=Directory Manager,cn=Root DNs,cn=config
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
objectClass: ds-cfg-root-dn-user
userpassword: {SSHA512}e1N8lorBIdDPtPFRAwOn5d8hLmHHU4NYc4NV

Note that you should use vi or a serious programmers’ text editor like Atom or Notepad++ to edit the config.ldif file (set to Unix line endings and UTF-8 encoding). This is very important: After pasting the hash value in, with the file still open in vi hit ESC and go to the very end of the line containing the hash. Hit the x key to delete any whitespace after the last character of the hash. If using a text editor other than vi turn on visible spaces so you can remove the trailing whitespace that will definitely be there. If you don’t do this that space will be considered part of the hash by OpenDJ and attempts to authenticate will fail (simply adding whitepace to the end of your password will not cut it — this is a hash we’re talking about, not plaintext).

4. Start the directory back up (“start-ds”).

To reset the password for the replication admin (“admin”):

Use “ldappasswordmodify” as Directory Manager:

ldappasswordmodify \
-h localhost \
-p 1389 \
-D "cn=Directory Manager" \
-w directorymanagerpassword \
-a "dn: cn=admin,cn=Administrators,cn=admin data" \
-n newadminpassword