OpenLDAP

Quand on commence à avoir un certain nombre d’applications et donc, un certain nombre de bases utilisateur, cela devient vite compliqué à la fois pour l’administration, mais également pour les utilisateurs (plusieurs logins, mots de passe, etc..).
Il est donc temps de se poser la question de la centralisation de ses utilisateurs dans un seul référentiel. On pourrait très bien se service d’une base SQL, mais il existe un autre type de service bien plus adapté à ce genre d’usage : OpenLDAP, un annuaire  LDAP (Lightweight Directory Access Protocol), dérivé des vénérables annuaires X500.

 

Table des matières

OpenLDAP

I – Présentation

Installation et configuration

I – Installation

II – Quelques explications

A – Les Schémas

B – Les commandes

C – BaseDn, Filtres, Attributs

III – Configuration

A – Compte admin

1 – Mdp Admin dans un fichier

2 – Droits d’accès à la configuration du serveur

B – Logs à l’aide de Rsyslog

1 – Slapd

2 – Rsyslog

Les Overlays

I – Quid ?

II – MemberOf

III – Intégrité Référentielle

IV – Overlay Audit Log

V – Overlay Unique

VI – Overlay Ppolicy

Peuplement

I – Les OUs

II – Les utilisateurs

III – Les groupes

IV – Comptes Système et ACL

Modification des données

I – Préparatif rapide

II – OU

A – Ajout d’une OU

B – Modification d’une OU

C – Déplacement d’une OU

D – Suppression d’une OU

III – Modification d’entrées

A – Ajout

1 – Ajout d’un utilisateur

2 – Ajout d’un groupe

B – Déplacement

1 – Déplacement d’un utilisateur

2 – Déplacement d’un groupe

C – Renommage

1 – Renommage d’un utilisateur

2 – Renommage d’un groupe

D – Suppression

1 – Suppression d’un utilisateur

2 – Suppression d’un groupe

IV – Modification d’attributs

A – Ajout

1 – Utilisateur

2 – Groupe

B – Modification

1 – Utilisateur

2 – Groupe

C – Suppression

1 – Utilisateur

2 – Groupe

V – Conclusion

Sauvegarde et restauration

I – Sauvegarde

A – Configuration

B – Données

II – Restauration

A – Configuration

B – Données

Réplication

I – Prérequis

II – Configuration

A – Activation Overlay

B – ServerID

C – Création utilisateur réplication

III – Réplication de la configuration

A – ACL

B – Configuration

C – Paramétrage

IV – Réplication des données

A – ACL et limitation

B – Index

C – Configuration

D – Paramétrage

V – Dernier réglage

Keepalived

I – Maintenez les en vie !

A – Présentation

B- Installation

II – Configuration simple : une IP virtuelle

III – Et avec du loadbalancing ?

 

I – Présentation

