36. Les annuaires LDAP

Important: La plupart des explications qui suivent sont tirées de l'excellent cours de Ganaël LAPLANCHE.

36.1. Les concepts du protocol

36.1.1. Quatre modèles

Les caractéristiques et fonctionnalités de LDAP sont regroupées en quatre modèles :

  1. Le modèle de nommage : définit comment l’information est stockée et organisée,

  2. Le modèle fonctionnel : définit les services fournis par l’annuaire (recherche, ajout, etc.),

  3. Le modèle d’information : définit le type d’informations stockées,

  4. Le modèle de sécurité : définit les droits d’accès aux ressources.

LDAP est un protocole, ce qu’il signifie que son rôle est de présenter des informations. Un serveur LDAP agit en tant qu’intermédiaire entre une source de données et un client. Il fonctionne sur le port 389 par défaut.

36.2. Organisation des données (le modèle de nommage)

Le modèle de nommage est la manière dont sont organisées les données dans l’annuaire.

36.2.1. Une réprésentation hiérarchique des données

Les données sont représentées sous forme d'arbre, couramment appelé Directory Information Tree (DIT). Chaque nœud, le Directory Entry Service (DES), représente une entrée. Ce format est conçu pour obtimiser la consultation des données, et non pas pour leur mise à jour.

Cette arborescence est liée au nommage de chaque élément : un élément marque son appartenance à l'élément supérieur en en reprenant le nom, qu'il complète par le sien.

Voici un exemple concret d'une représentation type (le rappel des entrées a été volontairement supprimé pour ne pas surcharger la figure) :

Figure 9. Exemple d'arbre LDAP

Une entrée peut soit être un élément d'organisation (typiquement une ou 'personnes'), soit un élément concret de cette organisation : un individu.

36.2.2. Termes à connaître

Voici un rappel des termes à connaître parfaitement :

  • Chaque élément est appelé une entrée (an entry). Une entrée peut être un branchement (un noeud, a node) ou un élément terminal (une feuille, a leaf).

  • Chaque élément possède un Distinguished Name (DN). Le DN est le nom complet de l’élément qui permet de le positionner dans l'arborescence. Il est unique dans l'annuaire.

    e.g : "cn=ventes,ou=groups,dc=martymac,dc=com"

  • Chaque élément possède également un Relative Distinguished Name (RDN). Le RDN est la partie du DN de l’élément qui est relative au DN supérieur. Le RDN d'un élément ne permet pas de l'identifier de manière abolue dans l'annuaire.

    e.g : "cn=ventes"

  • La racine est l'élément supérieur de tous les autres, c'est la base de l’arborescence. On l'appelle root en anglais, parfois on parle de "root DN".

    e.g : "dc=martymac,dc=com"

Les DN de chaque entrées sont composés au moins d'un attribut de l'élément (par exemple "cn" ou "uid") et de sa valeur. Un attribut est l'une des caractéristiques de cet élément.

L'arbre (en exemple ci-dessus) se découpe ensuite en deux Organisational Units (ou) qui constituent deux branchements : "users" et "groups", dans lesquels nous trouvons ensuite les entrées feuilles de notre arbre : les utilisateurs et les groupes.

36.2.3. Règles de nommage

La RFC 2253 (rendue obsolète par la RFC 4514) normalise l’écriture des DN et conseille de ne pas ajouter d'espaces autour du signe "=", ni à la fin du DN. Les espaces sont autorisés par contre pour les valeurs des entrées. Il est aussi possible d'utiliser un "line-wrap" (saut de ligne) pour les DN très long mais à condition de découper après le caractère séparateur.

Exemples concrets possibles :

  • "CN=Kurt D. Zeilenga,OU=Engineering,L=Redwood Shores,

    O=OpenLDAP Foundation,ST=California,C=US"

  • "cn=Ganael Laplanche,cn=ventes,ou=groups,dc=martymac,dc=com"

36.3. Accéder à l'annuaire (modèle fonctionnel)

Il existe plusieurs types d'opération possibles applicables sur l'annuaire :

L'utilisation des ces actions nécessite certains outils.

36.3.1. La base

La base est le DN à partir duquel nous allons agir. Pour une recherche, il s’agir du nœud à partir duquel est effectuée la recherche. Il peut s’agir de la racine de l’arbre pour une recherche sur la totalité de l’arbre.

e.g "dc=martymac,dc=com".

36.3.2. La porté

La portée (scope) définit la profondeur, le nombre de niveaux sur lesquels effectuer la recherche dans l'arbre des données. Il existe trois niveaux différents :

  1. SUB : l'action est effectuée récursivement à partir de la base spécifiée sur la totalité de l’arborescence.

  2. ONE : l'action est effectuée sur un seul niveau inférieur par rapport à la base spécifiée (les fils directs). Si l'on effectuait une recherche avec la portée ONE à partir de "dc=martymac,dc=com", nous pourrions trouver "ou=users,dc=martymac,dc=com" et "ou=groups,dc=martymac,dc=com".

  3. BASE : l'action est effectuée uniquement sur la base spécifiée. Une recherche sur "dc=martymac,dc=com" avec la portée BASE renverrait cette entrée uniquement.

