Article publié dans Linux Magazine 66, novembre 2004.
Copyright © 2004 - Jérôme Fenal.
slurpd
Après avoir vu les fondements du protocole LDAP, son organisation des données et son utilisation de base, intéressons-nous maintenant aux fonctionnalités avancées de sa mise en œuvre libre, OpenLDAP.
Nous verrons d'abord comment ajouter des données non standard par le biais d'un schéma qui nous est propre. Ensuite, la sécurisation du transport LDAP via SSL/TLS, et enfin la sécurisation du service via la réplication.
Il peut être plus qu'intéressant d'écrire son propre schéma. En effet, cela vous permettra d'avoir la sémantique la plus appropriée pour les données que vous désirez intégrer dans votre annuaire.
Nous allons voir ici rapidement comment écrire un petit schéma auxiliaire. Je ne parlerai cependant pas (sauf dans cette phrase) des considérations amenant à cette décision : centralisation des données dans un annuaire, création de nouvelles données au meilleur endroit (i.e. dans l'annuaire et non dans une application), etc. De même, je ne vous parlerai pas des implications de la création du schéma : pas de limitation directe sur la taille d'un champ, instrumentation nécessaire des applications utilisant les données du nouveau schéma, etc.
Nous avons vu précédemment sur la description des schémas que ceux-ci s'appuyaient sur des types de données documentés par la RFC2252. Ces types se voient associés à des ordres de tri, de même qu'à des règles de correspondance, qui sont fonctions du type de la donnée (« collate order » en anglais). Par exemple, les règles de tri associées à des contenus UTF-8 ne seront pas les mêmes que pour des contenus ASCII simples.
Avec OpenLDAP, la définition d'un schéma se fait dans le format des fichiers de
configuration de slapd
, alors que sur d'autres annuaires, le schéma est
lui-même inscrit dans l'annuaire (de façon logique, d'une part - par le biais de
qu'on pourrait appeler une vue - ou dans la base de données d'autre part). C'est
ainsi que l'on trouve deux formats de définition de schéma, le format LDIF,
et le format d'OpenLDAP, qui n'est qu'une partie du fichier de configuration de
slapd
(merci include
!). Nous avons déjà vu ces deux formats.
Mais comment arriver à un schéma à partir de notre liste de courses ?
En fait, c'est relativement simple, il suffit essentiellement de savoir ce que l'on doit mettre, comment le mettre, et surtout créer une sémantique qui ne soit pas ambiguë. De plus, elle ne devra de préférence pas non plus reprendre une sémantique d'un des schémas standards. Je ne saurai donc trop vous conseiller de prendre le temps de lire d'abord les RFC et schémas fournis par OpenLDAP.
Ensuite, il va falloir nous créer deux espaces de nommage. Le premier espace va s'appliquer aux noms des classes d'objets et des attributs. En règle générale, un simple suffixe suffit, tel que le nom de l'entreprise ou un acronyme.
Le second concerne les OID, identifiants numériques dont nous avons parlé dans l'article précédent. Pour identifier nos classes d'objet et nos attributs, nous ne pouvons pas choisir au hasard la 1ère partie des OID, au risque d'une collision avec des objets existants ou lors d'une prochaine extension de l'annuaire. Mais, et cela tombe bien, une branche spéciale dans l'arbre des OID existe pour ça, la branche enterprises. Pour l'utiliser, deux solutions : soit choisir un numéro au hasard, soit tout simplement s'enregistrer auprès de l'IANA qui les gère et les attribue de façon séquentielle. Pour des raisons de commodité, je prendrai le numéro 99999.
Mais cela ne nous donne que la première partie de l'espace de nommage des OID.
La seconde partie est de savoir comment bien utiliser notre sous-branche, créée sous la branche enterprise (au singulier) de l'IANA. Pourquoi ? Parce que nous pourrons être amenés un jour à créer des agents SNMP (comme cela a été illustré dans GLMF n°43). Nous allons donc créer deux branches à notre arbre : SNMP (branche 1, normal, car ce protocole est plus ancien) et LDAP (branche 2). Puis la branche LDAP sera elle-même découpée en deux autres branches : les classes d'objets (branche 1) et les attributs (branche 2). Cela nous donne la configuration suivante pour OpenLDAP :
objectIdentifier jroot 1.3.6.1.4.1.99999 # pas de :1 car c'est pour SNMP objectIdentifier j jroot:2 objectIdentifier jObjectClass j:1 objectIdentifier jAttributeType j:2
Notez la notation abrégée que nous permet OpenLDAP par le biais du mot-clé « objectIdentifier ». Nous allons la réutiliser un peu plus loin.
Nous allons créer un petit schéma auxiliaire de Person
, dans lequel nous
allons vouloir stocker les données suivantes : un trigramme (une contraction
en trois lettres du prénom et du nom de la personne), la liste de ses amis (sous
forme de liens dans l'annuaire, et donc de DN
), un booléen pour savoir si la
personne est droitière ou non, la photo de son chien (si elle en a un, syntaxe
JPEG
), et enfin un attribut avec son nom en chinois, puisque, c'est bien
connu, nos personnes le parlent couramment. Ce dernier attribut est
d'importance, car il va nous commander de choisir un encodage UTF-8, i.e.
applicable à autre chose qu'un alphabet latin, en deux mots :
Directory String
.
Pendant que nous y sommes, donnons-nous aussi un raccourci pour écrire les syntaxes, ce qui nous donne :
objectIdentifier ldapAttributeTypes 1.3.6.1.4.1.1466.115.121.1 attributetype ( jAttributeType:1 NAME 'jTrigramme' DESC 'Trigramme de la personne' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX ldapAttributeTypes:26{3} SINGLE-VALUE )
Le trigramme est en IA5 String
(:26
, soit US-ASCII pour les intimes) car
nous n'admettrons pas d'accent. De plus, le trigramme est une conception
essentiellement anglo-saxonne, donc applicable uniquement aux noms écrits ou
transcrits en caractères latins, quelle que soit leur origine. On demande aussi
à OpenLDAP de garder à l'esprit quelque part qu'il ne fait que trois caractères.
attributetype ( jAttributeType:2 NAME 'jAmis' DESC 'Amis de la personne' EQUALITY distinguishedNameMatch SYNTAX ldapAttributeTypes:12 )
Ici, la syntaxe est donc DN
(:12
), car nous y mettrons les DN des autres
personnes présentes dans l'annuaire amies d'une personne considérée.
attributetype ( jAttributeType:3 NAME 'jPhotoDuChien' DESC 'Photo du chien de la personne' SYNTAX ldapAttributeTypes:28 ) attributetype ( jAttributeType:4 NAME 'jDroitier' DESC 'La personne est droitière ?' SYNTAX ldapAttributeTypes:7 SINGLE-VALUE)
Rien de particulier, sinon les syntaxes JPEG
(:28
) et Boolean
(:7
).
Notez quand même que la latéralisation est précisée comme SINGLE-VALUE
(une
seule valeur stockable dans l'annuaire à un instant donné), mais que l'on
s'autorise plusieurs chiens (champ multi-valué), chiens que nous aurions pu
compter, d'ailleurs.
Enfin, voici le nom en chinois :
attributetype ( jAttributeType:5 NAME 'jNomEnChinois' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch DESC 'Le nom en chinois de la personne' SYNTAX ldapAttributeTypes:15 SINGLE-VALUE)
Je ne sais pas s'il existe une notion de majuscule et minuscule en chinois, mais nous sommes néanmoins parés à la présence de caractères le permettant, tant dans les recherches d'égalité pure que dans les recherches partielles.
Maintenant que nous avons les attributs, il nous faut les réunir dans une classe d'objets :
objectclass ( jObjectClass:1 NAME 'jPersonne' SUP 'top' AUXILIARY DESC 'Quelques données sur les personnes de mon annuaire' MUST ( cn $ uid $ jTrigramme $ jDroitier) MAY ( jAmis $ jPhotoDuChien $ jNomEnChinois ) )
Cette classe va obliger un objet qui en fait partie à avoir au moins les
attributs jTrigramme
et jDroitier
, de même que cn
et uid
. Les autres
sont optionnels et pourront ne pas être renseignés.
Mettez toutes ces définitions dans un fichier, que nous pourrons appeler
jPersonne.schema, et incluez-le dans slapd.conf via l'instruction include
.
Redémarrez OpenLDAP, et vous pouvez maintenant commencer à peupler votre
annuaire avec ldapadd
et ce qui suit :
dn: uid=toto,ou=Paris,ou=People, dc=example,dc=com objectClass: top objectClass: Person objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount userPassword: $BAbgoFfMV4LM uid: toto uidNumber: 1100 cn: toto loginShell: /bin/bash gidNumber: 513 gecos: Charlie toto description: System User homeDirectory: /home/toto sn: toto jTrigramme: TOT jDroitier: TRUE jPhotoDuChien::< file:///chemin/vers/medor.jpeg
Ne sachant (ni ne pouvant pour des raisons techniques) écrire en caractères chinois dans ces colonnes, je vous passerai la transcription de Toto dans cette écriture.
Pensez bien à votre schéma avant de l'intégrer à votre annuaire. En effet, il vous sera difficile de renommer ou de déplacer (via un changement d'OID) un attribut. Donc lors de la conception, prévoyez bien vos attributs, et si nécessaire, ne réutilisez pas les OID s'il y a déjà eu des insertions sur les attributs que vous aimeriez détruire.
Encore une fois, ce travail de conception demande de la planification. Mais une fois ce travail fait, la transcription est relativement rapide. Il faut simplement faire attention aux règles de mise en correspondance (matching).
Enfin, n'oubliez pas que d'autres annuaires ne permettent pas les raccourcis syntaxiques que nous avons pris avec OpenLDAP. Il vous faudra donc dans ce cas procéder comme indiqué dans les RFC ou comme dans les schémas fournis avec votre OpenLDAP, voire en format LDIF. Reportez-vous à votre documentation pour plus de détails. Un peu de Googlage peut aussi vous permettre de trouver des exemples.
Puisque nous allons un peu plus loin mettre en œuvre deux serveurs LDAP répliqués, nous allons devoir générer des certificats de serveur SSL/TLS certifiés par une autorité. Si vous avez déjà une autorité de certification, pas de souci, utilisez-la. Si vous avez lu le MISC de mai 2004, mettez en œuvre la PKI de votre choix. Dans le cas contraire, voici la marche à suivre pour générer l'autorité de certification (CA pour « certification authority » en anglais), puis les certificats des serveurs LDAP signés par cette autorité.
Le plus simple pour éviter un maximum de saisie est d'avoir son propre fichier de configuration pour OpenSSL.
Pour des raisons de concision, voici uniquement les lignes que j'ai modifiées par rapport au fichier openssl.cnf fourni en standard dans la distribution :
HOME = /home/jfenal # pour le fichier ~/.rnd dir = /home/jfenal/CA/demoCA # Where everything is kept countryName_default = FR stateOrProvinceName_default = Ile de France localityName_default = Paris 0.organizationName_default = Jerome Fenal en personne emailAddress_default = jerome.fenal@example.com
Ce fichier est stocké sur mon compte, dans le répertoire ~/CA.
On définit ensuite la variable d'environnement OPENSSL_CONF
pour la faire
pointer sur ce fichier :
export OPENSSL_CONF=~/CA/jfenal.cnf
Il nous reste maintenant à créer la CA, à créer ensuite un certificat, et à signer ce certificat avec le certificat de l'autorité pour avoir le certificat définitif et valide.
Nous allons utiliser le script Perl founi avec OpenSSL pour toutes les opérations. De votre côté, n'hésitez pas à reprendre ce script pour, par exemple, augmenter la durée de validité (365 jours par défaut) des certificats générés.
$ /usr/lib/ssl/misc/CA.pl -newca CA certificate filename (or enter to create) ¶
Appuyez sur entrée de façon à prendre le nom par défaut pour nous éviter de vous perdre, puis répondez ensuite aux questions qui vous sont posées, en évitant les accents :
Making CA certificate ... Generating a 1024 bit RSA private key ..++++++ ....................................++++++ writing new private key to './demoCA/private/cakey.pem' Enter PEM pass phrase:**********************************¶ Verifying - Enter PEM pass phrase:**********************************¶ ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [FR]:¶ State or Province Name (full name) [Ile de France]:¶ Locality Name (eg, city) [Paris]:¶ Organization Name (eg, company) [Jerome Fenal en personne]:¶ Organizational Unit Name (eg, section) []:Autorite de certification primaire¶ Common Name (eg, YOUR name) []:Autorite de certification primaire¶ Email Address [jerome.fenal@example.com]:¶
(Les « ¶ » indiquent les retours-chariot lors de la saisie.)
Notre autorité de certification est prête. Le certificat racine de l'autorité est dans ~/CA/demoCA/cacert.pem. La clé privée du certificat racine est dans ~/CA/demoCA/private/cakey.pem. Nous créons ensuite le certificat pour notre serveur LDAP : cela passe par la création de la requête, du certificat, puis la signature du certificat par la CA.
L'utilisation du script CA.pl impliquerait la création d'un certificat avec une phrase de passe. Or nous voulons pouvoir redémarrer le service LDAP sans devoir taper cette phrase de passe au démarrage. Nous allons devoir réaliser les opérations à la main.
Il nous faut d'abord générer un couple clé privée/clé publique pour le certificat :
$ openssl genrsa -out ldap1.example.com.key 1024 Generating RSA private key, 1024 bit long modulus ...........++++++ ..............................++++++ e is 65537 (0x10001)
Création de la demande de certificat :
$ openssl req -new -key ldap1.example.com.key -out ldap1.example.com.req You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [FR]:¶ State or Province Name (full name) [Ile de France]:¶ Locality Name (eg, city) [Paris]:¶ Organization Name (eg, company) [Jerome Fenal en personne]:¶ Organizational Unit Name (eg, section) []:¶ Common Name (eg, YOUR name) []:ldap1.example.com¶ Email Address [jerome.fenal@example.com]:¶ Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:¶ An optional company name []:¶
La demande est donc maintenant dans ldap1.example.com.req. Pour information, c'est ce que vous envoyez à une autorité de certification qui vous le signera en retour. Reste donc à certifier cette demande pour en faire un certificat valide.
$ openssl ca -in ldap1.example.com.req -extensions v3_ca -out ldap1.example.com.pem -days 3000 Using configuration from /home/jfenal/MyCA/myca.cnf Enter pass phrase for /home/jfenal/MyCA/demoCA/private/cakey.pem: Check that the request matches the signature Signature ok Certificate Details: Serial Number: 1 (0x1) Validity Not Before: May 29 20:39:49 2004 GMT Not After : Aug 15 20:39:49 2012 GMT Subject: countryName = FR stateOrProvinceName = Ile de France organizationName = Jerome Fenal en personne commonName = ldap1.example.com emailAddress = jerome.fenal@example.com X509v3 extensions: X509v3 Subject Key Identifier: BD:3F:C0:4C:75:14:D5:00:E6:B3:E6:1D:71:45:19:4D:61:D4:2D:C3 X509v3 Authority Key Identifier: keyid:AC:2F:66:7A:8A:D0:69:F9:2E:48:DC:3A:E8:6C:AC:E7:B0:1C:61:08 DirName:/C=FR/ST=Ile de France/L=Paris/O=Jerome Fenal en \ personne/OU=Autorite de certification primaire/CN=Autorite \ de certification primaire/emailAddress=jerome.fenal@example.com serial:00 X509v3 Basic Constraints: CA:TRUE Certificate is to be certified until Aug 15 20:39:49 2012 GMT (3000 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
Remarquez que nous voulons éviter de devoir changer tous les ans le certificat, la période de validité de la certification est donc étendue à 3000 jours, soit plus de 8 ans... de quoi voir venir.
Nous avons donc notre certificat pour notre serveur LDAP (qui doit donc
s'appeler ldap1.example.com
).
Copiez le certificat de notre autorité de certification (~/MyCA/demoCA/cacert.pem) dans le répertoire /etc/ssl/.
Copiez aussi les deux fichiers ldap1.example.com.pem et ldap1.example.com.key dans /etc/ssl/openldap ou où bon vous semble, pourvu que vous vous y retrouviez.
Modifiez le fichier slapd.conf afin d'avoir les lignes suivantes :
TLSCertificateFile /etc/ssl/openldap/ldap1.example.com.pem TLSCertificateKeyFile /etc/ssl/openldap/ldap1.example.com.key TLSCACertificateFile /etc/ssl/MyCAcert.pem
Redémarrez ensuite le service ldap :
# service ldap restart
ou
# /etc/init.d/ldap restart
Le script devrait vous répondre OK ou ne pas vous sortir d'erreur.
Pour vérifier que l'on peut bien joindre l'annuaire via le protocole LDAP sur SSL, essayez de lancer une requête :
$ ldapsearch -b dc=example,dc=com -s sub -x -w secret -D cn=Manager,dc=example,dc=com -H ldaps://localhost/
Si aucune réponse ne vient, ou si une erreur survient, vérifiez bien que
OpenLDAP écoute bien en TLS, et que ldaps:///
est bien spécifié sur la ligne
de commande de slapd
. Par exemple, l'erreur suivante :
ldap_bind: Can't contact LDAP server (81) additional info: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
signifie que le serveur a bien été contacté, mais que son certificat n'a pu être validé au regard du certificat racine de l'autorité dont il dépend. Il nous faut donc configurer le client LDAP (via la bibliothèque), et pour ce faire, créer un fichier de configuration pour le compte d'où le client est lancé (~/.ldaprc ou ~/ldaprc). Le fichier doit contenir :
BASE dc=example, dc=com URI ldaps://ldap1.example.com/ TLS_CACERT /etc/ssl/MyCAcert.pem TLS_REQCERT demand
Cela nous permet d'indiquer la base de recherche par défaut, la connexion au
serveur par défaut, ainsi que le protocole (LDAP ou LDAP/SSL), et pour la partie
SSL/TLS, le certificat de l'autorité de certification dont dépend le serveur (si
nous sommes sur la même machine, autant spécifier le même fichier), et le type
de comportement face au certificat SSL (on le vérifie absolument, ou pas). Pour
plus d'informations, référez-vous à la page de manuel ldap.conf(5)
.
slurpd
Pour monter un serveur LDAP répliqué, commencez d'abord par monter un second serveur LDAP similaire au premier.
La configuration spécifique à la réplication est relativement simple : il faut spécifier au maître de faire rejouer les transactions sur le ou les esclaves, et il faut que le serveur esclave redirige les clients voulant faire des modifications vers le serveur maître, lui seul ayant la possibilité de recevoir des écritures.
Dans ce cas, un client sera bien déconnecté du serveur sur lequel il était pour aller interroger et renseigner le serveur maître. Ce n'est en fait pas le client qui le fait, mais la bibliothèque LDAP qui s'en charge pour lui.
Je partirai du principe que le serveur maître est ldap1.example.com, le serveur esclave ldap2.example.com. N'oubliez pas de générer un certificat avec le bon nom de serveur (Common Name dans la description du certificat), dérivant de la même autorité de certification (pour simplifier les choses).
La réplication n'est pas très difficile, voire plutôt très simple à mettre en
œuvre, pourvu que l'on ait la bonne information au départ. Alors je l'écris en
gras : une configuration de réplication s'applique à une base de
données LDAP et non à un annuaire. Ça va mieux en le disant, d'autant que je n'ai trouvé cette
information qu'après une lecture assidue des lidies (listes de distribution) sur
gmane.org
(pub !). En effet, un annuaire OpenLDAP peut gérer plusieurs bases,
avec plusieurs suffixes différents. Or il est tout à fait possible de vouloir
répliquer une base et pas une autre. Ce point de détail bloquant m'a valu une
certaine perte de temps avant de comprendre que je ne pouvais pas mettre la
configuration de réplication où je voulais dans /etc/openldap/slapd.conf.
C'est pourtant explicitement dit dans la page de manuel de slapd.conf(5)
:
Specify a replication site for this database, mais que voulez-vous... Une
directive de réplication se met donc dans la section de description database
afférente.
Le serveur qui doit répliquer sa base de données sur un autre serveur met à disposition les modifications de ces données dans un fichier, sous une forme proche de LDIF. C'est le journal des modifications.
Ce fichier est lu ensuite par un processus frère, slurpd
, qui est démarré en
même temps que slapd
quand on veut faire de la réplication. Son boulot est de
vérifier le journal que lui passe slapd
, et de faire passer les modifications
sur les tous les serveurs configurés. Les modifications sont communiquées par
slurpd
aux autres slapd
par le protocole que vous utilisez, LDAP.
Il va sans dire qu'il faudra donc spécifier l'utilisateur qu'utilisera
slurpd
pour se connecter sur les esclaves. Cet utilisateur, que nous
nommerons le réplicateur et qu'il nous faudra définir d'abord dans l'annuaire maître,
sera le seul avoir le droit en écriture sur les serveurs esclaves.
Pour éviter les modifications par tout autre que le réplicateur sur les serveurs esclaves, nous allons utiliser une particularité de LDAPv3 : l'utilisation des renvois (Referrals). Ces renvois, notifiés de façon transparente au client, feront que ce client LDAP se connectera de manière tout aussi transparente au serveur spécifié dans le renvoi afin de mener à bien les modifications demandées. Tous les clients actuels (basés sur les bibliothèques clientes OpenLDAP) supportent ainsi LDAPv3, et donc les renvois.
On modifie la configuration des serveurs maître et esclave de la façon suivante :
On ajoute à la suite de la définition de la base de données (database
) les
lignes :
replica host=ldap2.example.com:389 tls=yes bindmethod=simple binddn="cn=Replicator,dc=example,dc=com" credentials=ksdhjdlk
On a donc défini un serveur ldap2, accessible via TLS, s'authentifiant via un
mot de passe (et non via SASL) avec le compte cn=Replicator,dc=example,dc=com
et le mot de passe : ksdhjdlk
.
N'oubliez pas d'insérer la définition LDIF du compte réplicateur dans l'annuaire :
dn: cn=Replicator, dc=example,dc=com userPassword: {MD5}wTLNbidzOxJH8bbfhDL83A== objectClass: person objectClass: top sn: Replicator cn: Replicator
On notera que le réplicateur est défini à la racine du DIT (« Directory Information Tree », arbre contenant les données de l'annuaire). Cela évitera par la suite de le confondre avec un compte utilisateur.
Ce compte sera donc défini tant dans l'annuaire maître que dans l'annuaire esclave, car les deux sont identiques. On peut cependant imaginer avoir une base de données spécifique au serveur esclave, avec un autre suffixe. Mais pour un simple compte de réplication, cela en vaut-il la peine ?
De même que pour la base de données à répliquer de l'annuaire maître, on ajoute les lignes suivantes à la suite de la définition de la base de données répliquée sur le serveur esclave :
updateref ldap://ldap1.example.com:389/ updatedn "cn=Replicator,dc=example,dc=com"
La première ligne permet le renvoi vers l'annuaire maître pour les écritures, et
spécifie le DN
du réplicateur. Ajoutez et/ou modifiez les ACL par ce qui
suit, pour autoriser le réplicateur à écrire dans l'annuaire répliqué :
access to attr=userPassword by self write by anonymous auth by dn="cn=Replicator,dc=example,dc=com" write by * none access to * by dn="uid=Replicator,dc=example,dc=com" write by * read
Encore une fois, les lignes updateref
et updatedn
sont spécifiques à une
database
(me répété-je ?).
Pour la synchronisation, il vaut mieux placer l'annuaire en lecture seule le
temps de récupérer son contenu, même si dans les versions récentes, avec
Berkeley DB, il est possible de lancer la commande slapcat
en étant assuré
d'avoir un vidage cohérent du contenu de l'annuaire.
De plus, le fait de placer l'annuaire maître en lecture seule le temps de la réplication permet de s'assurer de l'absence de modification sur le maître pendant que le contenu est transféré du maître à l'esclave. Le retour en mode normal, autorisant des modifications sur l'annuaire maître, ne doit se faire qu'après le redémarrage de l'esclave, qui contiendra à ce moment-là exactement les données du maître.
Pour ce faire, nous allons rajouter une clause include
au fichier de
configuration de l'annuaire maître pour la base de données à répliquer. Cette
clause pointera sur un fichier, situé à côté de slapd.conf, dans lequel nous
pourrons spécifier readonly on
ou readonly off
. Cela nous permettra de
passer la base dans un mode ou l'autre beaucoup plus facilement (et rapidement)
qu'avec un appel à perl (du style
perl -pi -e 's/readonly on/readonly off/g' /etc/openldap/slapd.conf
),
qui devra même être plus compliqué que ça dans le cas d'un annuaire avec
plusieurs bases.
La ligne à ajouter dans slapd.conf, après la définition de la base
dc=example,dc=com
:
include /etc/openldap/readonly-example.com.conf
Le script pour lancer la réplication sera donc :
#!/bin/bash # Réplication d'annuaire OpenLDAP par dump ou par copie des bases # BACKUPDIR=/var/lib/ldap/backup BASE=example.com BASESUFFIX="dc=example,dc=com" REPL=base #REPL=dump # mkdir -p $BACKUPDIR chown root:root $BACKUPDIR chmod 700 $BACKUPDIR # echo "readonly on" > /etc/openldap/readonly-${BASE}.conf service ldap restart # slapcat -b "$BASESUFFIX" > $BACKUPDIR/slapcat.dump rc=$? if [ $rc -ne 0 ] ; then echo "Le dump de la base $BASESUFFIX a échoué" echo "Réplication impossible" exit 1 fi # # Arret LDAP distant ssh ldap2.example.com "/etc/init.d/ldap stop" if [ "$REPL" == "base" ] ; then scp $BACKUPDIR/slapcat.dump ldap2.example.com:$BACKUPDIR/slapcat.dump scp /var/lib/ldap/*.dbb ldap2.example.com:/var/lib/ldap ssh ldap2.example.com "chown ldap:ldap /var/lib/ldap/*.dbb" else cmd="/etc/init.d/ldap stop" cmd="$cmd ; rm -f /var/lib/ldap/*" cmd="$cmd ; su - ldap -c slapadd -c -l $BACKUPDIR/slapcat.dump" ssh ldap2.example.com "$cmd" fi ssh ldap2.example.com "/etc/init.d/ldap start" echo "readonly off" > /etc/openldap/readonly-${BASE}.conf service ldap restart
Ce script suppose que vous ayez soit une clé pour le compte root
de ldap1
autorisée sur ldap2
, soit que vous ayez « l'agent forwarding » pour votre clé
personnelle activé (et votre clé autorisée sur le compte root de vos deux
serveurs), soit que vous soyez prêt à taper un certain nombre de fois le mot de
passe root
de ldap2
.
Ce script ne teste pas tous les cas de figures où peuvent survenir des problèmes, en particulier en cas d'erreur au cours du transfert des données. À ce titre, ne le lancez que manuellement et surveillez son déroulement. Sinon, modifiez-le afin de vérifier tous les codes retour de toutes les commandes et n'avancez dans le déroulement du script que si tout se passe bien. N'oubliez pas d'envoyer des avertissements pour vérifier à votre arrivée le matin le bon déroulement des transferts de nuit en automatique.
Définition des syntaxes d'attributs LDAP. http://www.ietf.org/rfc/rfc2252.txt
L'annuaire libre. http://www.openldap.org/
... nous verrons comment authentifier un serveur Linux sur un annuaire LDAP, ce grâce aux PAM (sans jeu de mot, S.V.P.).
Je vous donne ici le nom de la liste, ainsi que sa localisation dans l'excellent
moteur d'archivage et de présentation en NNTP de lidies, j'ai nommé
Gmane.org
, ainsi que le site Web du gestionnaire de liste.
La liste en français sur LDAP.
Les listes OpenLDAP.
<jfenal@free.fr> et <jerome.fenal@logicacmg.com>.
Jérôme Fenal est utilisateur de GNU/Linux depuis 1994, de divers Unix (Ultrix) ou Unix-like depuis un peu plus longtemps, membre de Paris.pm.
Merci aux Mongueurs Marseillais, Lyonnais, Parisiens et Grenoblois qui ont assuré la relecture avisée de cet article.
Cet article a été écrit sous Linux, avec [g]vim, en pod (Plain Old Documentation).
Copyright © Les Mongueurs de Perl, 2001-2011
pour le site.
Les auteurs conservent le copyright de leurs articles.