Table of Contents

LDAP con slapd 2.5.13

Aggiornando da Debian 11 a Debian 12 Bookworm che installa slapd 2.5.13, non è più supportato il vecchio backend HDB, in syslog si legge l'errore:

slapd[1081465]: lt_dlopenext failed: (back_hdb) file not found

Il backend alternativo consigliato è LMDB.

Durante l'aggiornamento (fallito) del pacchetto è stato comunque creato il backup della vecchia installazione, questa si trova in /var/backups/slapd-2.4.57+dfsg-3+deb11u1/. Conviene copiare i file presenti per lavorare su quelli.

Migrazione da HDB a MDB

FIXME La Service - Migrating from OpenLDAP 2.4.x to 2.5.x non ha funzionato; fallisce quando si tenta di ricaricare il database dc=rigacci,dc=org.ldif con il comando slapadd.

Per ripristinare il servizio si sono eseguite ex-nove tutte le operazoni necessarie, in particolare:

(Re)installation from scratch

By installing the slapd package from scratch, an empty LDAP database is created using the dn (distinguished name) dc=lan,dc=rigacci,dc=net (i.e. the output of the hostname --domain - which in our case is lan.rigacci.net - is used to generate the dc domain content parts of the name). During configuration you are asked for a password to be assigned to the admin user, i.e. to the item cn=admin,dc=rigacci,dc=net.

The LDAP database is numbered as #1; initially it contains only the root objext objectClass: organization. You can view it with the command

slapcat -n1

​If you run dpkg-reconfigure slapd it is possibile to generate the LDAP database again; you can change the distinguished name, assign a different organization name and the admin password.

Actually a special database numbered #0 named cn=config is created too. Here you can view the configuration options of the database #1, the (hashed) password of the admin user, etc. You can view that special database using:

slapcat -n0

Reading the dump of database #0, you can see that the cn=config database has the olcRootDN: cn=admin,cn=config, but it does not have an olcRootPW, so you cannot modify the config database connecting with a login/password pair. See below on how to modify the cn=config database (e.g. to add a new database backend).

Enable SSL

Create a self signed certificate or get it from some provider, like Let's Encrypt. Copy the files into /etc/ldap/ssl/ and give them permissions for the openldap user.

Create the following file config-ssl.ldif:

dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/ssl/fullchain.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/ssl/privkey.pem
-
replace: olcTLSCACertificatePath
olcTLSCACertificatePath: /etc/ssl/cert

and load it into the slapd 2.5 configuration:

ldapmodify -Y EXTERNAL -H ldapi:/// -f config-ssl.ldif

Enable ldaps into /etc/default/slapd:

SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"

Restart the slapd service.

Adding a second (new) database

Suppose you want to create a new LDAP database, beside the #0 (the cn=config one) and the #1 (with the suffix dc=lan,dc=rigacci,dc=net). This is possibile because the slapd daemon can serve different DITs (Directory Information Tree) eventually using different database backends, different olcRootDN, etc. The only constraint is that different databases must have different suffixes belonging to different hierarchy trees.

To add a new LDAP database you will use the ldapadd command. You may find several tutorials on the net that instruct on how to use the slapadd command, but beware that slappadd is not intended for incremental use; it is used for the initial configuration of the slapd service, when you feed it a single complete LDIF.

Using ldapadd to create a new database, requires the privilege to modify the cn=config database. The default Debian installation does not assign a password to the cn=admin,cn=config entry, so you cannot use a standard TCP connection to the server, you must use the EXTERNAL SASL mechanism.

Here it is the example of an LDIF file to create a new DIT database, supposed to contain an addressbook. We will use the MDB backend and the /var/lib/ldap/abook/ directory will contain the data. The database will be populated later. The item cn=admin,ou=Addressbook,dc=rigacci,dc=org is defined here and it will be used as an administrator account with full privileges on the database itself. Beware that the olcSuffix must not be a child of an already existing database suffix (notice that we used the org top level domain instead of net used in the previous examples).

The file was named abook-db.ldif:

dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbDirectory: /var/lib/ldap/abook
olcRootDN: cn=admin,ou=Addressbook,dc=rigacci,dc=org
olcRootPW: MySecret
olcSizeLimit: 1500
olcDbMaxSize: 104857600
olcSuffix: ou=Addressbook,dc=rigacci,dc=org
olcDbIndex: objectClass eq
olcDbIndex: cn,givenName,mail,sn eq,sub
olcAccess: to * by dn="cn=admin,ou=Addressbook,dc=rigacci,dc=org" write
    by anonymous auth
    by dn="cn=guest,ou=Addressbook,dc=rigacci,dc=org" read

Notice we will grant read-only privileges to an item cn=guest in the same LDAP tree; that item will be added into the database later. Before creating the database we create the destination directory and assign the required permissions:

mkdir /var/lib/ldap/abook
chmod 750 /var/lib/ldap/abook
chown openldap:openldap /var/lib/ldap/abook

Method #1: connecting without a password

To integrate the new configuration into the existing one and to activete it, just run the following command as root:

ldapadd -Y EXTERNAL -H ldapi:/// -f abook-db.ldif