36.3.3. Les filtres

Un filtre va permettre d’effectuer des tests de correspondance lors d’une recherche. Il s’agit en quelques sortes du critère de la recherche.

Il existe quatre tests basiques, qui peuvent ensuite être combinés :

  1. Le test d'égalité : X=Y

  2. Le test d'infériorité : X<=Y

  3. Le test de supériorité : X=>Y

  4. Le test d’approximation : X∼=Y

Les autres opérateurs (<, >) ou des tests plus complexes peuvent être mis en place par combinaison, il faut alors utiliser les parenthèses ( ) et l'un des opérateurs suivants :

  • L'intersection (et) : &

  • L'union (ou) : |

  • La négation (non) : !

Ainsi, un test d'infériorité stricte donnerait : (&(X<=Y)( !(X=Y)))

36.3.4. Les URLs LDAP

Récemment est apparue une méthode concise et simplifiée pour interroger un annuaire LDAP. Il s'agit d'un format d’URL combinant toutes les notions étudiées. En une seule ligne, il est possible de spécifier tous les éléments de notre requête. Voici le format de cette URL (RFC 2255, rendue obsolète par la RFC 4516) :

  • ldap[s]://serveur[:port][/[base[?[attributs à afficher][?[portée][?[filtre][?extensions]]]]]]

L'exemple ci-dessous recherche tous les uid de notre arbre, à partir de la branche users :

  • ldap://localhost:389/ou=users,dc=martymac,dc=com?uid?sub

36.4. Les données contenues dans l'annuaire (modèle d’information)

36.4.1. Les attributs

Un attribut est une valeur contenue dans une entrée.

Une entrée peut bien entendu contenir plusieurs attributs.

Voici un exemple de l'entrée LDAP d'un utilisateur POSIX :


dn: uid=martymac,ou=users,dc=martymac,dc=com
objectClass: account
objectClass: posixAccount
cn: martymac
uid: martymac
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/martymac
userPassword:: e0NSWVBUfWJjT29IUk5SbG1HbC4=
loginShell: /bin/sh
gecos: martymac
description: martymac

Le format affiché est le format LDIF.

Ce paragraphe présente tous les attributs, un par ligne, que comprend notre entrée. Un attribut est séparé de sa valeur par " :". Suivant son type, un attribut peut avoir plusieurs valeurs : dans ce cas, il est dit "multivalué" et apparaît sur plusieurs lignes avec des valeurs différentes.

Nous pouvons observer ici des attributs nommés "dn", "objectClass", "cn", "uid", ...

L’attribut "dn" qui est indiqué en première ligne est le nom unique de notre entrée dans l'arbre dont nous avons parlé précédemment. Il constitue un attribut à part entière dans notre entrée. Il est composé du dn de l'entrée supérieure, ainsi que du rdn.

n.b: le rdn est défini par un ou plusieurs attributs de l'entrée (dans ce cas séparés par un +). Il est conseillé, pour une entrée de type posixAccount, d'utiliser les attributs uid ou cn (cf. RFC 2307). Nous avons choisi ici uid=martymac.

Sur un annuaire LDAP la racine est toujours composée des attributs "dc" (Domain Component) associés à chacune des parties du nom de domaine où est hébergé le serveur ("dc=martymac,dc=com" pour le domaine martymac.com).

Ceci est une convention. X500 préconisait les attributs "o", "l" et "c", mais LDAP a simplifié le procédé (cf. RFCs 2247, 4519, 4524).

L'attribut "ou" constitue une Organisational Unit, c’est à dire une unité organisationnelle : en quelque sorte un regroupement. Nous avons choisi d'en créer deux dans notre exemple : "users", qui accueillera nos utilisateurs et "groups", nos groupes. L'un des attributs le plus important est la classe d'objet (objectClass).

36.4.2. Les classes d'objets

L'objectClass d’une entrée est un attribut qui permet de cataloguer cette entrée. Un objectClass définit un regroupement d'attributs obligatoires ou autorisés pour une entrée. Une entrée peut posséder un ou plusieurs objectClass. Ce sont ces objectClass qui définissent la présence de tous les autres attributs.

Ici, l’objectClass "posixAccount" rend obligatoires (MUST) les attributs cn, uid, uidNumber, gidNumber et homeDirectory. Il rend possible (MAY) l’utilisation des quatre autres attributs userPassword, loginShell, gecos et description.

36.4.3. Les schémas

Un annuaire LDAP a la capacité de charger en mémoire plusieurs schémas. À travers ces schémas, il est possible de définir de nouveaux attributs et de nouveaux objectClass. Cette souplesse permet de définir très finement ce qui sera stocké dans notre annuaire.

Concrètement, un schéma est un fichier qui décrit un à un les attributs disponibles (leur nom, leur type, etc...), ainsi que les objectClass qui y font appel. Au démarrage du serveur LDAP, le ou les fichiers de schéma spécifiés dans sa configuration seront chargés.

