Projet

Général

Profil

Actions

Annuaire LDAP

Installation d'OpenLDAP

Documentation:
http://www.openldap.org/doc/admin24 (la doc de référence openldap en anglais)
http://www.zytrax.com/books/ldap/ (en anglais mais très bien pour apprendre)
http://www.vogelweith.com/debian_server/050_openldap.php (pas forcément très à jour)
http://doc.ubuntu-fr.org/openldap-server

Versions utilisées dans le cadre de cette documentation:
Ubuntu 11.04 Natty Narwal / Debian Wheezy
openldap 2.4.23

Approche choisie pour l'installation:
  • utilisation de debconf pour générer un début de conf
  • le strict minimum de configuration à la main dans /etc/ldap/slapd.d
  • utilisation du client lourd Apache Directory Studio pour terminer la configuration et administrer le serveur

L'intérêt d'utiliser précocement un client ldap lourd pour faire la conf est de donner le plus tôt possible à l'utilisateur néophyte une vision globale de l'arborescence ldap, de rendre celle-ci un peu plus facile à appréhender. Les autres docs en ligne exploitent davantage les outils ldap de base en ligne de commande (slapadd, fichiers ldif, etc), et peuvent sembler encore plus absconses quand on a pas l'habitude d'OpenLDAP.

Note:
  • dans openldap, SHA signifie SHA1
  • dans openldap, SSHA signifie Seeded SHA1 (un salt en plus)

Installation du package / debconf

Note: il semble raisonnable de ne pas ouvrir le LDAP sur l'extérieur tant que l'on a pas terminé son installation, la configuration des ACL et celle de TLS.

sudo apt-get install slapd ldap-utils
Debconf:
  • Please enter the password for the admin entry in your LDAP directory.
    -> saisir n'importe quoi à ce stade. ce mdp sera écrasé par le suite

Debconf a créé un début de configuration pour openldap, ainsi qu'un annuaire basé sur le fqdn du système, qui ne va pas convenir à nos besoins.

Configuration d'openldap

http://www.openldap.org/doc/admin24/slapdconf2.html

Description

Le LDAP a une structure arborescente.
La racine s'appelle le root DSE (root directory specific entry).

Juste en dessous du DSE, deux sous-arbres identifiés par leur Distinguished Name:

  • DN="cn=config": la configuration d'OpenLDAP, organisée de manière arborescente, avec la conf des backends de données, avec les schémas de données installés, la réplication, etc. Problème: l'install debian n'a pas défini de compte admin pour cette branche du LDAP. On ne peut donc pas encore y accéder avec un client LDAP. Par contre, cette branche de l'annuaire est stockée au format ldif dans /etc/ldap/slapd.d et elle est modifiable à froid.
  • DN="o=ILLYSE,l=Villeurbanne,st=RHA,c=FR": l'annuaire d'Illyse. Les données, avec les comptes d'utilisateurs, les groupes, etc. Cette branche de l'annuaire est stockée dans une base HDB sous /var/lib/ldap. Problème: debconf n'a pas généré un "contexte de nommage" convenable pour cette branche: les objets ont des noms (DN) se terminant en "dc=xxx,dc=yyy" (en fonction du fqdn du serveur) au lieu de "o=ILLYSE,l=Villeurbanne,st=RHA,c=FR". Il faut corriger cela sous /etc/ldap/slapd.d également.

Note: le choix du contexte de nommage en o=ILLYSE,l=Villeurbanne,st=RHA,c=FR permet d'avoir une cohérence entre les noms (DN) des objets du ldap et les noms (DN) des certificats issus de la PKI. Cela facilite l'utilisation conjointe du ldap et de la PKI pour faire de l'authentification forte. (Pour en savoir plus: http://en.wikipedia.org/wiki/Directory_information_tree - ici, on a fait le choix de tout aligner sur la structure par défaut des DN dans openssl. On aurait à priori pu choisir une autre structure et adapter la configuration d'openssl.)

Configuration de base dans /etc/ldap/slapd.d

