OpenLDAP - Changer de moteur backend

Depuis la version 2.4, le moteur de stockage recommandé par défaut pour OpenLDAP est MDB ou LMDB (Lightning Memory-Mapped Database). Dans les distributions Red Hat par contre, c'est toujours le moteur BDB (Berkeley DataBase), ou son évolution HDB (Hierarchical Database) qui est recommandé et utilisable, vu la version ancienne utilisé : 2.4.23.

HDB est une variante du backend BDB. HDB utilise un modèle hiérarchique, qui supporte notamment le renommage d'un sous-arbre. Etant basé sur BDB, les mêmes options de configurations sont présentes.

OpenLDAP recommande d'utiliser la version la plus récente de l'annuaire, qui corrige des bugs et apporte des améliorations. En cette fin d'année 2013, c'est actuellement la version 2.4.38.

Si l'on a installé un OpenLDAP depuis plusieurs années, on peut vouloir changer le moteur, afin d'améliorer les performances et de s'assurer du support OpenLDAP.

Instanciation d'une base BDB (ou HDB)

On peut facilement créer un suffixe avec une base BDB ou HDB, via la commande :

ldapadd -c -x -D cn=admin,cn=config -w password -f newbdb.ldif 

Si on utilise une authentification système (par défaut), la commande sera la suivante :

ldapadd -Y EXTERNAL -H ldapi:/// -f newbdb.ldif

Le contenu du fichier newbdb.ldif étant le suivant :

dn: olcDatabase=bdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcBdbConfig
olcDatabase: bdb
olcSuffix: dc=example,dc=bdb
olcDbDirectory: /data/openldap/example-bdb
olcRootDN: cn=Manager,dc=example,dc=bdb
olcRootPW: secret
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn pres,eq,approx,sub
olcDbIndex: objectClass eq
olcDbCacheSize: 20000
olcDbCheckpoint: 512 30
olcDbConfig: set_cachesize 0 10485760 0
olcDbConfig: set_lg_bsize 2097512
olcDbConfig: set_flags DB_LOG_AUTOREMOVE
olcAccess: to attrs=userPassword
  by self write 
  by anonymous auth 
  by dn.base="cn=Manager,dc=example,dc=bdb" write
  by * none 
olcAccess: to *
  by self write
  by dn.base="cn=Manager,dc=example,dc=bdb" write
  by * read

Idem pour un backend HDB :

dn: olcDatabase=hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: hdb
olcSuffix: dc=example,dc=hdb
olcDbDirectory: /data/openldap/example-hdb
olcRootDN: cn=Manager,dc=example,dc=hdb
olcRootPW: secret
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn pres,eq,approx,sub
olcDbIndex: objectClass eq
olcDbCacheSize: 20000
olcDbCheckpoint: 512 30
olcDbIDLcacheSize: 320000
olcDbConfig: set_lg_bsize 2097512
olcDbConfig: set_flags DB_LOG_AUTOREMOVE
olcAccess: to attrs=userPassword
  by self write 
  by anonymous auth 
  by dn.base="cn=Manager,dc=example,dc=hdb" write
  by * none 
olcAccess: to *
  by self write
  by dn.base="cn=Manager,dc=example,dc=hdb" write
  by * read

Les options olcDbConfig permettent de générer le fichier DB_CONFIG dans le répertoire des données.

Note : pour une database de type hdb, la valeur idlcachesize doit être importante pour avoir de bonnes performances en lecture / recherche, typiquement 3 fois ou plus la taille du cache d'entrées.

Note : il faut auparavant avoir créer le répertoire correspondant à olcDbDirectory, et mettre le compte ldap comme propriétaire de ce répertoire. Par exemple :

mkdir -p /data/openldap/example-hdb
chown ldap:ldap /data/openldap/example-hdb

 

Cohabitation HDB / BDB

Si on utilise les 2 backends conjointement sur le même serveur, le démarrage du daemon slapd donne un message d'avertissement :