Dans notre exemple, l’objectClass posixAccount est défini dans le fichier nis.schema. Étudions une partie de ce fichier, livré avec OpenLDAP et situé dans /etc/ldap/schema :


#[...]
attributetype ( 1.3.6.1.1.1.1.0 NAME ’uidNumber’
	DESC ’An integer uniquely identifying a user in a domain’
	EQUALITY integerMatch
	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE−VALUE )
#[...]
objectclass( 1.3.6.1.1.1.2.0 NAME ’posixAccount’ SUP top AUXILIARY
               DESC ’Abstraction of an account with POSIX attributes’
               MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
               MAY ( userPassword $ loginShell $ gecos $ description))

Le premier paragraphe définit l'un des attributs utilisés par le posixAccount : uidNumber.

Le second, l’objectClass posixAccount. Il est important de savoir :

  • À chaque définition correspond un OID (Object IDentifier), qui permet de rendre unique l’attribut spécifié. Ces OIDs sont déposés auprès de l'IANA et sont donc officiels.

  • Un attribut définit un type d’égalité à mettre en oeuvre lors d’une recherche (ici, intergerMatch) ainsi que le type de données qu’il contient (l’OID spécifié après SYNTAX).

  • Un objectClass définit les attributs que l’objet doit présenter (MUST) et ceux qu'il peut posséder (MAY).

Il est tout à fait possible de créer ses propres schémas mais il est préférable de réutiliser ceux déjà existant.

36.4.4. Le format LDIF

Les données contenues dans l’annuaire sont présentées dans un certain format : il s’agit du format LDIF (LDAP Data Interchange Format - RFC 2849).

Dans ce format, chaque entrée constitue un paragraphe, et, au sein de chaque paragraphe, chaque ligne constitue un attribut. Voici un exemple un peu plus complet, incluant le groupe de notre utilisateur :


#[...]
dn: cn=utilisateurs,ou=groups,dc=martymac,dc=com
objectClass: posixGroup
cn: utilisateurs
gidNumber: 10001

dn: uid=martymac,ou=users,dc=martymac,dc=com
objectClass: account
objectClass: posixAccount
cn: martymac
uid: martymac
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/martymac
userPassword:: e0NSWVBUfWJjT29IUk5SbG1HbC4=
loginShell: /bin/sh
gecos: martymac
description: martymac
#[...]

36.5. La sécurité (modèle de sécurité)

LDAP fournit plusieurs modèles de sécurité applicable.

36.5.1. L’authentification simple, le binding

L’une des opérations préalables à l’interrogation de l’annuaire est cette opération dite de "binding" (dans le cas d’une authentification simple). Le client envoie alors le DN d’un compte contenu dans l’annuaire lui-même, ainsi que le mot de passe associé. On pourra par la suite appliquer des droits particuliers sur ce compte en utilisant les ACLs.

Ceci correspond, si l’on fait le parallèle avec l’annuaire téléphonique, à la fonctionnalité de liste rouge, où certaines données ne sont pas accessibles à tout le monde.

Notez enfin qu’il est possible de se connecter de manière anonyme : le client envoie alors un DN vide au serveur LDAP.

36.5.2. Les ACLs

Les ACLs (Access Control Lists) interviennent après la notion de binding. Il sera possible de donner des droits de lecture, d’écriture (ou d’autres droits divers) sur des branches particulières de l’annuaire au compte connecté.

Ceci permet de gérer finement les droits d’accès aux données. Nous verrons plus tard des exemples concrets d’ACLs.

36.5.3. Le chiffrement des communications (SSL/TLS)

Le chiffrement des communications, via SSL (Secure Socket Layer, ou TLS - Transport Layer Security) est également une méthode de protection de l’information. Il est possible, avec la plupart des annuaires existants, de chiffrer le canal de communication entre l’application cliente et l’annuaire. Ceci permet de garantir (un minimum) la confidentialité des données et d’éviter qu’un tiers n’écoute les communications sur le réseau.

36.5.4. SASL

SASL (Simple Authentication and Security Layer) est un mécanisme qui permet d’ajouter des méthodes d’authentification à des protocoles orientés connexion tels que LDAP ou IMAP. Il est défini dans la RFC 2222 ; l’implémentation la plus couramment utilisée est Cyrus-Sasl.

SASL donne la possibilité au client et au serveur de sélectionner quelle sera la méthode d’authentification utilisée. Ces méthodes sont extensibles via des plugins. Il permet également de mettre en place une couche de connexion sécurisée telle que SSL/TLS (sans rapport direct avec le chiffrement indépendant des connexions que nous avons cité ci-dessus).

36.6. Concepts avancés

36.6.1. La réplication

Certains serveurs LDAP, dont OpenLDAP, permettent de manière native, la mise en place d’un annuaire répliqué (entièrement ou partiellement). Un annuaire dit "maître" envoie alors, par le biais du format LDIF, toutes les modifications effectuées sur un annuaire "esclave".

