389 libs of glue – aka how to get rid of resurrecting entries

A directory server topology could be quite complex and it could happen that deleted entries are resurrected due to replication conflicts.

Those entries are marked with:
– the “glue” and “extensibleObject” objectclass
– the “nsds5ReplConflict” attribute

You may need to filter those entries, and the suggested way is to use an ACI, as suggested in the official documentation.

certutil cheatsheet for 389 Directory Server

389 certificates – like google crome – are managed via nss-util, a crypto suite which includes the following tools:
– certutil for managing certificates
– pk12util for managing PKCS12 certificate bundles

NSS store certificates in a directory containing the following files:
* cert8.db, secmod.db, key3.db
and an optional file with the keystore password to be used by 389
* pin.txt

To shorten paths we replace
# certutil -d /path/to/pki/
# certutil -d.

We can list certs with
# certutil -d. -L

Exporting and re-importing a CA Certificate

Export our certificate in txt
# certutil -d. -L -n babel.it -a > babel.it.asc

Import our certificate (eg. on another server).
# certutil -d. -L -n babel.it -t "CT,," -a -i babel.it.asc

Export SSL certificate+key

PKCS12 is a container format for bundling certs and keys. It uses an encrypted format.

Exporting a key requires two passwords:
1- the keystore password
2- the key-certificate password

certutil DOES NOT allow to store both cert and key. We must use pk12util both for
* exporting the cert+key from a keystore
* importing the cert+key in a new keystore
# pk12util -d. -L -n foo.babel.it -i foo.babel.it.p12

NSS can’t retrieve keys in PEM format, so we can use openssl to do it and strip off the encryption part used by p12 to protect the bundle. NOTE: certutil doesn’t allow to IMPORT a non-p12 key but we may want to export and reimport to change eg. the certificate name.

# openssl pkcs12 -in foo.babel.it.p12 -nodes -clcerts -out bar.babel.it.pem
# openssl pkcs12 -export -in bar.babel.it.pem -inkey bar.babel.it.pem -nodes -name bar.babel.it -out bar.babel.it.p12

Import SSL keys under a new 389 instance

Importing a new key+cert under a keystore which is not password-protected will lead to the following error – that arises when we try to list private keys

# certutil -d. -K
certutil: Checking token "NSS Certificate DB" in slot "NSS User Private Key and Certificate Services "
certutil: could not authenticate to token NSS Certificate DB.: An I/O error occurred during security authorization.

This means that our keystore is not password-protected and cannot store certificate keys. We can fix with
# certutil -d. -W

Now that our keystore is fine, we can just add the keypair.
NOTE: IMPORT DOES NOT SUPPORT NAMING. You must change the certificate name with openssl *before* importing
# pk12util -d. -i bar.babel.it.p12

Verify your keystore
Check that we have both keys and certs

# certutil -d. -L
# certutil -d. -K

python dsadmin module: 389 made easy

Rich Megginson, the 389 Keymaster, created this wonderful python library https://github.com/richm/scripts

To create a new root suffix just

credential = {
'host': 'localhost,
'port': 10389,
'cn=directory manager',
'bindpw': 'secret'

Connect to an already-existing instance passing our dict variable as function arguments
conn = DA(**credential)

Create a backend database
backend_name = conn.setupBackend('o=addressbook1')

Bind it to an entry
conn.setupSuffix(suffix='o=addressbook1', bename=backend_name)

And create the entry

e = Entry('o=addressbook1')
e.setValue('objectclass', ['top','organization'])

Easy, isn’t it?

Nobody backups 389 Directory Server!

389 Directory Server  (like Sun/Oracle DS) has a nice tool for taking logical backups: db2ldif. Logical backups are – simply – backups taken in an exportable format – like LDIF or SQL. They differ from raw backups – which are taken copying or snapshotting data files.

db2ldif works triggering a backup in 389: it simply tells to slapd – the ldap daemon – to export a backup on a given file

As 389DS usually runs as user “nobody”, there’s a common error you’ll se when running it:

# db2ldif -s "dc=babel,dc=it" -U -a /backup-ldap/myds.$(date -I).ldif
db2ldif: can't open /backup-ldap/myds.2012-06-14.ldif: 13 (Permission denied)

Actually it’s not the command you’re running that lacks permissions, but the user “nobody”.

# chown -R nobody /backup-ldap/
And everything will work fine!