The new database will be created and it will be assigned the number #2. An LDIF configuration file will be created into /etc/ldap/slapd.d/cn=config/olcDatabase={2}mdb.ldif.

If the suffix is child of an already existing database, we will get the following error:

adding new entry "olcDatabase=mdb,cn=config"
ldap_add: Other (e.g., implementation specific) error (80)
        additional info: <olcSuffix> namingContext "ou=Addressbook,dc=rigacci,dc=org"
        already served by a preceding mdb database

Method #2: setting a password for the cn=config database

If you want to use ldapadd over a standard TCP connection to alter the cn=config database, you must first add the olcRootPW attribute to the database. Create an config-chpasswd.ldif file:

dn: olcDatabase={0}config,cn=config
changetype: modify
replace: olcRootPW
olcRootPW: ConfigMySecret

then feed this file to the running slapd service, authenticating with the EXTERNAL SASL mechanism:

ldapmodify -Y EXTERNAL -H ldapi:/// -f config-chpasswd.ldif

Now it is possibile to connect the slapd service and feed the abook.ldif, we will bind using the cn=admin,cn=config name with the associated password:

ldapadd -x -W -D "cn=admin,cn=config" -f abook-db.ldif

Adding an additional schema

The default installation of slapd in Debian 12 creates some LDAP schemas into the default configuration; namely (see the /etc/ldap/slapd.d/cn=config/cn=schema/ directory):

Suppose you want to install an additional schema, e.g. the mozillaAbPersonAlpha, to create an address book database. Get the schema file from the Mozilla Wiki and have a look inside it; from the comments you can see that this schema depends upon core, cosine and inetorgperson, this means that no other schemas are required. Save the schema file into /etc/ldap/schema/mozillaabpersonalpha.schema.

We will use the slaptest tool in a tricky manner. First we will create a slapd-tmp.conf using the old slapd.conf(5) syntax (OpenLDAP pre-2.5 versions), then slaptest will be used to generate, into a temporary directory, the configuration files using the new slapd-config(5) syntax. From the temporary directory only the ldif file relative the mozillaAbPersonAlpha schema will be copied into the actual slapd configuration directory.

echo "Creating a slapd-tmp.conf file..."
cat << EOF > slapd-tmp.conf
include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/mozillaabpersonalpha.schema
EOF
 
echo "Converting slapd.conf(5) file into slapd-config(5) ldif files..."
mkdir slapd-tmp.d
slaptest -f slapd-tmp.conf -F slapd-tmp.d
 
echo "Copying mozillaAbPersonAlpha schema into actual Slapd config..."
systemctl stop slapd.service
cp "slapd-tmp.d/cn=config/cn=schema/cn={4}mozillaabpersonalpha.ldif" "/etc/ldap/slapd.d/cn=config/cn=schema/"
chown openldap:openldap "/etc/ldap/slapd.d/cn=config/cn=schema/cn={4}mozillaabpersonalpha.ldif"
chmod 0600              "/etc/ldap/slapd.d/cn=config/cn=schema/cn={4}mozillaabpersonalpha.ldif"
systemctl start slapd.service

Restore from the backup file

The upgrade process created a backup of the existing LDAP database into the /var/backups/slapd-2.4.57+dfsg-3+deb11u1/ directory. In our case there is a single file dc=rigacci,dc=org.ldif containing all the required entries. In the following examples we extracted from the file the logically different items to be restored.

Beware that the restore will be not a perfect copy of the previous database. Several tags must be purged from the backup file before feeding it back to the LDAP server because they are not allowed to be set directly. They are:

Once a snippet of the file is ready, you can feed it to the slapd service with the following command:

ldapadd -x -W -D "cn=admin,ou=Addressbook,dc=rigacci,dc=org" -f file.ldif

In the following three paragraphs we will see what is needed for a full restore.

Create the Addressbook organizationalUnit

dn: ou=Addressbook,dc=rigacci,dc=org
objectClass: top
objectClass: organizationalUnit
ou: Addressbook

Create the Addressbook guest person

dn: cn=guest,ou=Addressbook,dc=rigacci,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
sn: guest
cn: guest
userPassword: ReadOnlySecret

Load all the mozillaAbPersonAlpha entries

Each mozillaAbPersonAlpha item is somethink like this, after removing the unallowed tags:

dn: cn=Niccolo Rigacci,ou=Addressbook,dc=rigacci,dc=org
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: mozillaAbPersonAlpha
cn: Niccolo Rigacci
givenName: Niccolo
sn: Rigacci
mail: niccolo@rigacci.org
telephoneNumber: 055-0118525
mobile: 327-5556667
facsimileTelephoneNumber: 055-0118525
homePhone: 055-8979395
mozillaWorkUrl: http://www.rigacci.org/

Testing an ldapsearch

Finally you can test if the LDAP database is working doing a full search with ldapsearch:

ldapsearch -W \
    -H ldap://127.0.0.1/ \
    -D "cn=guest,ou=Addressbook,dc=rigacci,dc=org" \
    -b 'ou=Addressbook,dc=rigacci,dc=org'

The ldap protocol is on port 389/tcp, ldaps is on 636/tcp.

Web References