L'avantage d'utiliser cette technique est double :

  • permettre une meilleure montée en charge pour de gros annuaires : il est possible de rediriger le client vers l’un ou l’autre des annuaires répliqués,

  • disposer d’une copie conforme du premier annuaire, utile en cas de crash (attention, toute opération est reportée de l’annuaire maître vers l’esclave, donc ceci est non valable en cas de mauvaise manipulation).

Deux types de réplication existent :

  • le mode "maître-esclave", le plus courant : la réplication est unidirectionnelle, un annuaire maître envoie toutes les modifications à un annuaire esclave. Ceci n’autorise bien évidemment l’écriture que sur l’annuaire maître ; l’esclave est alors disponible uniquement en lecture.

  • le mode "maître-maître" : la réplication est bidirectionnelle, chaque annuaire peut être maître de l’autre. Ceci permet d’écrire indifféremment sur l’un ou l’autre des annuaires.

Sachez enfin qu’il est possible de chaîner les réplications pour obtenir plusieurs réplicats.

36.6.2. La distribution

La distribution est un mécanisme qui va permettre de faire pointer un lien vers un autre annuaire pour une branche particulière. Ceci va permettre de déléguer la gestion de cette branche, un peu au sens DNS lorsqu’on délègue la gestion d’un domaine.

Ce mécanisme peut être représenté de la manière suivante, si l’on reprend l’exemple de notre domaine martymac.com :

Figure 10. Illustration de la situation

Ici, l’annuaire 1 possède un referral pour la branche ou=groups. ce referral pointe vers l’annuaire 2. La gestion de cette branche est donc en quelques sortes "déléguée" à l’annuaire 2.


dn: ou=groups,dc=martymac,dc=com
objectClass: referral
ref: ldap://ldap2.martymac.com/ou=groups,dc=martymac,dc=com

n.b : Il existe également les "alias" qui sont des liens symboliques au sein du même annuaire. Cf. l’objectClass "alias".

36.7. OpenLDAP

OpenLDAP est un projet libre créé en 1998 par "Net Boolean". C'est l'implémentation libre la plus utilisée des annuaires LDAP.

36.7.1. Installation

Pour installer OpenLDAP, il suffit de récupérer deux paquets précompilé (slapd et ldap-utils, respectivement le serveur OpenLDAP et les utilitaires LDAP) via notre gestionnaire de paquets favori :


cvanvinc@pinson ~ $ sudo apt-get install slapd ldap-utils
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances       
Lecture des informations d'état... Fait
[...]

36.7.1.1. Les commandes liées au serveur

La paquet slapd fournit un ensemble de binaires permettant d'interagir avec le serveur OpenLDAP :

  • slapd : le démon OpenLDAP,

  • slurpd : le démon de réplication,

  • slapindex : crée les index au sein de la base,

  • slapcat : effectue un dump (une copie intégrale) de la base,

  • slapadd : ajoute des entrées LDIF dans la base,

  • slappasswd : utilitaire de conversion de mots de passe,

  • slaptest : teste la validité du fichier de configuration slapd.conf,

  • slapdn : teste la conformité d'un DN donné en ligne de commande.

36.7.1.2. Les commandes clientes

La paquet ldap-utils fournit également un ensemble de binaires utilisant le protocole LDAP :

  • ldapsearch : effectue une recherche au sein de l'annuaire,

  • ldapadd : ajoute une entrée,

  • ldapdelete : supprime une entrée,

  • ldapmodify : modifie une entrée (ajoute/supprime un attribut, ajoute/supprime une entrée, etc.),

  • ldapmodrdn : modifie le RDN d'une entrée (renomme une entrée),

  • ldappasswd : modifie le mot de passe d'une entrée LDAP,

  • ldapwhoami : affiche avec quel utilisateur le binding a eu lieu,

  • ldapcompare : permet de comparer l'attribut d’une entrée à une valeur spécifiée.

36.7.2. Configuration du serveur

Le fichier de configuration de du serveur OpenLDAP (slapd) se situe dans le répertoire /etc/ldap.

Voici un exemple de configuration (/etc/ldap/slapd.conf) :


#######################################################################
# Directives globales

# Inclusion des schémas
include			/etc/ldap/schema/core.schema
include			/etc/ldap/schema/cosine.schema
include			/etc/ldap/schema/nis.schema
include			/etc/ldap/schema/inetorgperson.schema

# Où sera stocké le PID du demon
pidfile			/var/run/slapd/slapd.pid

# Liste des arguments passés au démarrage du serveur
argsfile		/var/run/slapd.args

# Niveau de log
loglevel		0

# Emplacement des modules
# Chargement du module BDB (Berkeley DB)
modulepath		/usr/lib/ldap
moduleload		back_bdb

#####################################################################
# Déclaration des options pour le premier type de backend utilisé
# Toutes les options s'y appliquent jusqu'à la prochaine directive
# backend.
#backend		bdb

#####################################################################
#backend   <autre>