Permettre l'accès à cn=config

Il faut ajouter un DN de login et un mot de passe dans le fichier ldif définissant le backend pour la branche cn=config. On utilise slappasswd pour calculer un hachage.

sudo /etc/init.d/slapd stop
lemur@rigel:/etc/ldap/slapd.d$ slappasswd
New password:
Re-enter new password:
{SSHA}foobarEbUllsH1tolnl8CXbUllsH1tFi
sudo vi /etc/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif

Modifier la ligne olcRootDN et ajouter la ligne olcRootPW, avec le hachage produit par slappasswd:

olcRootDN: cn=admin,cn=config
olcRootPW: {SSHA}foobarEbUllsH1tolnl8CXbUllsH1tFi

sudo /etc/init.d/slapd start

Il est maintenant possible de se connecter au LDAP en tant que cn=admin,cn=config et de modifier la configuration du serveur.

Correction du contexte de nommage

Le fichier slapd.d/cn=config/olcDatabase={1}hdb.ldif définit le backend pour la branche du ldap contenant les données. Il est nécessaire de le corriger pour passer au contexte de nommage o=ILLYSE,l=Villeurbanne,st=RHA,c=FR

sudo /etc/init.d/slapd stop
sudo vi /etc/ldap/slapd.d/cn=config/olcDatabase\=\{1\}hdb.ldif