L’idée est de faire en sorte qu’un utilisateur puisse se connecter avec un login/mdp et qu’en fonction d’appartenance à des groupes, de présence d’attributs, etc.. il ait l’accès ou non aux applications, services, etc…
Je parlais un peu avant de la possibilité de faire cela avec un serveur SQL. Cependant, effectuer l’authentification en passant par le LDAP offre un avantage non négligeable : la rapidité. En effet, la particularité d’un ldap par rapport à un SGBD est l’optimisation pour la lecture. Une requête sera traité bien plus rapidement par LDAP que par MYSQL.
Dans un environnement avec de nombreuses authentifications concomitantes la différence peut se faire sentir en terme de charge. Et pour terminer avec les avantages du LDAP pour l’authentification, c’est que cela s’intégrera parfaitement dans un futur contexte AAA (Authentication, Authorization, Accounting).
Je ne vais pas faire un cours magistral sur le protocole LDAP (on trouve de nombreuses doc sur la toile), retenez simplement que c’est donc très pratique mais pas forcement simple à prendre en main.
Ce qu’il faut savoir :
Les informations sont stockées dans une structure en arborescence (différent en ce point par exemple d’un SGBD qui stocke les informations de manière relationnelle.
Avec OpenLDAP vous avez la liberté de définir complètement l’arborescence vous-même. On l’appelle « Directory Information Tree » (DIT).

Dans la grande majorité des articles sur OpenLDAP, on trouve la classique arborescence avec les OU People et Group.

Dans notre exemple, nous allons faire un peu plus complexe en prévision du futur.Nous allons commencer par un nœud racine dc=debugo,dc=fr contenant trois nœuds sous la racine:

ou=group,dc=debugo,dc=fr : elle contiendra elle même deux OU :

ou=people,dc=debugo,dc=fr : deux sous OU la aussi :

ou=system,dc=debugo,dc=fr : OU qui contiendra les comptes systèmes permettant de lire les mots de passe des utilisateurs ldap.

Une chose à savoir, à partir de la version 2.3, la façon de configurer OpenLDAP a changé : on passe d’une configuration dans un fichier (slapd.conf) à une configuration elle même dans une base LDAP (dans l’arbre cn=config).L’avantage est conséquent : il est possible de modifier la configuration sans arrêter et redémarrer le service (ce qui dans le cas d’un gros annuaire peut être très long).

Pour se faire, nous mettrons nos différents paramétrages dans des fichiers ldif, que nous injecterons dans le serveur, sans le couper, et ce, dans le but de modifier sa configuration à chaud.

Bref, voila pour la présentation de cette série de tutoriels.

Installation et configuration

I – Installation

Classique, une mise à jour et on installe le paquet slapd et le paquet ldap-utils contenant les outils pour modifier le ldap

# apt-get update && apt-get upgrade

# apt-get install slapd ldap-utils

Cependant, la configuration par défaut du paquet n’est peut être pas celle que vous voulez (elle se base sur le FQDN de la machine), bref, pour être sur :

# dpkg-reconfigure slapd

La, vous répondez comme cela :

Omit OpenLDAP server configuration? No

DNS domain name: debugo.fr

Organization name? Debugo

Administrator password: PASSWORD

Confirm password: PASSWORD

Database backend to use: MDB

Do you want the database to be removed when slapd is purged? YES

Allow LDAPv2 protocol? No

Ensuite, un petit tour dans le fichier /etc/ldap/ldap.conf pour le configurer comme il faut (utilisé par les outils ldap pour modifier le LDAP en ligne de commande) :

BASE dc=debugo,dc=fr

URI ldap://IP.MACHINE/

On test avec :

# ldapsearch -xLLL

ou bien

# ldapsearch -Y external  -H ldapi:/// -b dc=debugo,dc=fr -LLL

Ce qui doit retourner quelque chose comme :

dn: dc=debugo,dc=fr

objectClass: top

objectClass: dcObject

objectClass: organization

o: debugo

dc: debugo

dn: cn=admin,dc=debugo,dc=fr

objectClass: simpleSecurityObject

objectClass: organizationalRole

cn: admin

description: LDAP administrator

Youpi ! On peut continuer.
Pour avoir d’autres informations sur le serveur, vous pouvez utiliser les commandes suivantes :

# slapd -V

# ldapsearch -Y external  -H ldapi:/// -b cn=config "(objectClass=olcGlobal)" -LLL

-LLL : Permet de ne pas afficher certains informations superflues dans la sortie (testez avec et sans pour voir la différence …)

Comme je l’expliquais dans l’introduction de cette série de tutoriels, la configuration n’est plus dans un fichier unique, mais sous forme de DIT (cn=config). On peut en avoir un aperçu avec la commande

# tree /etc/ldap/slapd.d/

/etc/ldap/slapd.d/

|-- cn=config

|   |-- cn=module{0}.ldif

|   |-- cn=schema

|   |   |-- cn={0}core.ldif

|   |   |-- cn={1}cosine.ldif

|   |   |-- cn={2}nis.ldif

|   |   `-- cn={3}inetorgperson.ldif

|   |-- cn=schema.ldif

|   |-- olcBackend={0}mdb.ldif

|   |-- olcDatabase={-1}frontend.ldif

|   |-- olcDatabase={0}config.ldif

|   `-- olcDatabase={1}mdb.ldif

`-- cn=config.ldif

Si la commande tree n’existe pas :

# apt-get install tree

A vrai dire, on peut encore configurer en passant par le fichier slapd.conf mais cela requiert un redémarrage du serveur à chaque modification. De plus, cette méthode n’est pas recommandée.

 

II – Quelques explications

A – Les Schémas

Si vous regardez le résultat de la commande :

# tree /etc/ldap/slapd.d/

Vous voyez plusieurs entrées sous la branche cn=schema. En l’occurrence, core, cosine, nis et inetorgperson.

Ce sont en quelque sorte les modèles qu’utiliseront vos futurs enregistrement (quel attribut, de quel type, etc..). Ceux déjà intégrés sont les plus couramment utilisés, mais il en existe d’autres, soit déjà disponibles dans /etc/ldap/schema :

# ls /etc/ldap/schema/*.ldif

Soit disponibles sur Internet.

Il est aussi tout à fait possible de créer vos propres schémas, afin que votre annuaire réponde précisément à vos besoins.

B – Les commandes

Pour modifier la configuration du serveur nous utiliserons principalement les commandes ldapadd, ldapmodify, ldapdelete (installées avec le paquet ldap-utils) Ces dernières prennent en option un fichier (option -f) de format ldif (Ldap Data Interchange Format).

Nous allons rapidement voir de quoi il s’agit.

Pour effectuer des requêtes, nous utiliserons la commande ldapsearch.

Celle ci peut interroger le serveur LDAP de plusieurs façons.

Sur le socket interne :

# ldapsearch -Q -Y external -H ldapi:/// -b cn=config

L’option -Q cache les infos SASL, inutile à l’affichage.

Ou sur un socket réseau :

# ldapsearch -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -W -b cn=config

Sur le socket réseau, nous indiquons les options :

-x : authentification simple.

-H indique l’hôte (en l’occurrence, localhost).

-D est le compte qui va se connecter.

-W sert à demander le mot de passe.

-b ou basedn est l’endroit ou nous voulons faire notre recherche.

La commande fonctionne mais ne retourne rien. Le compte admin n’a pas accès à la configuration en passant par le socket réseau (nous allons y remédier après).

Au passage, pourquoi donc s’embêter alors qu’on ne pourrait qu’utiliser le socket interne ?

L’intérêt du socket réseau est qu’on peut lancer les commandes à distance (dans ce cas remplacer localhost par le nom de la machine distante).

C – BaseDn, Filtres, Attributs

Je reviens sur la commande :

# ldapsearch -Q -LLL -Y external -H ldapi:/// -b cn=config

Celle ci affiche donc l’intégralité de l’arbre cn=config (le baseDN de notre requête).

Au passage, on peut l’écrire sous la forme :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config"

Si l’on veut n’afficher que les attributs dn des résultats, on fera alors :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" dn

Si par exemple, je veux afficher d’autres attributs :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "(objectClass=olcModuleList)" dn olcModuleLoad

Dans la commande précédente, j’utilise un filtre. Pour les utiliser, il suffit de les indiquer après l’option -b et avant ce que l’on demande par ex :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "(&(objectClass=olcDatabaseConfig))" dn

Cette commande n’affichera que les attributs dn des objectClass olcDatabaseConfig. Le & est facultatif. J’aurais très bien pu mettre :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "(objectClass=olcDatabaseConfig)" dn

Si l’on ne veut pas que les attributs dn, mais toutes les infos :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "(&(objectClass=olcDatabaseConfig))"

Et si je voulais les attributs dn des objectClass étant des olcDatabaseConfig ou ceux étant des olcModuleList, je vais utiliser le | pour indiquer un OU (le ET étant spécifié par &)

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "(|(objectClass=olcDatabaseConfig)(objectClass=olcModuleList))" dn

Petite explication sur l’utilisation des filtres. Ceux ci utilisent un principe qui rappelle la notation polonaise inversée, l’opérateur étant ici devant.

Exemple :

Si je veux A et B :

( & (A) (B) )

Si je veux A ou B

( | (A) (B) )

Si je veux A et B ou A et C :

 (  |  ( & (A) (B) )  ( & (A) (C) )  )

ou, en simplifiant :

 ( & (A) ( | (B) (C) ))

On peut aussi inverser avec le !.

Si l’on veut par ex ce qui est A et ce qui n’est pas B :

( & (A) (!  B) )

 

Au niveau des filtres, nous pouvons utiliser les opérateurs suivants :

On peut utiliser un joker, par ex, = *toto* sortira tout ce qui contient toto comme sous chaîne.

Il existe également la notion de filtres étendus, utilisé ainsi : attribut:dn:=valeur.

Par ex :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -w password -b "dc=debugo,dc=fr" ou=people dn

me donne :

dn: ou=people,dc=debugo,dc=fr

Et :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -w password -b "dc=debugo,dc=fr" ou:dn:=people dn

me donne :

dn: ou=people,dc=debugo,dc=fr

dn: ou=client,ou=people,dc=debugo,dc=fr

dn: ou=debugo,ou=people,dc=debugo,dc=fr

dn: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr

dn: uid=ldap1,ou=debugo,ou=people,dc=debugo,dc=fr

dn: uid=ldap2,ou=debugo,ou=people,dc=debugo,dc=fr

Ils permettent donc de considérer les éléments du DN comme faisant partie de l’entrée elle même.

On peut également utiliser les filtres étendus pour modifier les opérateurs.

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -w password -b "dc=debugo,dc=fr" title:2.5.13.5:=Admin dn

ne me sortira que les entrées ou l’attribut title est égal à Admin (et non pas admin, ADMIN, etc…). Par défaut, l’opération n’est pas sensible à la casse.

Pour connaitre l’ensemble des matchingRules disponibles :

# ldapsearch -xLLL -D cn=admin,dc=debugo,dc=fr -w password -b "cn=subschema" -s base matchingRuleUse | grep "matchingRule" | cut -d ' ' -f3,5

III – Configuration

Nous allons créer un répertoire /root/ldap/conf qui va centraliser tous nos fichiers de configuration :

# cd

# mkdir ldap

# cd ldap

# mkdir conf

# cd conf

A – Compte admin

1 – Mdp Admin dans un fichier

Afin d’éviter d’avoir à toujours retaper le mot de passe admin (mot de passe que nous avons créé lors de la configuration du paquet) lors des commandes, nous allons l’enregistrer dans un fichier.

On va créer un fichier /root/pwdldap et mettre le mot de passe dedans :

# echo -n "mdpadmin" > /root/pwdldap

# chmod 600 /root/pwdldap

On test :

# ldapsearch -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b dc=debugo,dc=fr

2 – Droits d’accès à la configuration du serveur

Par défaut, l’accès à la configuration n’est pas possible en passant par le socket réseau avec le compte admin :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b cn=config

nous donne :

No such object (32)

Créez le fichier LDIF /root/ldap/conf/acces-conf-admin.ldif, et insérez :

dn: olcDatabase={0}config,cn=config

changeType: modify

add: olcAccess

olcAccess: to * by dn.exact=cn=admin,dc=debugo,dc=fr manage by * break

Injectez :

# ldapmodify -Y external -H ldapi:/// -f acces-conf-admin.ldif

Et restestez :

# ldapsearch -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b dc=debugo,dc=fr

B – Logs à l’aide de Rsyslog

Par défaut, OpenLdap ne cause pas beaucoup. On va changer cela.

1 – Slapd

On extrait la configuration actuelle dans un fichier :

# ldapsearch -Y external -H ldapi:/// -b cn=config "(objectClass=olcGlobal)" olcLogLevel -LLL > log.ldif

Avant de continuer, jetez un œil à ce fichier :

dn: cn=config

olcLogLevel: none

Explications :
La première ligne, DN est ce qu’on appelle le distinguished name, autrement dit, identifiant unique de l’entrée. La deuxième ligne contient l’attribut demandée lors de la requête (olcLogLevel), de valeur none. Vous comprendrez donc facilement que les logs sont, par défaut, désactivés.
On va modifier le fichier de la sorte :

dn: cn=config

changetype: modify

replace: olcLogLevel

olcLogLevel: 256

Pour information, les différents niveau de log sont :

-1   : enable all debugging

0    : no debugging

1    : trace function calls

2    : debug packet handling

4    : heavy trace debugging

8    : connection management

16   : print out packets sent and received

32   : search filter processing

64   : configuration file processing

128  : access control list processing

256  : stats log connections/operations/results

512  : stats log entries sent

1024 : print communication with shell backends

2048 : print entry parsing debugging

On injecte :

# ldapmodify -Y EXTERNAL -H ldapi:/// -f log.ldif

On regarde le résultat :

# ldapsearch -Y external -H ldapi:/// -b cn=config "(objectClass=olcGlobal)" olcLogLevel

2 – Rsyslog

Éditez le fichier /etc/rsyslog.conf et ajoutez à la fin :

LOCAL4.* -/var/log/slapd.log

Il faut redémarrer rsyslog :

service rsyslog restart

Lancez une requête et consulter le contenu du fichier /var/log/slapd.log:

ldapsearch -Y external -H ldapi:/// -b dc=debugo,dc=fr

tail /var/log/slapd.log

Normalement, on doit avoir un contenu assez significatif de ce qui a été exécuté par le serveur OpenLDAP.

Voila qui termine cette première partie de la série. Dans la suite, nous allons continuer la configuration de notre serveur en lui ajoutant des Overlays.

Les Overlays

I – Quid ?

Les overlays sont des fonctionnalités supplémentaires qui se rajoutent. Ils en existent un certain nombre. La liste est non exhaustive, je n’ai mis que les plus « importants ».

En gras, ceux dont nous nous servirons.

Plus d’informations sur ce site : https://www.openldap.org/doc/admin24/overlays.html.

Pour chaque overlay, la configuration se fait en plusieurs fichiers. Généralement, un pour l’activation (qui ne sera utilisé qu’une fois). L’autre pour la configuration (nous pourrons alors le modifier plus tard). Ce fichier pour la configuration porte sur la base par défaut {1}mdb (qui contient notre arbre dc=debugo,dc=fr. Par la suite, avec d’autres arbres, nous pourrons alors configurer ces overlays sur ceux ci.

II – MemberOf

L’overlay memberof permet de savoir dans quels groupes se trouve un utilisateur en une seule requête au lieu de deux.
Exemple :

# ldapsearch -xLLL  "(uid=toto)" memberof

retournera la liste des groupes auquel l’utilisateur toto appartient.

Créez un fichier memberof_act.ldif et insérez le contenu suivant :

dn: cn=module,cn=config

cn:module

objectclass: olcModuleList

objectclass: top

olcmoduleload: memberof.la

olcmodulepath: /usr/lib/ldap

Créez un fichier memberof_conf.ldif et insérez le contenu suivant :

dn: olcOverlay=memberof,olcDatabase={1}mdb,cn=config

changetype: add

objectClass: olcMemberOf

objectClass: olcOverlayConfig

objectClass: olcConfig

objectClass: top

olcOverlay: memberof

olcMemberOfDangling: ignore

olcMemberOfRefInt: TRUE

olcMemberOfGroupOC: groupOfNames

olcMemberOfMemberAD: member

olcMemberOfMemberOfAD: memberOf

On injecte :

# ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_act.ldif

# ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_conf.ldif

Pour vérifier :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"

Ou bien encore :

# tree /etc/ldap/slapd.d/

On doit trouver trace dans la liste des modules.

On peut vérifier la configuration avec :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcmemberOf"

III – Intégrité Référentielle

Cet overlay permet de supprimer un utilisateur d’un groupe quand on supprime l’utilisateur. Au passage, si un groupe se retrouve vide, l’admin sera automatiquement ajouté (un groupe vide créé une erreur dans OpenLdap)

Créez un fichier refint_act.ldif et insérez le contenu suivant :

dn: cn=module,cn=config

cn: module

objectclass: olcModuleList

objectclass: top

olcmoduleload: refint.la

olcmodulepath: /usr/lib/ldap

Créez un fichier refint_conf.ldif et insérez le contenu suivant :

dn: olcOverlay=refint,olcDatabase={1}mdb,cn=config

objectClass: olcConfig

objectClass: olcOverlayConfig

objectClass: olcRefintConfig

objectClass: top

olcOverlay: refint

olcRefintAttribute: memberof member manager owner

olcRefintNothing: cn=admin,dc=debugo,dc=fr

On injecte :

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f refint_act.ldif

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f refint_conf.ldif

On vérifie :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"

On peut vérifier la configuration avec :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcRefintConfig"

IV – Overlay Audit Log

Cet overlay sert à auditer chaque modification au sein de l’annuaire. Dans notre cas, cela sera inscrit dans le fichier : /var/log/openldap/audit.ldif

Créez le fichier auditlog_act.ldif pour y insérer :

dn: cn=module,cn=config

cn: module

objectclass: olcModuleList

objectclass: top

olcModuleLoad: auditlog.la

olcmodulepath: /usr/lib/ldap

Créez le fichier auditlog_conf.ldif pour y insérer :

dn: olcOverlay=auditlog,olcDatabase={1}mdb,cn=config

objectClass: olcOverlayConfig

objectClass: olcAuditLogConfig

olcOverlay: auditlog

olcAuditlogFile: /var/log/openldap/auditlog.ldif

Injectez :

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f auditlog_act.ldif

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f auditlog_conf.ldif

On vérifie :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"

On peut vérifier la configuration avec :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcAuditLogConfig"

Ensuite, nous allons créer le fichier :

# mkdir /var/log/openldap

# chmod 755 /var/log/openldap

# chown openldap:openldap /var/log/openldap

# touch /var/log/openldap/auditlog.ldif

# chmod 755 /var/log/openldap/auditlog.ldif

# chown openldap:openldap /var/log/openldap/auditlog.ldif

V – Overlay Unique

Cet overlay permet de nous assurer l’unicité des attributs que l’on spécifie.

Créez un fichier unique_act.ldif pour y insérer :

dn: cn=module,cn=config

cn: module

objectclass: olcModuleList

objectclass: top

olcModuleLoad: unique.la

olcmodulepath: /usr/lib/ldap

Créez un fichier unique_conf.ldif pour y insérer :

dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config

objectClass: olcOverlayConfig

objectClass: olcUniqueConfig

olcOverlay: unique

olcUniqueUri: ldap:///ou=people,dc=debugo,dc=fr?uid?sub

olcUniqueUri: ldap:///ou=people,dc=debugo,dc=fr?mail?sub

olcUniqueUri: ldap:///ou=people,dc=debugo,dc=fr?uidNumber?sub

olcUniqueUri: ldap:///ou=groups,dc=debugo,dc=fr?cn?sub

Nous demandons ici à ce que les attributs ui, mail et uidNumber dans l’ou people soient uniques. Et que l’attribut cn dans l’ou groups soit lui aussi unique.

Injectez :

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f unique_act.ldif

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f unique_conf.ldif

On vérifie :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"

On peut vérifier la configuration avec :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcUniqueConfig"

VI – Overlay Ppolicy

Cet overlay va nous permettre de spécifier une politique de mot de passe.

Un peu particulier, il faut ajouter son schéma dans l’annuaire :

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/ppolicy.ldif

On peut voir que c’est bon avec :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=schema,cn=config" cn

Ou bien encore :

# tree /etc/ldap/slapd.d/

Dans la branche cn=schema, on doit voir le schéma ppolicy qui s’est ajouté à ceux présent par défaut (core, cosine, nis et inetorgperson).

Créez un fichier ppolicy_act.ldif pour y insérer :

dn: cn=module,cn=config

cn: module

objectclass: olcModuleList

objectclass: top

olcModuleLoad: ppolicy.la

olcmodulepath: /usr/lib/ldap

Créez un fichier ppolicy_conf.ldif pour y insérer :

dn: olcOverlay=ppolicy,olcDatabase={1}mdb,cn=config

objectClass: olcOverlayConfig

objectClass: olcPpolicyConfig

olcOverlay: ppolicy

olcPPolicyDefault: cn=ppolicy,dc=debugo,dc=fr

olcPPolicyHashCleartext: TRUE

olcPPolicyUseLockout: FALSE

olcPPolicyDefault : Indique le DN de configuration utilisé par défaut (nous le définirons apres).

olcPPolicyHashCleartext : Indique si les mots de passe doivent être cryptés.

olcPPolicyUseLockout : Si TRUE, le message d’erreur retourné en cas de connexion à un compte vérouillé indiquera qu’il s’agit d’un compte vérouillé. Si FALSE, ce sera un message d’échec stantard.

On injecte

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f ppolicy_act.ldif

# ldapadd -Q -Y EXTERNAL -H ldapi:/// -f ppolicy_conf.ldif

On vérifie :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcPpolicyConfig" -LLL

On va maintenant créer la politique par défaut.

Créez un fichier ppolicy_def.ldif pour y insérer :

dn: cn=ppolicy,dc=debugo,dc=fr

objectClass: top

objectClass: device

objectClass: pwdPolicy

cn: ppolicy

pwdAllowUserChange: TRUE

pwdAttribute: userPassword

pwdCheckQuality: 1

pwdExpireWarning: 0

pwdFailureCountInterval: 30

pwdGraceAuthNLimit: 5

pwdInHistory: 5

pwdLockout: TRUE

pwdLockoutDuration: 60

pwdMaxAge: 0

pwdMaxFailure: 5

pwdMinAge: 0

pwdMinLength: 5

pwdMustChange: FALSE

pwdSafeModify: FALSE

La signification des attributs est :

pwdAllowUserChange : indique si l’utilisateur peut changer son mot de passe.

pwdCheckQuality : indique si OpenLDAP renvoie une erreur si le mot de passe n’est pas conforme

pwdExpireWarning : avertissement d’expiration.

pwdFailureCountInterval : Intervalle de temps entre deux tentatives infructueuses pour qu’elles soient considérées comme « à la suite ».

pwdGraceAuthNLimit : période de grâce suite à l’expiration du mot de passe.

pwdInHistory : nombre de mots de passe dans l’historique.

pwdLockout : indique si on bloque le compte au bout de X échecs.

pwdLockoutDuration : durée du blocage du compte (en secondes).

pwdMaxAge : age maximal du mot de passe (en secondes).

pwdMaxFailure : nombre d’échecs de saisie du mot de passe maximal (avant blocage).

pwdMinAge : age minimal du mot de passe (en secondes).

pwdMinLength : longueur minimale du mot de passe.

pwdMustChange : indique si l’utilisateur doit changer son mot de passe.

pwdSafeModify : indique si il faut envoyer l’ancien mot de passe avec le nouveau pour modification.

On injecte :

# ldapadd -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f ppolicy-def.ldif

On vérifie :

# ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "dc=debugo,dc=fr" "Objectclass=pwdPolicy"

On peut avoir plusieurs politique (une adapté pour des comptes clients, par exemple).

Par ex, fichier ppolicy-client.ldif :

dn: cn=ppolicy-client,dc=debugo,dc=fr

objectClass: top

objectClass: device

objectClass: pwdPolicy

cn: ppolicy-client

pwdAllowUserChange: TRUE

pwdAttribute: userPassword

pwdCheckQuality: 1

pwdExpireWarning: 0

pwdFailureCountInterval: 30

pwdGraceAuthNLimit: 5

pwdInHistory: 10

pwdLockout: TRUE

pwdLockoutDuration: 60

pwdMaxAge: 0

pwdMaxFailure: 3

pwdMinAge: 0

pwdMinLength: 8

pwdMustChange: FALSE

pwdSafeModify: TRUE

Qu’on injecte :

# ldapadd -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f ppolicy-client.ldif

Et qu’on affectera avec un fichier changeppolicy.ldif :

dn: uid=toto,ou=client,ou=people,dc=debugo,dc=fr

changetype: modify

replace: pwdPolicySubEntry

pwdPolicySubEntry: cn=ppolicy-client,dc=debugo,dc=fr

Qu’on injectera avec :

# ldapadd -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f changeppolicy.ldif

On pourra aussi spécifier cet attribut à la création de l’utilisateur.

 

Voila pour la seconde partie.

Dans la suite, nous peuplerons notre annuaire.

Peuplement

I – Les OUs

Nous avions créé un répertoire /root/ldap/conf pour y mettre la configuration. Créons un répertoire pour y mettre les fichiers ldif contenant les données.

# cd /root/ldap

# mkdir data

# cd data

Pour rappel, les OUs sont des conteneurs qui permettent de ranger les données dans l’annuaire, de les hiérarchiser. Il ne faut pas les confondre avec les Groupes.

Créez un fichier OU.ldif et remplissez le de la sorte :

dn: ou=people,dc=debugo,dc=fr

ou: people

objectClass: organizationalUnit

 

dn: ou=group,dc=debugo,dc=fr

ou: group

objectClass: organizationalUnit

 

dn: ou=system,dc=debugo,dc=fr

ou: system

objectClass: organizationalUnit

 

dn: ou=debugo,ou=people,dc=debugo,dc=fr

ou: debugo

objectClass: organizationalUnit

 

dn: ou=client,ou=people,dc=debugo,dc=fr

ou: client

objectClass: organizationalUnit

 

dn: ou=sysgroup,ou=group,dc=debugo,dc=fr

ou: sysgroup

objectClass: organizationalUnit

 

dn: ou=workgroup,ou=group,dc=debugo,dc=fr

ou: workgroup

objectClass: organizationalUnit

Les OUs que j’utilise me sont propres. Surement en aurez vous besoin d’autres, etc.. A vous de modifier.

On injecte :

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f OU.ldif

II – Les utilisateurs

On va créer notre premier utilisateur.

Fichier User_niko.ldif :

dn: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

uid: niko

sn: niko

givenName: Nicolas

cn: Nicolas

displayName: Nicolas

userPassword: password

mail: mail@spam.com

title: Admin

initials: N

On injecte :

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f User_niko.ldif

Profitons pour faire une explication sur ces lignes :

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

Notre utilisateur héritera des attributs de ces trois classes. Mais qu’est ce donc ?

Voyons un peu les schémas :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config"

Beaucoup d’infos, pour s’en sortir affichons les dn des schémas :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" dn

Ce qui nous affiche :

dn: cn=schema,cn=config

dn: cn={0}core,cn=schema,cn=config

dn: cn={1}cosine,cn=schema,cn=config

dn: cn={2}nis,cn=schema,cn=config

dn: cn={3}inetorgperson,cn=schema,cn=config

dn: cn={4}ppolicy,cn=schema,cn=config

Concentrons nous sur le schéma core :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core"

La vous devez voir deux grands types de données : les olcObjectClasses et les olcAttributeTypes:

Les AttributeTypes sont les attributs que peuvent avoir les entrées de l’annuaire. Les ObjectClasses sont les regroupement de ces attributs.

Regardons les différents ObjectClasses qui composent notre schéma core :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core" olcObjectClasses

En cherchant dedans, on va trouver nos objectclasses person et organizationalPerson :

olcObjectClasses: {4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top

STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $

description ) )

olcObjectClasses: {5}( 2.5.6.7 NAME 'organizationalPerson' DESC 'RFC2256: an o

rganizational person' SUP person STRUCTURAL MAY ( title $ x121Address $ regis

teredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $

teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ fac

simileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $

physicalDeliveryOfficeName $ ou $ st $ l ) )

Ce qu’il faut comprendre :

L’ObjectClasses person hérite de top.

Must spécifie les AttributeTypes obligatoires : sn et cn.

May définie les AttributeTypes facultatives

Les AttributeTypes sont définis sur un modèle similaire, par exemple :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core" olcAttributeTypes

J’en prend un au hasard :

olcAttributeTypes: {6}( 2.5.4.9 NAME ( 'street' 'streetAddress' ) DESC 'RFC225

6: street address of this object' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreS

ubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )

On trouve le nom de l’attribut, une description et son type (SYNTAX suivi d’un OID, je reviendrais sur ce point dans le chapitre consacré à la création d’un schéma).

L’objet que l’on créé hérite des attributs des classes person, organizationalPerson et inetOrgPerson.

Voila donc pour les explications sur les ObjectClasses et les AttributeTypes:

Au passage, on va vérifier quelques points.

Regardons comment est stocké le mdp dans la base :

# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "uid=niko"

On voit une ligne :

userPassword:: e1NTSEF9TklxSkd5YVFBdVcwMkpOVmplcjArOGYwRmNNMjNBVXg=

Il s’agit d’un codage en base64. Pour le décoder :

# echo e1NTSEF9TklxSkd5YVFBdVcwMkpOVmplcjArOGYwRmNNMjNBVXg= | base64 -d

Et la on le résultat suivant :

{SSHA}NIqJGyaQAuW02JNVjer0+8f0FcM23AUx

Le mot de passe est bien crypté comme configuré avec l’overlay ppolicy.

Et pour tester la connexion avec ce compte :

# ldapsearch -xLLLH ldap://localhost -D uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr -W -b "dc=debugo,dc=fr" "uid=niko"

Et si vous tapez le bon mot de passe, cela vous affiche votre propre fiche.

III – Les groupes

A noter, il existe deux types de groupes : les posixgroup et les groupofnames.
Les posixgroup sont similaires au groupes Unix, et les groupofnames ressemblent plus à des groupes AD.
Pour faire simple, l’avantage des groupofnames est qu’avec un filtre sur un utilisateur, on peut connaitre ses groupes (avec l’overlay memberof). Chose impossible avec les posixgroups.
Par contre, il est impératif d’avoir au moins un utilisateur dans un groupe de type groupofnames. Vous pouvez être tenté de vous mettre par défaut, mais le jour ou vous aller modifier votre schéma, vous allez devoir supprimer les utilisateurs, et un groupe sans utilisateur garde l’uid du dernier membre à l’avoir quitté et si vous refaite un compte avec le même uid, impossible de vous remettre dedans sans supprimer le groupe. Bref, perso, je met l’admin par défaut, comme ça pas de risques. De plus notre overlay refint configuré au préalable est raccord avec cela.

On créé un fichier Group.ldif :

dn: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr

cn: cloud

description: Cloud

objectClass: groupOfNames

member: cn=admin,dc=debugo,dc=fr

 

dn: cn=debugo,ou=workgroup,ou=group,dc=debugo,dc=fr

cn: debugo

description: Debugo

objectClass: groupOfNames

member: cn=admin,dc=debugo,dc=fr

J’ai mis dedans les groupes dont j’ai besoin, à vous de faire en fonction, etc…

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f Group.ldif

Au passage, on peut tester notre overlay memberof :

# ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "cn=admin" memberof

Doit nous retourner quelque chose qui ressemble à :

dn: cn=admin,dc=debugo,dc=fr

memberOf: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr

memberOf: cn=wiki,ou=sysgroup,ou=group,dc=debugo,dc=fr

memberOf: cn=debugo,ou=workgroup,ou=group,dc=debugo,dc=fr

A la question, si je veux rajouter un utilisateur dans un groupe, comment faire ?

Je vous répond qu’avec OpenLdap, tout passe par des fichiers ldif, du coup, créez un fichier addusertogroup.ldif pour y mettre :

dn: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr

changetype: modify

add: member

member: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr

Puis on injecte :

# ldapmodify -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f addusertogroup.ldif

Et la, si on requête cela :

ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "uid=niko" memberof

On doit avoir ceci :

dn: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr

memberOf: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr

Nous verrons plus en détail les ajouts, modifications, suppressions dans la partie suivante.

IV – Comptes Système et ACL

Par défaut, l’accès à l’annuaire est assez ouvert :

# ldapsearch -xLLL

On voit ce que l’accès anonyme nous affiche…

On va devoir filtrer un peu.

Tout d’abord, nous allons créer deux compte systèmes. Un viewer (qui aura des droits de lecture uniquement, utilisé par les applications pour se connecter à l’annuaire et vérifier des droits, au lieu de passe par le bind anonyme) et un Writer (qui lui aura des droits d’écriture…)

Créez le fichier viewer.ldif :

dn: cn=viewer,ou=system,dc=debugo,dc=fr

objectClass: simpleSecurityObject

objectClass: organizationalRole

cn: viewer

description: LDAP viewer

userPassword: passview

Créez le fichier writer.ldif :

dn: cn=writer,ou=system,dc=debugo,dc=fr

objectClass: simpleSecurityObject

objectClass: organizationalRole

cn: writer

description: LDAP Writer

userPassword: passwrite

Injectez :

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f viewer.ldif

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f writer.ldif

Voyons les ACLs par défaut :

# ldapsearch -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=config" "olcDatabase={1}mdb" olcaccess

Modifions les pour empêcher les connexions anonymes.

Créez un fichier acl.ldif :

dn: olcDatabase={1}mdb,cn=config

changetype: modify

replace: olcAccess

olcAccess: to attrs=userPassword by self write by anonymous auth by dn="cn=writer,ou=system,dc=debugo,dc=fr" write by dn="cn=viewer,ou=system,dc=debugo,dc=fr" read by dn="cn=admin,dc=debugo,dc=fr" write by * none

olcAccess: to dn.base="dc=debugo,dc=fr" by users read

olcAccess: to * by self write by dn="cn=admin,dc=debugo,dc=fr" write by * read by anonymous none

J’expliquerais plus précisément le fonctionnement des ACLs dans un autre article. Nous modifions la deuxieme ACL qui par défaut donne accès en lecture à tout le monde. La, nous réduisons la lecture aux utilisateurs authentifiés.

On injecte :

ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f acl.ldif

On test de manière anonyme :

# ldapsearch -xLLL

Ça ne passe plus.

On teste avec notre compte viewer :

# ldapsearch -xLLL -H ldap://localhost -D cn=viewer,ou=system,dc=debugo,dc=fr -w passview -b "dc=debugo,dc=fr" "uid=niko"

Bingo !

Dans la prochaine partie, nous allons voir comment modifier les entrées de l’annuaire.

Modification des données

Quatrième partie de la série de tuto sur OpenLDAP consacrée à la modification des données.

Après avoir vu l’installation, les overlays et inséré nos premières données, voyons maintenant comment les modifier.

Avant tout, rappelons que nous pouvons en gros séparer les objets que nous manipulons en quatre familles (il y en a plus, mais je fais simple)

Les schémas (nous verrons cela en détail dans un autre article)

Les OU, qui sont des conteneurs.

Les entrées : groupes, utilisateur, etc…

Les attributs, rattachés aux entrées.

I – Préparatif rapide

Nous allons utiliser énormément les commande ldapsearch et ldapmodify.

Du coup, afin d’aller plus vite nous allons créer des alias.

Éditez le fichier /root/.bashrc pour y ajouter :

alias lmodif='ldapmodify -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap'

alias lsearch='ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap'

alias ladd='ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap'

alias ldel='ldapdelete -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap'

Puis pour recharger le fichier :

# source ~/.bashrc

Dorénavant, il n’y aura plus tout à saisir…

II – OU

Tout d’abord, listons ce qui est présent

# lsearch -b "dc=debugo,dc=fr" "objectClass=organizationalUnit"

A – Ajout d’une OU

Je vais profiter de cette partie sur les OU pour expliquer les trois commandes à notre disposition pour modifier les données de l’annuaire : ldapadd, ldapmodify et ldapdelete.

ldapadd est un alias de ldapmodify -a, le commutateur -a indiquant un ajout. Ce commutateur peut être remplacé par la ligne changetype: add dans le fichier ldif.

Ainsi, pour ajouter une OU par ex avec le fichier addou.ldif :

dn: ou=test,ou=people,dc=debugo,dc=fr

ou: test

objectClass: organizationalUnit

Injection :

# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f addou.ldif

ou

# ldapmodify -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -a -f addou.ldif

Autre méthode avec le ficher addou.ldif :

dn: ou=test,ou=people,dc=debugo,dc=fr

changetype: add

ou: test

objectClass: organizationalUnit

Injection

# ldapmodify -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f addou.ldif

Ces trois façons de faire donnent le même résultat.

L’avantage de tout faire par ex avec ldapmodify est que l’on peut effectuer plusieurs opérations en un fichier, le tout étant de laisser une ligne avec – entre chaque opération.

Exemple avec le fichier test.ldif :

dn: ou=test,ou=people,dc=debugo,dc=fr

changetype: add

ou: test

objectClass: organizationalUnit

-

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

changetype: delete

Dans ce fichier, nous ajoutons une OU puis nous supprimons un utilisateur. Il n’y a pas de limite d’opérations que l’on peut effectuer en une fois.

B – Modification d’une OU

Nous renommons l’OU test en newtest avec le fichier chgou.ldif :

dn: ou=test,ou=people,dc=debugo,dc=fr

changetype: modrdn

newrdn: ou=newtest

deleteoldrdn: 1

Injection :

# lmodif -f chgou.ldif

C – Déplacement d’une OU

Nous déplaçons l’OU newtest de la branche ou=people,dc=debugo,dc=fr vers la branche ou=workgroup,ou=group,dc=debugo,dc=fr avec le fichier mvou.ldif :

dn: ou=newtest,ou=people,dc=debugo,dc=fr

changetype: modrdn

newrdn: ou=newtest

deleteoldrdn: 1

newsuperior: ou=workgroup,ou=group,dc=debugo,dc=fr

Injection :

# lmodif -f mvou.ldif

D – Suppression d’une OU

Il est nécessaire qu’elle soit vide.

Supprimons l’OU newtest avec le fichier deleteou.ldif :

dn: ou=newtest,ou=workgroup,ou=group,dc=debugo,dc=fr

changetype: delete

Injection :

# lmodif -f deleteou.ldif

Ou bien un fichier deleteou.ldif :

ou=newtest,ou=workgroup,ou=group,dc=debugo,dc=fr

Injection :

# ldel -f deleteou.ldif

 

III – Modification d’entrées

Dans notre cas, les entrées sont de deux types, les users et les groupes.

Listons les groupes :

# lsearch -b "dc=debugo,dc=fr" "objectClass=groupOfNames"

Listons les users :

# lsearch -b "dc=debugo,dc=fr" "objectClass=InetOrgPerson"

A – Ajout

1 – Ajout d’un utilisateur

Ajoutons un utilisateur toto avec le fichier adduser.ldif :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

objectclass: top

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

uid: toto

sn: toto

givenName: toto

cn: toto

displayName: toto

userPassword: password

Injection :

# ladd -f adduser.ldif

2 – Ajout d’un groupe

Ajoutons un groupe test avec le fichier addgrp.ldif :

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

cn: test

description: test

objectClass: groupOfNames

member: cn=admin,dc=debugo,dc=fr

Injection :

# ladd -f addgrp.ldif

B – Déplacement

1 – Déplacement d’un utilisateur

Déplaçons toto de ou=debugo,ou=people,dc=debugo,dc=fr vers ou=client,ou=people,dc=debugo,dc=fr avec le fichier mvuser.ldif :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

changetype: modrdn

newrdn: uid=toto

deleteoldrdn: 1

newsuperior: ou=client,ou=people,dc=debugo,dc=fr

Injection :

# lmodif -f mvuser.ldif

2 – Déplacement d’un groupe

Déplaçons le groupe test de ou=workgroup,ou=group,dc=debugo,dc=fr vers ou=sysgroup,ou=group,dc=debugo,dc=fr avec le fichier mvgrp.ldif :

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

changetype: modrdn

newrdn: cn=test

deleteoldrdn: 1

newsuperior: ou=sysgroup,ou=group,dc=debugo,dc=fr

Injection :

# lmodif -f mvgrp.ldif

C – Renommage

1 – Renommage d’un utilisateur

Renommons toto en tata avec le fichier renameuser.ldif :

dn: uid=toto,ou=client,ou=people,dc=debugo,dc=fr

changetype: modrdn

newrdn: uid=tata

deleteoldrdn: 1

Injection

# lmodif -f renameuser.ldif

Ceci ne change que le nom de l’entrée dn: uid=tata,ou=client,ou=people,dc=debugo,dc=fr. Les autres attributs (cn, sn, etc..) s’ils doivent être renommés seront modifiés par une autre opération (voir plus bas).

2 – Renommage d’un groupe

Renommons le groupe test en newtest avec le fichier renamegrp.ldif :

dn: cn=test,ou=sysgroup,ou=group,dc=debugo,dc=fr

changetype: modrdn

newrdn: cn=newtest

deleteoldrdn: 1

Injection

# lmodif -f renamegrp.ldif

D – Suppression

1 – Suppression d’un utilisateur

Supprimons l’utilisateur tata à l’aide d’un fichier deluser.ldif :

dn: uid=tata,ou=client,ou=people,dc=debugo,dc=fr

changetype: delete

Injection

# lmodif -f deluser.ldif

On aurait pu aussi directement faire :

# ldel uid=tata,ou=client,ou=people,dc=debugo,dc=fr

2 – Suppression d’un groupe

Supprimons le groupe newtest à l’aide d’un fichier delgrp.ldif :

dn: cn=newtest,ou=sysgroup,ou=group,dc=debugo,dc=fr

changetype: delete

Injection

# lmodif -f delgrp.ldif

Ou bien :

# ldel cn=newtest,ou=sysgroup,ou=group,dc=debugo,dc=fr

IV – Modification d’attributs

Nous allons réinsérer un utilisateur test et un groupe test avant tout :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

objectclass: top

objectclass: person

objectclass: organizationalPerson

objectclass: inetOrgPerson

uid: toto

sn: toto

givenName: toto

cn: toto

displayName: toto

userPassword: password

Injection :

# ladd -f adduser.ldif

Puis :

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

cn: test

description: test

objectClass: groupOfNames

member: cn=admin,dc=debugo,dc=fr

Injection :

# ladd -f addgrp.ldif

A – Ajout

1 – Utilisateur

Listons les attributs à notre disposition :

# lsearch -b "cn=schema,cn=config" olcAttributeTypes

Ou plus précises ment du schéma core :

# lsearch -b "cn={0}core,cn=schema,cn=config" olcAttributeTypes

Ajoutons un attribut description à notre utilisateur toto avec un fichier addattribute.ldif :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

changetype: modify

add: description

description: Sa tete est egale a zero plus zero !

Injection :

# lmodif -f addattribute.ldif

Et on peut vérifier l’ajout :

# lsearch -b "dc=debugo,dc=fr" uid=toto

 

2 – Groupe

Regardons ce que propose la classe groupOfNames (dans le schéma core)

# lsearch -b "cn={0}core,cn=schema,cn=config" olcObjectClasses

On va trouver :

olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of n

ames (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategory $

seeAlso $ owner $ ou $ o $ description ) )

Pour un groupe, ce qui est le plus fréquent d’ajouter comme attribut, c’est un utilisateur (ajout d’un membre dans un groupe…)

Bref, ajoutons donc notre utilisateur test dans le groupe test  avec un fichier addusertogroup.ldif :

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

changetype: modify

add: member

member: uid=toto,ou=client,ou=people,dc=debugo,dc=fr

Injection :

# lmodif -f addusertogroup.ldif

On peut vérifier :

# lsearch -b "dc=debugo,dc=fr" "(&(objectclass=inetOrgPerson)(memberof=cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr))" dn

Si on regarde la fiche de toto :

# lsearch -b "dc=debugo,dc=fr" "uid=toto"

On constater qu’on ne voit pas l’attribut memberof (overlay que nous avons pourtant configuré. En effet, il faut le demander spécifiquement :

# lsearch -b "dc=debugo,dc=fr" "uid=toto" memberof

Ou alors, nous pouvons le voir avec cette commande :

# lsearch -b "dc=debugo,dc=fr" "uid=toto" +

B – Modification

1 – Utilisateur

Un attribut qui peut etre modifié fréquement sur un utilisateur, c’est le mot de passe. Modifions donc le mot de passe de toto avec un fichier chgpwd.ldif :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

changetype: modify

replace: UserPassword

UserPassword: newpass

Injection :

# lmodif -f chgpwd.ldif

Ceci dit, pour modifier un mot de passe, nous avons la commande ldappassword consacré à cet usage :

# ldappasswd -H ldap://localhost -D "uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr" -W -S

-W pour la demande de l’ancien mot de passe.

-S pour la demande d’un nouveau mot de passe (sinon, le nouveau mot de passe est généré aléatoirement)

Cette commande peut également servir à changer le mot de passe d’un autre utilisateur, par exemple, le compte admin demande à changer le mot de passe de l’utilisateur niko :

# ldappasswd -D "cn=admin,dc=debugo,dc=fr" -w passsadmin -x "uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr" -S

2 – Groupe

Modifions la description de notre groupe test avec un fichier chgattr.ldif :

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

changetype: modify

replace: description

description: Nouvelle description

Injection :

# lmodif -f chgattr.ldif

C – Suppression

1 – Utilisateur

Supprimons l’attribut description de toto avec un fichier delattr.ldif :

dn: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

changetype: modify

delete: description

Injection :

# lmodif -f delattr.ldif

2 – Groupe

Pour un groupe, vous vous en doutez, un attribut qui peut etre amené à etre supprimé, c’est un membre. Supprimons donc toto du groupe test avec un ficher

dn: cn=test,ou=workgroup,ou=group,dc=debugo,dc=fr

changetype: modify

delete: member

member: uid=toto,ou=debugo,ou=people,dc=debugo,dc=fr

Injection

# lmodif -f deluserfromgroup.ldif

Vérification :

# lsearch -b "dc=debugo,dc=fr" "(&(objectclass=groupOfNames)(cn=test))" member

V – Conclusion

Voila qui termine ce long article. J’aurais pu faire plus court, certaines manipulation étant au final tres similaire, mais j’ai ainsi voulu couvrir de nombreuses applications que vous pouvez être amenés à rencontrer.

Dans le chapitre suivant, nous allons parler sauvegarde et restauration.

Sauvegarde et restauration

Cinquième partie de la série de tuto sur OpenLDAP consacrée à la sauvegarde et restauration des données.

Jusque la, nous avons vu l’installation, les overlays,inséré nos premières données, et appris comment les modifier.

Voyons maintenant comment effectuer des sauvegardes de tout cela.

Rappel, j’utilise des alias que je défini au début de cet article.

I – Sauvegarde

On va prendre connaissance de l’endroit ou sont stockées les données.

# lsearch -b "cn=config" "(&(objectClass=olcDatabaseConfig))" olcDbDirectory

Ce qui va donner :

dn: olcDatabase={-1}frontend,cn=config

 

dn: olcDatabase={0}config,cn=config

 

dn: olcDatabase={1}mdb,cn=config

olcDbDirectory: /var/lib/ldap

La ligne qui nous intéresse est /var/lib/ldap.

A – Configuration

Cette commande peut être lancée avec le service LDAP en fonctionnement.

# slapcat -b cn=config > save_config.ldif

B – Données

Comme pour la configuration, cette commande peut être lancée avec le service en fonctionnement.

# slapcat -b dc=debugo,dc=fr > save_data.ldif

 

II – Restauration

A – Configuration

On commence par arrêter le serveur si celui ci tourne :

# service slapd stop

On va supprimer l’existant :

# rm /etc/ldap/slapd.d/ -r

On va recréer :

# mkdir /etc/ldap/slapd.d/

On réinjecte :

# slapadd -F /etc/ldap/slapd.d -b cn=config -l save_config.ldif

On redonne les droits

# chown -R openldap:openldap /etc/ldap/slapd.d/

On peut relancer :

# service slapd start

 

B – Données

On commence par arrêter le serveur si celui ci tourne :

# service slapd stop

On va supprimer l’existant (repertoire que nous avons noté au début) :

# rm /var/lib/ldap/ -r

On va recréer :

# mkdir /var/lib/ldap/

On réinjecte :

# slapadd -b dc=debugo,dc=fr -l save_data.ldif

On redonne les droits

# chown -R openldap:openldap /var/lib/ldap/

On ré-indexe :

# slapindex

On relance le serveur :

# service slapd start

 

 

Et voila ! Ces manipulations sont simple, mais ne les négligez pas, il reste assez facile de fusiller un annuaire LDAP avec quelques fausses manipulations…

Dans l’article suivant, nous allons voir la réplication.

Réplication

Nous allons mettre en place une réplication Maitre-Maitre. L’idée est de faire en sorte que n’importe lequel de nos serveurs LDAP soit capable à la fois de lire les données, mais également de les modifier. De plus,nous allons mettre en place une réplication, à la fois sur l’arbre de données dc=debugo,dc=fr mais également sur l’arbre de configuration cn=config.

 

I – Prérequis

Sur un nouveau serveur, installez OpenLDAP, puis comme pour le serveur déjà en place:

# dpkg-reconfigure slapd

Mettez les informations que vous aviez renseignées.

Effectuez également la configuration de rsyslog.

Maintenant, sur le premier serveur, créez des sauvegardes de la configuration et des données (suivez ce tuto). Puis, depuis le premier serveur, nous allons envoyer les fichiers de sauvegarde sur le second serveur, ceci afin de gagner du temps. Pas de besoin de tout reconfigurer à l’identique.

maitre1# scp save_*.ldif root@maitre2:/root

Ensuite, réinjectez les sauvegardes en suivant la partie II de l’article Sauvegarde et restauration.

 

II – Configuration

Ce qui suit est à faire sur chaque serveur !

A – Activation Overlay

Nous allons commencer par activer l’Overlay Syncprov à l’aide d’un fichier 01-syncprov_act.ldif :

dn: cn=module,cn=config

cn: module

objectclass: olcModuleList

objectclass: top

olcmoduleload: syncprov.la

olcmodulepath: /usr/lib/ldap

On injecte :

ldapx# ldapadd -Y EXTERNAL -H ldapi:/// -f 01-syncprov_act.ldif

On peut vérifier avec :

ldapx# ldapsearch -LLLY external -H ldapi:/// -b "cn=config" "objectClass=olcModuleList"

ldapx# ldapsearch -LLLY external -H ldapi:/// -b "cn=module{6},cn=config"

B – ServerID

Sur chaque serveur, un fichier 02-serverid.ldif :

dn: cn=config

changetype: modify

add: olcServerID

olcServerID: x

Attention, sur le premier serveur olcServerID:1, sur le second  olcServerID: 2, etc…

On injecte :

ldapx# ldapmodify -Y EXTERNAL -H ldapi:/// -f 02-serverid.ldif

Pour vérifier :

ldapx# ldapsearch -LLLY external -H ldapi:/// -b "cn=config" "objectClass=olcGlobal" olcServerID

C – Création utilisateur réplication

Ensuite, nous allons créer un utilisateur pour la replication dans un fichier 03-replica_account.ldif :

dn: cn=replica,ou=system,dc=debugo,dc=fr

userPassword: password

cn: replica

objectclass: top

objectclass: person

sn: replica

On injecte :

ldapx#  ldapadd -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f 03-replica_account.ldif

 

III – Réplication de la configuration

Ces manipulations sont toujours à effectuer sur les deux serveurs.

A – ACL

Nous allons donner à l’utilisateur cn=replica,dc=debugo,dc=fr le droit de modifier la configuration via un fichier 04-droit_conf.ldif :

dn: olcDatabase={0}config,cn=config

changeType: modify

add: olcAccess

olcAccess: to * by dn.exact=cn=replica,ou=system,dc=debugo,dc=fr manage by * break

On injecte

ldapx# ldapmodify -Y EXTERNAL -H ldapi:/// -f 04-droit_conf.ldif

B – Configuration

Créez un fichier 05-syncprov_conf_conf.ldif pour y mettre :

dn: olcOverlay=syncprov,olcDatabase={0}config,cn=config

changetype: add

objectClass: olcOverlayConfig

objectClass: olcSyncProvConfig

olcOverlay: syncprov

Injectez :

ldapx# ldapmodify -Y EXTERNAL -H ldapi:/// -f 05-syncprov_conf_conf.ldif

C – Paramétrage

Créez un fichier 06-repl_conf_conf.ldif pour y mettre :

dn: olcDatabase={0}config,cn=config

changetype: modify

add: olcSyncRepl

olcSyncRepl: rid=01 provider=ldap://IPSERVEUR1

  binddn="cn=replica,ou=system,dc=debugo,dc=fr" bindmethod=simple

  credentials=password searchbase="cn=config"

  type=refreshAndPersist retry="5 5 300 5" timeout=1

olcSyncRepl: rid=02 provider=ldap://IPSERVEUR2

  binddn="cn=replica,ou=system,dc=debugo,dc=fr" bindmethod=simple

  credentials=password searchbase="cn=config"

  type=refreshAndPersist retry="5 5 300 5" timeout=1

-

add: olcMirrorMode

olcMirrorMode: TRUE

Les lignes binddn, credentials, et type doivent commencer avec deux espaces.

et injectez :

ldapx# ldapmodify -Y EXTERNAL -H ldapi:/// -f 06-repl_conf_conf.ldif

Vérifiez avec :

# ldapsearch -QLLLY external -H ldapi:/// -b "cn=config" "olcDatabase={0}config" olcSyncRepl

Et voila !

Si vous modifiez la configuration sur un serveur (des ACLs par exemple), cela sera répliqué sur l’autre.

Dans les logs, on doit voir des traces de la synchro. Et pour être sur que tout est bien configuré :

# ldapsearch -z1 -LLLQY EXTERNAL -H ldapi:/// -s base -b cn=config contextCSN

doit vous donner le même contextCSN sur chaque serveur.

 

IV – Réplication des données

Ces manipulations ne sont à faire que sur un serveur étant donné que la réplication de la configuration est en place !

A – ACL et limitation

Nos acls avaient déjà été établies.

Vérifiez sur les deux serveurs :

ldapx# ldapsearch -QLLLY external -H ldapi:/// -b "cn=config" "olcDatabase={1}mdb" olcAccess

Doit vous donner :

dn: olcDatabase={1}mdb,cn=config

olcAccess:

  {0}to attrs=userPassword

  by self write by anonymous auth

  by dn="cn=writer,ou=system,dc=debugo,dc=fr" write

  by dn="cn=viewer,ou=system,dc=debugo,dc=fr" read

  by dn="cn=admin,dc=debugo,dc=fr" write

  by * none

olcAccess:

  {1}to dn.base="dc=debugo,dc=fr"

  by users read

olcAccess:

  {2}to *

  by self write

  by dn="cn=admin,dc=debugo,dc=fr" write

  by * read

  by anonymous none

Nous allons les modifier avec un fichier 07-acl_replica.ldif pour donner le droit à l’utilisateur réplica de TOUT lire (y compris les passwords)  :

dn: olcDatabase={1}mdb,cn=config

changetype: modify

replace: olcAccess

olcAccess: to attrs=userPassword by self write by anonymous auth by dn="cn=writer,ou=system,dc=debugo,dc=fr" write by dn="cn=viewer,ou=system,dc=debugo,dc=fr" read by dn="cn=admin,dc=debugo,dc=fr" write by dn.exact="cn=replica,ou=system,dc=debugo,dc=fr" read by * none

olcAccess: to dn.subtree="dc=debugo,dc=fr" by users read by * none

olcAccess: to * by self write by dn="cn=admin,dc=debugo,dc=fr" write by * read by anonymous none

On injecte :

ldap1# ldapmodify -Y EXTERNAL -H ldapi:/// -f 07-acl_replica.ldif

Vous pouvez vérifier sur chaque serveur, c’est à jour :

ldapx# ldapsearch -QLLLY external -H ldapi:/// -b "cn=config" "olcDatabase={1}mdb" olcAccess

Au passage, on va modifier les limitations dans un fichier 08-limit.ldif :

dn: olcDatabase={1}mdb,cn=config

changetype: modify

add: olcLimits

olcLimits: dn.exact="cn=replica,ou=system,dc=debugo,dc=fr" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited

On injecte :

ldap1# ldapmodify -Y EXTERNAL -H ldapi:/// -f 08-limit.ldif

B – Index

On va indexer entryCSN et entryUUID à l’aide d’un fichier 09-index.ldif :

dn:olcDatabase={1}mdb,cn=config

changetype: modify

add: olcDbIndex

olcDbIndex: entryCSN,entryUUID eq

On injecte :

ldap1# ldapmodify -Y EXTERNAL -H ldapi:/// -f 09-index.ldif

C – Configuration

On va configurer l’overlay sur la base {1}mdb, qui correspond à notre dc=debugo,dc=fr, avec un fichier 10-syncprov_conf_data.ldif :

dn: olcOverlay=syncprov,olcDatabase={1}mdb,cn=config

changetype: add

objectClass: olcOverlayConfig

objectClass: olcSyncProvConfig

olcOverlay: syncprov

Injectez :

ldap1# ldapmodify -Y EXTERNAL -H ldapi:/// -f 10-syncprov_conf_data.ldif

D – Paramétrage

Créez un fichier 11-repl_conf_data.ldif et insérez :

dn: olcDatabase={1}mdb,cn=config

changetype: modify

add: olcSyncRepl

olcSyncRepl: rid=01 provider=ldap://IPSERVEUR1

  binddn="cn=replica,ou=system,dc=debugo,dc=fr"

  bindmethod=simple credentials=password

  searchbase="dc=debugo,dc=fr"

  type=refreshAndPersist retry="5 5 300 5" timeout=1

olcSyncRepl: rid=02 provider=ldap://IPSERVEUR2

  binddn="cn=replica,ou=system,dc=debugo,dc=fr"

  bindmethod=simple credentials=password

  searchbase="dc=debugo,dc=fr"

  type=refreshAndPersist retry="5 5 300 5" timeout=1

-

add: olcMirrorMode

olcMirrorMode: TRUE

Injectez :

ldap1# ldapmodify -Y EXTERNAL -H ldapi:/// -f 11-repl_conf_data.ldif

Pour vérifier la synchro, sur un des serveurs, effectuez par exemple une modification d’attribut sur un utilisateur, puis sur les deux serveurs, lancez la commande :

ldapx# ldapsearch -z1 -LLLQY EXTERNAL -H ldapi:/// -s base -b dc=debugo,dc=fr contextCSN

Celle ci doit vous donner la meme réponse. Il faut qu’il y ait eu une modification (changement d’attribut par exemple) sans quoi l’attribut contextCSN n’existera pas.

 

V – Dernier réglage

Dernier point, concernant un petit effet de bord du à la synchro des configurations :

Vos serveurs se retrouvent avec le meme ServerID :

ldapx# ldapsearch -x -LLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -w passadmin -b cn=config "objectClass=olcGlobal"

Pour modifier cela, pas le choix, nous allons devoir éditer le fichier directement (si on refait un ldif qu’on injecte ça va se répliquer…). C’est le mal d’éditer les configs ldap à la main, mais ce coup ci, on a guère le choix…

Du coup, sur les deux serveurs, on arrête slapd :

ldapx# service slapd stop

Puis on va éditer le fichier /etc/ldap/slapd.d/cn\=config.ldif pour renseigner :

olcServerID: X

Ou X sera égal à 1 sur le premier serveur et égal à 2 sur le second.

Puis on relance les deux serveurs: :

ldapx# service slapd start

Et maintenant sur chaque serveur, la commande :

ldapx# ldapsearch -x -LLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -w passadmin -b cn=config "objectClass=olcGlobal"

donne bien son ID propre.

 

Voila qui clos la partie sur la réplication à proprement parlé.

Dans la partie suivante, nous allons rajouter Keepalived, qui nous permettra d’avoir une IP virtuelle unique pour interroger nos LDAPs.

Keepalived

Septième partie de la série de tuto sur OpenLDAP dans la continuité de la partie précédente sur la réplication, nous allons mettre en place le logiciel Keepalived afin que nos services LDAP soient accessibles via une IP unique.

Ceci ne sera pas un tutoriel complet sur Keepalived, mais juste une rapide présentation et mise en place. J’en parlerais plus longuement dans un futur article sur la haute disponibilité, etc…

I – Maintenez les en vie !

A – Présentation

Keepalived permet de faire deux choses distinctes :

Comme je l’expliquais au préalable, nous allons rapidement l’installer et le configurer sans trop rentrer dans les détails, non pas que ça ne soit pas intéressant, mais ce n’est pas le sujet qui nous intéresse aujourd’hui. Pour le moment, on veut juste avoir nos serveurs Ldap accessible.

B- Installation

Sur nos deux serveurs, nous installons Keepalived :

ldapx# apt-get install keepalived

Sa configuration se trouvera dans /etc/keepalived qui, pour le moment est vide.

 

II – Configuration simple : une IP virtuelle

Nous allons commencer par la configuration la plus simple, la création d’une IP virtuelle qui se « baladera » entre nos deux serveurs LDAP en fonction de leur état.

Pour cela, créez sur les deux serveurs un fichier /etc/keepalived/keepalived.conf et remplissez le ainsi :

vrrp_script check_server_health {

    script "/etc/keepalived/test_ldap.sh aaa.aaa.aaa.aaa" (mettre l'ip réel de votre serveur)

    interval 2

    fall 2

    rise 2

}

vrrp_instance VI_LDAP {

    state BACKUP

    interface eth1

    virtual_router_id 50

    priority xxx (mettre 100 sur le serveur 1 et 10 par ex, sur le serveur 2)

    advert_int 1

    lvs_sync_daemon_interface eth1

 

    authentication {

        auth_type PASS

        auth_pass MON_MOT_DE_PASSE_SECRET

    }

 

    track_script {

        check_server_health

    }

 

    virtual_ipaddress {

        XXX.XXX.XXX.XXX (mettre l'ip virtuelle de votre choix)

    }

}

La valeur priority doit être adaptée. Elle doit être plus élevée sur votre serveur principal et plus faible sur le serveur secondaire.

Bien sur, vous remplacerez aaa.aaa.aaa.aaa par l’ip de votre serveur Ldap sur lequel vous êtes actuellement et xxx.xxx.xxx.xxx par l’ip virtuelle que vous aurez choisi.

Renseignez également la bonne interface dans les options interface et lvs_sync_daemon_interface en fonction de votre configuration (chez moi, eth1, pour le réseau inter-machines, l’eth0 étant pour les communications avec la gateway)

Il faut également créer le fichier qui va tester la santé de vos serveurs Ldap.
Créez donc un fichier (toujours sur les deux serveurs bien évidement) /etc/keepalived/test_ldap.sh et mettez ceci dedans :

#!/bin/bash

 

ldapsearch -x -H ldap://$1 -D cn=viewer,ou=system,dc=debugo,dc=fr -w motdepasse-b dc=debugo,dc=fr -l 3 > /dev/null 2>&1

ldapresponse=$?

 

if [ "$ldapresponse" -gt 0 ]; then

    echo "down"

    exit 1

else

    echo "up"

fi

 

exit 0

Vous mettrez bien sur les valeurs adaptées à votre configuration. Keepalived attend une valeur à 0 si tout va bien et 1 si il y a une erreur.

Pensez à le rendre exécutable :

ldapx# chmod /etc/keepalived/test_ldap.sh +x

Ensuite, vous n’avez plus qu’à lancer sur les deux serveurs :

ldapx# service keepalived start

On peut vérifier l’état avec :

ldapx# service keepalived status

Sur le serveur principal, on fait un:

ldap1# ifconfig eth1

et …. rien !

En effet, keepalived passe par iproute2 et certaines données ne seront donc pas affichées avec la vieille commande ifconfig. Pour voir cette nouvelle IP, il faut donc faire :

ldap1#  ip addr show dev eth1

Maintenant, testez… Si vous coupez le serveur 1, l’ip bascule sur le 2 et si le serveur 1 revient, l’IP revient dessus.

 

III – Et avec du loadbalancing ?

Dans notre configuration actuelle, tout le trafic arrivant sur notre ip virtuelle est relayé vers un seul serveur.

Que faire si nous voulons ajouter du loadbalancing et faire en sorte que nos deux serveurs soient ainsi sollicités ?

Rien de compliqué, ajoutez ce qui suit au fichier /etc/keepalived/keepalived.conf à la suite de ce que nous avons déjà mis :

[...]

virtual_server xxx.xxx.xxx.xxx 389 {

    delay_loop 5

    lb_algo wrr

    lb_kind DR

    persistence_timeout 0

    protocol TCP

 

    real_server aaa.aaa.aaa.aaa 389 {

        weight 1

        inhibit_on_failure

        MISC_CHECK {

            misc_path "/etc/keepalived/test.sh aaa.aaa.aaa.aaa"

        }

        connect_timeout 1

        nb_get_retry 1

        delay_before_retry 1

    }

 

    real_server bbb.bbb.bbb.bbb 389 {

        weight 1

        inhibit_on_failure

        MISC_CHECK {

            misc_path "/etc/keepalived/test.sh bbb.bbb.bbb.bbb"

        }

        connect_timeout 1

        nb_get_retry 1

        delay_before_retry 1

    }

}

La, le complément du fichier sera le même sur les deux serveurs.

Modifiez simplement les adresses aaa.aaa.aaa.aaa et bbb.bbb.bbb.bbb par les adresses de vos serveurs Ldap et xxx.xxx.xxx.xxx par votre ip virtuelle.

On relance sur les deux serveurs :

ldapx# service keepalived restart

On va tester depuis une autre machine en installant ldap-utils :

test# apt-get ldap-utils

Puis, effectuez plusieurs fois :

test# ldapsearch -x -LLL -H ldap://ipvrituelle -D cn=admin,dc=debugo,dc=fr -w motdepasse-b cn=config "objectClass=olcGlobal" olcServerID

Tiens, curieux, une fois sur deux ça ne marche pas…

Mmm… Pourquoi donc…

Vous le savez, pour déboguer du réseau, tcpdump, c’est le bien. Du coup, on l’installe sur notre serveur qui ne répond pas (normalement, ce doit être le secondaire, vérifiez la réponse olcServerID) :

ldap2# apt-get install tcpdump

Et on va écouter un peu ce qui se passe :

ldap2# tcpdump -i eth1 port 389 -n

Puis relancer la commande sur la machine test. Entre les traces des paquets échangées entre les instances de Keepalived et le serveur Ldap, on doit voir des paquets émanant de votre machine de test et adressé à votre serveur sur l’IP Virtuelle….

Ha ! Il est la le problème !

Le serveur secondaire n’a pas cette IP (vu que pour le moment, elle est attribuée au serveur principal).

Donc, il nous suffit de rajouter un alias. Dans le fichier /etc/network/interfaces, ajoutez ceci :

auto lo:0

iface lo:0 inet static

address xxx.xxx.xxx.xxx

netmask 255.255.255.255

Pour l’activer de suite :

ldap2# if up lo:0

Cette manipulation est à faire également sur le serveur principal, au cas ou il perde l’IP virtuelle (ce ne devrait se produire que si Openldap tombe et du coup, n’étant plus loadbalancé par Keepalived, il ne devrait pas recevoir de requêtes, donc, manipulation en théorie inutile, mais je suis du genre prudent…)

On reste depuis notre machine de test :

test# ldapsearch -x -LLL -H ldap://ipvrituelle -D cn=admin,dc=debugo,dc=fr -w motdepasse-b cn=config "objectClass=olcGlobal" olcServerID

Et la, selon le serveur qui répond, la réponse olcServerID sera différente. Sur le reste par contre, ce sera transparent pour les clients.

Bingo !

 

Concernant Keepalived, on pourrait encore dire beaucoup de chose, mais comme promis, ce sera dans un article dédié à ces techniques (Haute Disponibilité, Load Balancing, etc…)