#####################################################################
# Déclaration des options de la première "base", c'est à dire de la
# première (et unique ici ) arborescence gerée par notre annuaire
# Toutes les options s'y appliquent jusqu'à la prochaine directive
# database.
database		bdb
checkpoint		512 30

# La racine de notre arborescence
suffix		"dc=martymac,dc=com"

# Le compte administrateur de notre arborescence et son mot de passe
rootdn			"cn=Manager,dc=martymac,dc=com"
rootpw			"secret"

# Ou sont stockés les fichiers BDBs de notre arborescence
directory		"/var/lib/ldap"

# Options d'index
index			objectClass eq

# Sauvegarde de l'heure à laquelle est modifiée une entrée
lastmod			on

# ACLs de notre première arborescence :
# Une personne non authentifiée peut s'authentifier
# Une personne authentifiée peut modifier son propre mot de passe
# Les autres n'ont pas accès à l'attribut mot de passe
access to attrs=userPassword
			by anonymous auth
			by self write
			by ∗ none

# Tout le monde peut lire l'annuaire
			access to ∗
			by ∗ read

#######################################################################
# Autre arborescence
# database <autre>
# suffix	"dc=debian,dc=org"
#[...]

À l'intar de testparm pour Samba, OpenLDAP fournit également une commande, slaptest, qui vérifie la validité du fichier de configuration.


vanvincq@CP2L /etc/ldap $ sudo slaptest -f /etc/ldap/slapd.conf
config file testing succeeded

vanvincq@CP2L /etc/ldap $ sudo /etc/init.d/slapd restart
Stopping OpenLDAP: slapd.
Starting OpenLDAP: slapd.

Le fichier de configuration est subdivisé en trois sections importantes :

  • la section globale (début du fichier),

  • la section concernant les options de backends (débute par "backend"),

  • la section concernant les déclarations et les options des arborescences gérées (débute par "database").

36.7.2.1. L'inclusion des schémas

L’inclusion des schémas est effectuée par la directive "include". Un schéma permet de définir les types de données contenus dans l'annuaire.

Par défaut, OpenLDAP fournit quelques schémas :


vanvincq@CP2L /etc/ldap $ ls /etc/ldap/schema/
collective.schema  core.schema    duaconf.schema      inetorgperson.schema  nis.ldif       openldap.schema  README
corba.schema       cosine.ldif    dyngroup.schema     java.schema           nis.schema     pmi.schema
core.ldif          cosine.schema  inetorgperson.ldif  misc.schema           openldap.ldif  ppolicy.schema

36.7.2.2. Les niveaux de log

Tableau 3. Les niveaux de log disponibles.

ValeurFonction correspondante
1Appels de fonctions
2Gestion des packets
4Trace détaillée
8Gestion des connexions
16Affichage des packets envoyés et reçus
32Gestion des filtres de recherche
64Gestion du fichier de configuration
128Gestion des ACLs
256Affichage des connexions, opérations et résultats
512Affichage des entrées retournées
1024Affichage des communications avec les backends
2048Parsing des entrées

Ces niveaux sont cumulables, c’est à dire qu'un niveau 48 équivaut aux niveaux 16 et 32. Un niveau 0 équivaut à un log désactivé.

Les logs sont gérés par syslog, ce qui signifie que vous pourrez consulter les informations logguées dans le fichier /var/log/syslog.

36.7.2.3. Les backends

Il existe différente sorte de Backend. Les plus couramment utilisés sont :

  • LDBM : ????????????

  • BDB (Berkekey DB) : recommandé car réputé plus robuste que LDBM.

Ces deux Backends sont des bases de données stockées dans des fichiers. Il en existe d'autres qui permettent de stocker les informations dans de véritables SGBD.

36.7.2.4. Les databases

Une section de database représente la déclaration d'une arborescence. Ceci implique plusieurs paramètres, dont une racine, un compte administrateur, etc.

Les paramètres importants de cette sections sont :

  • La racine

    Elle est spécifiée par la directive "suffix". La racine correspond souvent au FQDN (Fully Qualified Domain Name) de la machine associé aux attributs "dc".

    
suffix		"dc=martymac,dc=com"
    
  • L'accès administrateur

    Il est possible de déclarer un compte qui ne sera sujet à aucune limitation (un peu comme "root"). Ce compte peut correspondre ou non à une entrée dans l’annuaire. Il sera purement virtuel si aucun DN n'est effectivement stocké dans l’annuaire.

    Ce compte particulier n’est pas soumis aux restrictions imposées par les ACLs (voir ci-dessous). Il est déclaré par la directive "rootdn". Son mot de passe est spécifié par la directive "rootpw".

    n.b : attention, ne confondez pas "rootdn" et DN racine, qui correspond à la base de notre annuaire ! Ici le "rootdn" est bien le dn d’un utilisateur ayant les droits root...

    Le mot de passe du rootdn peut être soit en clair soit un hash généré par la commande slappasswd. Nous pouvons générer ce hash de cette manière :

    