Modifier les lignes suivantes (il s'agit essentiellement de remplacer les occurrences de dc=xxx,dc=yyy par o=ILLYSE,l=Villeurbanne,st=RHA,c=FR et de définir un mot de passe admin)

olcSuffix: o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by cn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write by * none
olcAccess: {2}to * by self write by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write by * read
olcRootDN: cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
olcRootPW: {SSHA}foobarEbUllsH1tolnl8CXbUllsH1tFi

Utiliser le même hachage de mot de passe que précédemment pour olcRootPW.

Note: les lignes sont coupées à 78 caractères par défaut dans les fichiers LDIF. Pour faciliter l'édition, il n'est pas gênant de joindre les lignes fractionnées (pour les olcAccess, notamment). slapd saura quand même les lire.

Note: on pourrait avoir des mdp différents pour l'administrateur de la configuration (cn=admin,cn=config) et pour celui des données (cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR). En pratique, sur un serveur en prod, on peut même ne pas définir du tout les comptes administrateurs, et faire les modifs en ligne de commande.

Purger la base HDB initialement créée par debconf. Openldap recréera une base vierge au redémarrage de slapd.

sudo rm /var/lib/ldap/*

sudo /etc/init.d/slapd start

Connexion avec Apache Directory Studio

http://directory.apache.org/studio/downloads.html

Note: pour le moment, la branche o=ILLYSE,l=Villeurbanne,st=RHA,c=FR est encore vide.

A ce stade, avec les ACL par défaut (stockées sous cn=admin), il existe trois niveaux d'accès:

  • anonyme: accès en consultation à tout o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, à l'exception des attributs sensibles (hachages de mots de passe). Dans DS, choisir Pas d'authentification sur l'onglet Authentification de la fenêtre de connexion.
  • admin o=ILLYSE,l=Villeurbanne,st=RHA,c=FR: accès complet à o=ILLYSE,l=Villeurbanne,st=RHA,c=FR. Dans DS, choisir Authentification simple et se connecter en tant que cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR avec le mdp.
  • admin cn=config: accès complet à la configuration d'openldap, ainsi qu'à o=ILLYSE,l=Villeurbanne,st=RHA,c=FR. Dans DS, choisir Authentification simple, se connecter en tant que cn=admin,cn=config avec le mdp, et sur l'onglet Options du navigateur, choisir cn=config comme DN de base.

Maintenant qu'on dispose d'un accès facile à cn=config, on peut commencer la configuration proprement dite.

Configuration

Se connecter en tant que cn=admin,cn=config.

Interdiction des connexions anonymes / restriction des droits des users authentifiés

En tant que cn=admin,cn=config.

http://www.openldap.org/doc/admin24/access-control.html

L'objet qui définit le backend de stockage pour la branche o=ILLYSE,l=Villeurbanne,st=RHA,c=FR est olcDatabase={1}hdb,cn=config.

Les ACL de base régissant l'accès à la branche o=ILLYSE,l=Villeurbanne,st=RHA,c=FR se trouvent dans les attributs olcAccess de cet objet.

Valeur par défaut des attributs olcAccess de olcDatabase={1}hdb,cn=config

olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write by * read

Un minimum d'explication de texte s'impose:

Première ligne: concerne spécifiquement les attributs d'authentification ("to attrs=userPassword,shadowLastChange")
  • by self write: un user authentifié a le droit de changer son propre mot de passe
  • by anonymous auth: une connexion non authentifiée peut y accéder, mais uniquement dans le cadre du process d'authentification (permet le login)
  • by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write: droit en écriture pour l'administrateur de la branche o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
  • by * none: aucun accès pour le reste du monde

Deuxième ligne: je ne suis pas encore certain de la signification de dn.base="" mais cette ligne est nécessaire à l'authentification SASL.

Troisième ligne: concerne l'ensemble de l'annuaire o=ILLYSE,l=Villeurbanne,st=RHA,c=FR ("to *")
  • by self write: un user authentifié peut modifier sa propre entrée dans l'annuaire
  • by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write: l'admin accède à tout en écriture
  • by * read: accès en lecture à tout le monde (y compris les connexions non authentifiées). On va changer ça tout de suite.

Les clauses des ACL sont évaluées dans l'ordre. L'évaluation s'arrête à la première clause qui matche.

On modifie ces ACL pour interdire la consultation anonyme et limiter les droits des utilisateurs authentifiés.

Configuration modifiée

olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR" write by users none by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by users none by * none

Désormais, les connexions anonymes (by anonymous, by *) n'ont plus accès qu'à la procédure d'authentification.
Les utilisateurs authentifiés n'ont accès (en lecture/écriture) qu'à leur propre entrée dans le ldap (by self write / by users none).

Indexation

En tant que cn=admin,cn=config.

Certains attributs sont indexés pour accélérer les recherches dans l'annuaire. On spécifie les attributs habituellement indexés dans olcDatabase={1}hdb,cn=config.
=>modifier l'attribut olcDbIndex de olcDatabase={1}hdb,cn=config:

olcDbIndex: objectclass,entryCSN,uid,cn,entryUUID eq

Cette ligne signifie que les attributs objectclass, entryCSN, uid, cn et entryUUID seront indexés pour l'opérateur d'égalité.

Note: attributs indexés au 17/1/2012 (pour référence - nécessite des schémas de données qui ne sont pas installés à ce stade)

olcDbIndex: objectclass,entryCSN,uid,cn,entryUUID,mail,dlzType eq

Il faut maintenant exécuter slapindex (à froid) en tant que openldap pour mettre à jour l'indexation.

sudo /etc/init.d/slapd stop
su - openldap -s /bin/bash
/usr/sbin/slapindex
# ou sudo -u openldap slapindex -v
#indexing id=00000001
#indexing id=00000002
#indexing id=00000003
# ...

sudo /etc/init.d/slapd start

StartTLS

En tant que cn=admin,cn=config.

http://www.openldap.org/doc/admin24/tls.html

Produire un certificat pour le serveur LDAP en utilisant la PKI.
Spécificités concernant la génération des certificats LDAP: ldap-pki

Note: la clé privée du certificat du serveur LDAP ne doit pas être protégée par mot de passe. Openldap ne le gère pas.

Stockage des certificats (CA+serveur LDAP) et de la clé:

lemur@rigel:/etc/ldap$ ls -al *.crt *.key
-rw-r--r-- 1 openldap openldap 1797 2011-10-16 23:05 ca.crt
-rw-r--r-- 1 openldap openldap 5649 2011-10-17 11:21 ldap0.illyse.org.crt
-rw------- 1 openldap openldap 1679 2011-10-17 11:21 ldap0.illyse.org.key

Note/FIXME: on doit pouvoir faire mieux pour les droits sur la clé, en ajoutant openldap au groupe ssl-cert.

Se connecter cn=admin,cn=config, afficher l'objet cn=config (et non plus olcDatabase={1}hdb), et ajouter les attributs suivants:

olcTLSCACertificateFile: /etc/ldap/ca.crt
olcTLSCertificateFile: /etc/ldap/ldap0.illyse.org.crt
olcTLSCertificateKeyFile: /etc/ldap/ldap0.illyse.org.key
olcTLSVerifyClient: allow

sudo /etc/init.d/slapd restart

On peut maintenant se connecter à l'annuaire avec StartTLS sur le port 389.
=> modifier les connexions dans Apache Directory Studio

l'attribut olcTLSVerifyClient=allow signifie que l'on peut s'authentifier en utilisant un certificat client, mais que ce n'est pas exigé par le serveur. Les connexions avec du simple chiffrement TLS restent autorisées. Forcer l'authentification forte rendrait le ldap difficile à exploiter depuis la plupart des clients/services. Elle sera toutefois employée dans le cadre de la réplication entre serveurs LDAP, entre autres pour éviter de laisser des mots de passe en clair dans la configuration.

ldaps (optionnel)

En tant que cn=admin,cn=config.

Certains services n'implémentent pas le chiffrement StartTLS, mais plutôt ldaps (SSL).

Il faut l'activer dans /etc/default/slapd en ajoutant ldaps:/// à la ligne SLAPD_SERVICES:

sudo vi /etc/default/slapd

# slapd normally serves ldap only on all TCP-ports 389. slapd can also
# service requests on TCP-port 636 (ldaps) and requests via unix
# sockets.
# Example usage:
# SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:/// ldapi:///" 
SLAPD_SERVICES="ldap:/// ldaps:/// ldapi:///" 
sudo /etc/init.d/slapd restart

On peut maintenant se connecter à l'annuaire avec ldaps sur le port 636.

Copies d'écran dans ADS

Modification des ACL

On va maintenant modifier les ACL pour forcer les connexions chiffrées. (On ne peut empêcher complètement les connexions sans chiffrement/authentification, mais on fait en sorte que ces connexions n'aient aucun droit sur l'annuaire, pas même en consultation.)
Pour cela, on utilise le Security Strength Factor (SSF) en ajoutant "ssf=128" devant les portions des ACL indiquant à qui s'applique tel ou tel droit.

Au passage, on supprime les références à cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR: ce dn étant défini dans olcDatabase={1}hdb,cn=config par l'attribut olcRootDN, ses droits administrateur sont implicites.

Configuration modifiée

olcAccess: {0}to attrs=userPassword,shadowLastChange by ssf=128 self write by anonymous auth by users none by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by ssf=128 self write by users none by * none

FIXME: passer à ssf=256 si possible. A ce jour, lorsqu'on se connecte avec un certificat client, on obtient seulement ssf=128, ce qui suggère que l'on pourrait utiliser de meilleurs algos de chiffrement (au niveau de la PKI?). A creuser.

Peuplement de l'annuaire

La configuration terminée, on peut maintenant se consacrer aux données.
On privilégiera désormais les connexions TLS.

Création de la racine des données

Se connecter en tant que cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR.

Pour l'instant, la branche de données de l'annuaire est encore vide. On va maintenant créer sa première entrée, o=ILLYSE,l=Villeurbanne,st=RHA,c=FR. Cette entrée est dite context entry. Elle définit le contexte de nommage de la branche des données, dont elle est la racine.

Dans Apache Directory Studio, clic-droit sur l'objet Root DSE / Nouveau / Nouvelle context entry.
Une boite de dialogue apparaît. Choisir:
  • créer l'entrée à partir de zéro
  • object class: organization (la classe top est ajoutée automatiquement au passage)
  • DN de la context entry: o=ILLYSE,l=Villeurbanne,st=RHA,c=FR

Unités organisationnelles

En tant que cn=admin,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR.

Habituellement, les données sont organisée en plusieurs Organizational Units. Ce sont les branches principales de l'annuaire. Cette organisation peut posséder plusieurs niveaux.

Pour créer une structure classique, nous allons créer dans l'arborescence, sous l'objet parent o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, deux nouveaux objets de classe organizationalUnit.

Pour créer ces deux objets dans Apache Directory Studio, clic-droit sur o=ILLYSE,l=Villeurbanne,st=RHA,c=FR / Nouveau / Nouvelle entrée.
  • créer l'entrée à partir de zéro
  • classe organizationalUnit. La classe parente top est automatiquement ajoutée.
  • RDN=ou. Cela définit la "clé" de l'objet qui fera partie de son nom complet, le DN (Distinguished Name, par exemple "ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR").
  • ou: groups ou users, voir ci-dessous

Exports LDIF:

  • Comptes d'utilisateurs
    dn: ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
    objectClass: organizationalUnit
    objectClass: top
    ou: users
    

Une fois la première unité organisationnelle créée, ADS offre la possibilité de l'utiliser comme modèle pour créer la suivante.
On peut aussi faire un simple copier-coller dans l'arborescence. ADS proposera de renommer l'objet collé.

  • Groupes
    dn: ou=groups,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
    objectClass: organizationalUnit
    objectClass: top
    ou: groups
    

Ultérieurement, on pourra créer d'autres unités organisationnelles à la racine de l'annuaire, pour stocker les zones DNS, le routage du courrier électronique, la config DHCP, etc.

Note/nomenclature: j'ai arbitrairement et unilatéralement décidé de bannir les majuscules des DN de l'annuaire. P.-A.

Premier utilisateur
Sous ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, on crée un nouvel objet:
  • classes inetOrgPerson et shadowAccount (les autres sont ajoutées automatiquement)
  • RDN=cn (la clé)
  • uid=jdupont
  • cn=jdupont
  • sn=Dupont
    (clic-droit/nouvel attribut)
  • givenName=Jean
    (clic-droit/nouvel attribut)
  • displayName=Jean Dupont
    (clic-droit/nouvel attribut)
  • userPassword: l'interface de DS permet de générer un hachage (équivalent de slappasswd en ligne de commande). On utilisera l'algorithme SSHA.

Cet objet est laissé intentionnellement minimaliste. Il sera possible d'ajouter ultérieurement d'autres attributs et classes, selon les besoins.

LDIF

dn: cn=jdupont,ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: jdupont
sn: Dupont
uid: jdupont
displayName: Jean Dupont
givenName: Jean
userPassword:: e1A5Eb8...

Premier groupe
Sous ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, on crée un nouvel objet:
  • classe posixGroup
  • RDN=cn
  • cn=admin
  • gidNumber=99 (peu importe, pour l'instant on ne cherche pas a créer des utilisateurs unix)

Pour ajouter l'utilisateur au groupe, afficher l'entrée que l'on vient de créer (cn=admin,ou=groups,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR) et ajouter un nouvel attribut (clic-droit...) memberUid=jdupont.

LDIF

dn: cn=admin,ou=groups,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR
objectClass: posixGroup
objectClass: top
cn: admin
gidNumber: 99
memberUid: jdupont

Test

Il est maintenant possible de se connecter en tant que uid=jdupont,ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, (fabs : j'ai utilisé cn=jdupont,ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR car ca ne marchait pas avec uid) avec le mot de passe saisi, et le contrôle d'accès est bien appliqué:

  • on peut modifier ses propres données personnelles (nom, prénom, mdp, etc...) (nécessite de forcer le DN de base à cn=jdupont,ou=users,o=ILLYSE,l=Villeurbanne,st=RHA,c=FR, dans la fenêtre de connexion d'ADS, onglet Options du navigateur).
  • on ne voit pas le reste de l'annuaire

Copie d'écran dans ADS

Mis à jour par Pierre-Arnaud Poudret il y a presque 11 ans · 2 révisions