back-bdb/back-hdb monitor: "olmBDBAttributes" previously defined "1.3.6.1.4.1.4203.666.1.55.0.1.1"
back-bdb/back-hdb monitor: "olmBDBObjectClasses" previously defined "1.3.6.1.4.1.4203.666.3.16.0.1.1"

Avantage de HDB

Le modèle HDB permet de renommer un sous-arbre complet via l'opération modrdn, mais pas BDB. Par exemple, si on a le fichier ldif suivant :

dn: ou=BACKEND-HDB,ou=users,dc=example,dc=corp
changetype: modrdn
newrdn: ou=BACKEND-RENAMED
deleteoldrdn: 1

Sur l'annuaire 121 cette database utilise BDB. On a alors :

ldapmodify -x -h 192.168.56.121 -D "cn=admin,dc=example,dc=corp" -w secret modrdn.ldif
ldap_initialize( ldap://192.168.56.121 )
modifying rdn of entry "ou=BACKEND-HDB,ou=users,dc=example,dc=corp"
	new RDN: "ou=BACKEND-RENAMED" (do not keep existing values)
ldap_rename: Operation not allowed on non-leaf (66)
	additional info: subtree rename not supported

Sur l'annuaire 122, la database utilise HDB. Le résultat est différent :

ldapmodify -x -h 192.168.56.122 -D "cn=admin,dc=example,dc=corp" -w secret modrdn.ldif
ldap_initialize( ldap://192.168.56.122 )
modifying rdn of entry "ou=BACKEND-HDB,ou=users,dc=example,dc=corp"
	new RDN: "ou=BACKEND-RENAMED" (do not keep existing values)
rename complete

Réplication HDB / BDB

On peut tout à fait avec deux moteurs différents sur 2 serveurs qui se répliquent. Ceci permet par exemple de procéder par étape pour un changement de backend sur une architecture avec de multiples serveurs.

Les tests effectués en mode master / miroir ont montré que la réplication fonctionnait de manière tout à fait normale, sauf dans un cas : le renommage de subtree sur l'annuaire utilisant HDB. Dans ce cas, l'opération n'est pas répliquée sur le serveur utilisant BDB.

 

Instanciation MDB

Le backend MDB peut être instancié avec peu d'éléments :

dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcSuffix: dc=example,dc=mdb
olcDbDirectory: /data/openldap/example-mdb
olcRootDN: cn=Manager,dc=example,dc=mdb
olcRootPW: secret
olcDbMaxSize: 1073741824        

La variable olcDbMaxSize doit être égale (ou supérieure) à la taille des données de l'annuaire, car le moteur MDB travaille en mémoire.

Procédure de migration

Les backends n'étant pas compatible physiquement, il n'est pas possible de modifier uniquement la configuration de la Database. Le changement de type de backend comporte également une migration de données, qui doit s'effectuer de manière "logique" :

  • Arrêt du daemon slapd
  • Export des données en LDIF (via slapcat)
  • Sauvegarde de l'ancien répertoire (pour le retour arrière)
  • Changement de la configuration de la database
  • Chargement des données (via slapadd)
  • Redémarrage du daemon et contrôle

Changement de configuration

Deux options peuvent être envisagées :

  • Modification des fichiers LDIF de configuration (dans le répertoire slapd.d/cn=config)
  • Création de la nouvelle base, via un fichier LDIF et un ldapadd

Option 1 : modification du fichier de configuration

Dans ce cas, on copie / renomme les fichiers /etc/openldap/slapd.d/cn=config/olcDatabase={X}bdb.ldif en /etc/openldap/slapd.d/cn=config/olcDatabase={X}hdb.ldif et on modifie les instances bdb par hdb :

dn: olcDatabase={2}bdb
objectClass: olcBdbConfig
olcDatabase: {2}bdb
structuralObjectClass: olcBdbConfig

devient

dn: olcDatabase={2}hdb
objectClass: olcHdbConfig
olcDatabase: {2}hdb
structuralObjectClass: olcHdbConfig

Les modifications doivent être faites une fois l'annuaire arrêté.

Si on a mis en place des overlays, il faut également renommer le répertoire content la définition de ces overlays. Dans notre cas, le répertoire

/etc/openldap/slapd.d/cn=config/olcDatabase={2}bdb

sera renommé en

/etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb

Option 2 : ajout de la DB par LDIF

Dans cette option, il faut supprimer la database déclarée avec bdb, et ajouter la même database utilisant hdb. En effet, il n'est pas possible d'utiliser 2 databases pour le même root Suffix.

Il faut tout d'abord identifier le numéro de la database utilisée :

ldapsearch -D 'cn=admin,cn=config' -w secret -x -b "cn=config" "objectclass=olcbdbconfig"
# {4}bdb, config
dn: olcDatabase={4}bdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcBdbConfig
olcDatabase: {4}bdb
olcDbDirectory: /product/openldap/data/example-bdb
olcSuffix: dc=example-bdb,dc=com
olcAccess:: ezB9dG8gYXR0cnM9dXNlclBhc3N3b3JkIGJ5IHNlbGYgd3JpdGUgIGJ5IGFub255bW
 91cyBhdXRoICBieSBkbi5iYXNlPSJjbj1BZG1pbixkYz1leGFtcGxlLWJkYixkYz1jb20iIHdyaXR
 lIGJ5ICogbm9uZSA=
olcAccess: {1}to * by self write by dn.base="cn=Admin,dc=example-bdb,dc=com" w
 rite by * read
olcRootDN: cn=Manager,dc=example-bdb,dc=com
olcRootPW: secret
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn pres,eq,approx,sub
olcDbIndex: objectClass eq

Dans notre exemple, c'est la database numéro 4 qu'il faudra supprimer.
La suppression n'est pas (a priori) faisable via une commande ldap. Il faut donc arrêter le service slapd, et supprimer le fichier manuellement.
Il faut également se positionner dans le répertoire des données, et supprimer tous les fichiers (que l'on aura sauvegardé auparavant, bien sûr).
La nouvelle database peut être crée via un fichier LDIF, une fois le service redémarré. Dans notre exemple, le fichier LDIF est :

dn: olcDatabase=hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: hdb
olcSuffix: dc=example-bdb,dc=com
olcDbDirectory: /product/openldap/data/example-bdb
olcRootDN: cn=Manager,dc=example-bdb,dc=com
olcRootPW: secret
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn pres,eq,approx,sub
olcDbIndex: objectClass eq
olcAccess: to attrs=userPassword
  by self write
  by anonymous auth
  by dn.base="cn=Admin,dc=example-bdb,dc=com" write
  by * none
olcAccess: to *
  by self write
  by dn.base="cn=Admin,dc=example-bdb,dc=com" write
  by * read

La création s'effectue de la manière suivante :

service slapd start
ldapadd -D 'cn=admin,cn=config' -w secret -x -f hdb-conf.ldif

 

Chargement des données

On peut alors charger les données issues du slapcat, après avoir arrêté le daemon via la commande :

service slapd stop
slapadd -b BASE -q -l FICHIER.ldif

Il faut ensuite remettre les droits corrects sur les données.

Points à vérifier

Si on passe d'un serveur à un autre, il faut également récupérer toutes les définitions de schéma.

De même, il faut s'assurer que les overlays soient en place sur les 2 configurations, sinon l'import des données risque de tombe en erreur. Notamment les attributs liés aux password policy

Note : Le core.ldif ne contient plus l'attribut userPassword ? (commenté dans /etc/ldap/schema/core.ldif). Il faut alors modifier : pwdAttribute: userPassword en pwdAttribute: 2.5.4.35
syntaxe de pwdAttribute = OID

Références

Catégorie