vanvincq@CP2L ~ $ sudo slappasswd -s "secret" -h {CRYPT}
    {CRYPT}mpGWeJqRe8ka2
    

    La valeur affichée est alors à copier-coller dans la valeur de la directive "rootpw" :

    
rootpw		{CRYPT}mpGWeJqRe8ka2
    
  • Les index

    Les index sont un moyen d’accélérer les recherches au sein de l’annuaire. Dans le fichier de configuration, il convient de préciser quels attributs seront le plus fréquemment utilisés pour les recherches et doivent donc être indexés. Ceci se fait par la directive "index" :

    
index		objectClass eq
    

    Ici, nous activons la gestion des index sur les objectClass, ce qui semble un minimum.

    Chaque index est destiné à faciliter un type de recherche. Le type d'index à créer est ici "eq", ce qui signifie qu'il sera efficace pour une recherche faisant intervenir une égalité stricte de chaînes. Voici une liste des types d'index disponibles et leur type de recherche associé :

    Tableau 4. Les niveaux de log disponibles.

    IndexType de recherche (filtre), exemple
    eq’uid=martymac’, égalité stricte, pas d’utilisation de "wildcard" * (cf. sub)
    sub’uid=marty*’, utilisation d’un wildcard
    subinitialoptimisation de sub pour ’uid=marty*’, wildcard à la fin
    subfinaloptimisation de sub pour ’uid=*mac’, wildcard au début
    subanyoptimisation de sub pour ’uid=*rtym*’, wilcard au début ou à la fin
    approx’uid =martymac’, recherche par approximation sonore
    pres’objectclass=posixAccount’, recherche de présence

    n.b : Le type de recherche effectué est déduit du filtre passé au client qui effectue cette recherche.

    Un ou plusieurs types de recherches peuvent être spécifiés pour un ou plusieurs attributs à la fois. Dans ce cas, la virgule sépare les différents éléments. Exemple :

    
index		uid,gecos,description eq,subinitial
    index		uidNumber,gidNumber eq
    

    Les index doivent être générés par l'administrateur pour être fonctionnels (commande "slapindex").

  • Les listes d'accès (ACLs)

    Les ALCs permettent de définir finement les droits d'accès à l'annuaire. La syntaxe générale des ACLs est la suivante :

    
access to <quoi> [ by <qui> <acces > [ <contrôle> ] ]+
    

    Dans l'exemple précédent, il y a deux ACLs :

    
access to attrs=userPassword
    		by anonymous auth
    		by self write
    		by ∗ none
    access to ∗
    		by * read
    

    La première concerne l’attribut userPassword :

    • on autorise l’accès aux personnes non authentifiées uniquement pour une authentification (by anonymous auth),

    • on autorise une personne authentifiée à modifier son propre mot de passe (by self write),

    • enfin, on refuse l’accès à cet attribut aux autres personnes.

    La seconde ACL concerne toutes les informations contenues dans l’annuaire (*) :

    • on autorise tout le monde à les lire.

    n.b : les ACls sont évaluées dans leur ordre d’apparition dans le fichier de configuration. OpenLDAP arrête leur évaluation lorsqu’il a trouvé une ACL faisant intervenir la cible recherchée. Les directives les plus générales doivent donc être situées après les directives s’appliquant à une cible particulière. C’est le cas ici avec l’ACL ciblant l’attribut userPassword, située avant celle ciblant toute information (*).

    Pour plus de détails, il est utile de consulter la page man de "slapd.access".

36.7.3. Administration du serveur

36.7.3.1. Introduction

Important : les commandes utilisées ici n’utilisent pas le protocole LDAP mais accèdent directement à la base de données sous-jacente (BDB dans notre cas). Il est donc impératif de toujours couper le serveur LDAP avant d’utiliser une commande slap(...), afin d’éviter un accès concurrent depuis le serveur lui-même, ce qui pourrait corrompre la base de données.

Pour arrêter le serveur :


vanvincq@CP2L ~ $ sudo /etc/init.d/slapd stop
Stopping OpenLDAP: slapd.

36.7.3.2. Slapindex

Le serveur est configuré pour qu’il utilise des index ; la première chose à effectuer avant de les utiliser est donc de les générer. Il faut en effet initialiser les index pour qu’OpenLDAP puisse ensuite les utiliser et les maintenir.

L’opération de génération n’est à effectuer qu’une seule fois et ceci se fait par le biais de la commande slapindex.


vanvincq@CP2L ~ $ sudo slapindex

WARNING!
Runnig as root!
There's a fair chance slapd will fail to start.
Check file permissions!

36.7.3.3. Slapcat

Slapcat est une commande très utile au quotidien. Elle effectue un "dump" de la base LDAP au format LDIF. Il est conseillé de l’utiliser régulièrement pour effectuer des sauvegardes d'annuaire.

Par défaut, slapcat affiche les informations sur la sortie standard, il faut donc la rediriger vers un fichier pour obtenir notre sauvegarde :


vanvincq@CP2L ~ $ sudo slapcat > sauvegarde.ldif

vanvincq@CP2L ~ $ cat sauvegarde.ldif
dn: dc=nodomain
objectClass: top
objectClass: dcObject
objectClass: organization
o: nodomain
dc: nodomain
structuralObjectClass: organization
entryUUID: 12da0472-0ee9-1031-8578-ff7c8d5f3ae5
creatorsName: cn=admin,dc=nodomain
createTimestamp: 20120330191954Z
entryCSN: 20120330191954.026871Z#000000#000#000000
modifiersName: cn=admin,dc=nodomain
modifyTimestamp: 20120330191954Z

dn: cn=admin,dc=nodomain
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: admin
description: LDAP administrator
userPassword:: e1NTSEF9SjVnR2NwZTJNci9HaDNrYkVXdFF3aWJMblJLYXprVDc=
structuralObjectClass: organizationalRole
entryUUID: 12da6c78-0ee9-1031-8579-ff7c8d5f3ae5
creatorsName: cn=admin,dc=nodomain
createTimestamp: 20120330191954Z
entryCSN: 20120330191954.029543Z#000000#000#000000
modifiersName: cn=admin,dc=nodomain
modifyTimestamp: 20120330191954Z

36.7.3.4. Slapadd

Slapadd est l’inverse de slapcat. Cette commande permet de peupler notre annuaire en utilisant un fichier LDIF. Elle est typiquement utilisée pour restaurer une sauvegarde effectuée avec slapcat :


vanvincq@CP2L ~ $ sudo slapadd < sauvegarde.ldif
=> hdb_tool_entry_put: id2entry_add failed: DB_KEYEXIST: Key/data pair already exists (-30995)
=> hdb_tool_entry_put: txn_aborted! DB_KEYEXIST: Key/data pair already exists (-30995)
slapadd: could not add entry dn="dc=nodomain" (line=1): txn_aborted! DB_KEYEXIST: Key/data pair already exists (-30995)
_########              44.12% eta   none elapsed            none spd   4.6 k/s 
Closing DB...

36.7.3.5. Arrêt et démarrage du serveur

L’arrêt et le démarrage du serveur LDAP se font par le biais du script /etc/init.d/slapd :


vanvincq@CP2L ~ $ sudo /etc/init.d/slapd start
Starting OpenLDAP: slapd.

36.7.4. Utilisation des outils clients

À la différence des outils slap, les outils ldap utilisent le protocole LDAP, il peuvent donc être mis en oeuvre depuis n’importe quelle machine disposant d’un accès réseau au serveur LDAP. Ils utilisent le format LDIF pour échanger des informations avec le serveur.

36.7.4.1. Ajouter une entrée : ldapadd

Pour ajouter une entrée dans l’annuaire, il faut utiliser la commande ldapadd.

Synopsis simplifié :


ldapadd -W -D <binddn> -x -H ldap://<serveur> -f <fichier.ldif>

L’option "-W" active la demande de mot de passe pour s’authentifier en tant que <binddn>. L’option "-x" permet de ne pas utiliser SASL pour l’authentification. Enfin, le fichier LDIF source doit contenir une (ou plusieurs) entrée(s) à insérer et l’intégralité de ses (leurs) attributs.

Exemple de fichier LDIF à insérer :


dn: uid=dupont , ou=users , dc=martymac , dc=com
objectClass: account
objectClass: posixAccount
cn: dupont
uid: dupont
uidNumber: 10001
gidNumber: 1024
homeDirectory: /home/dupont
userPassword:: e0NSWVBUfXZKblR0TjVSaXQ0Tmc=
loginShell: /bin/sh
gecos: dupont
description: dupont

Insertion de l'entrée


vanvincq@CP2L ~/Bureau $ ldapadd -W -D "cn=Manager,dc=martymac,dc=com" -x -H ldap://localhost -f fichier.ldif
Enter LDAP Password: 
ldap_bind: Invalid credentials (49)

L'entrée est insérée depuis le serveur même (localhost) à partir du compte "Manager" déclaré dans le fichier de configuration. Cette commande ne fonctionnera pas si vous n’avez pas initialisé l’annuaire avec les entrées de base qui ont été vues auparavant : ou=users et dc=martymac,dc=com. Voyons comment créer ces entrées basiques.

36.7.4.2. Initialiser l'annuaire

L’initialisation de l’annuaire n’est qu’un ajout massif de plusieurs entrées. Cet ajout massif peut se faire par le biais de slapadd si on posséde déjà un dump de l’annuaire et si on se situe sur le serveur. À distance, il faut se servir de la commande ldapadd. Il suffit de lui fournir un fichier LDIF contenant plusieurs entrées qui seront ajoutées dans le même ordre avec lequel elles apparaissent dans le fichier.

Ce fichier va donc tout d’abord contenir l’entrée de la racine, qui est nécessaire, puis chacune des "ou" qui ont été vues en exemple. Enfin, les feuilles seront constituées d’utilisateurs et de groupes.

Fichier LDIF à insérer :


dn: dc=martymac,dc=com
objectClass: dcObject
objectClass: organization
dc: martymac
o: martymac
description: martymac

dn: ou=users,dc=martymac,dc=com
objectClass: top
objectClass: organizationalUnit
ou: users

dn: ou=groups , dc=martymac , dc=com
objectClass: top
objectClass: organizationalUnit
ou: groups

dn: cn=utilisateurs,ou=groups,dc=martymac,dc=com
objectClass: posixGroup
cn: utilisateurs
gidNumber: 2000

dn: uid=garfield,ou=users,dc=martymac,dc=com
objectClass: account
objectClass: posixAccount
cn: garfield
uid: garfield
uidNumber: 10001
gidNumber: 2000
homeDirectory: /home/garfield
userPassword:: e0NSWVBUfWRhSDJadHI4dElnZFE=
loginShell: /bin/sh
gecos: garfield
description: garfield

dn: uid=odie,ou=users,dc=martymac,dc=com
objectClass: account
objectClass: posixAccount
cn: odie
uid: odie
uidNumber: 10002
gidNumber: 2000
homeDirectory: /home/odie
userPassword:: e0NSWVBUfTQzZXltaHBSUzBqQVk=
loginShell: /bin/sh
gecos: odie
description: odie

Le fichier ci-dessus comprends :

  • l’entrée de la racine (indispensable)

  • l’entrée des deux ou : users et groups

  • un groupe : utilisateurs

  • deux utilisateurs : garfield et odie appartenant au groupe utilisateurs (attr. gidNumber)

Voici un schéma représentant cette arboresence :

Figure 11. Schématisation de l'arborescence

Avant de pouvoir insérer cette arborescence, une réorganisation s'impose. En effet, actuellement mon fichier de configuration /etc/ldap/slapd.conf n'est pas pris en compte. Je propose que nous repartions du bon pied.

  1. Tout d'abord, on s'assure que la configuration actuelle du fichier /etc/ldap/slapd.conf est correcte et fonctionne :

    
vanvincq@CP2L /etc/ldap $ sudo slaptest -f slapd.conf 
    config file testing succeeded
    
  2. On arrête le daemon afin de pouvoir tranquillement effectuer les modifications :

    
vanvincq@CP2L /etc/ldap $ sudo /etc/init.d/slapd stop 
    Stopping OpenLDAP: slapd.
    
  3. Maintenant, il faut éditer et ajouter au fichier /etc/ldap/slapd.conf les lignes suivantes :

    
# before the first database definition
    database config
    # NOTE: the suffix is hardcoded as cn=config and 
    # MUST not have a suffix directive
    # normal rules apply - rootdn can be anything you want
    # but MUST be under cn=config
    rootdn "cn=admin,cn=config"
    # use any of the supported password formats e.g. {SSHA} etc
    # or plaintext as shown
    rootpw config
    
  4. Au cas où, faisons une sauvegarde du précédent répertoire slapd.d puis créons le notre :

    
vanvincq@CP2L /etc/ldap $ sudo mv slapd.d/ slapd.d.bak
    vanvincq@CP2L /etc/ldap $ sudo mkdir slapd.d
    vanvincq@CP2L /etc/ldap $ sudo chown openldap:openldap slapd.d
    vanvincq@CP2L /etc/ldap $ ls -l
    total 24
    -rw-r--r-- 1 root     root      245 22 nov.   2010 ldap.conf
    drwxr-xr-x 2 root     root     4096 15 juin   2011 sasl2
    drwxr-xr-x 2 root     root     4096  5 avril 23:23 schema
    -rw-r--r-- 1 root     root     2525  9 avril 18:02 slapd.conf
    drwxr-xr-x 2 openldap openldap 4096  9 avril 18:05 slapd.d
    drwxr-xr-x 3 openldap openldap 4096  5 avril 23:23 slapd.d.bak
    
  5. Maintenant, il faut convertir le fichier de configuration actuel au format de la nouvelle version de OpenLDAP, tout en prenant soin de changer également les droits :

    
vanvincq@CP2L /etc/ldap $ sudo slaptest -f slapd.conf -F slapd.d
    config file testing succeeded
    vanvincq@CP2L /etc/ldap $ sudo chown -R openldap:openldap slapd.d/*
    vanvincq@CP2L /etc/ldap $ ls -l slapd.d
    total 8
    drwxr-x--- 3 openldap openldap 4096  9 avril 18:11 cn=config
    -rw------- 1 openldap openldap  927  9 avril 18:11 cn=config.ldif
    
  6. Bon, rien ne marche... .... .. .. . ... Essayons un dpkg-reconfigure alors.


vanvincq@CP2L /etc/ldap $ sudo dpkg-reconfigure slapd
vanvincq@CP2L /etc/ldap $ sudo ldapsearch -x
# extended LDIF
#
# LDAPv3
# base <> (default) with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# search result
search: 2
result: 32 No such object

# numResponses: 1

Alors là, c'est le passage bizarre. Pourquoi n'ai-je rien ? En comparant un peu avec les autres journaux, je suis la même procédure mais rien n'y fait.

A REFAIRE !