Configuration des ACL dans l’annuaire de démonstration
La configuration des ACL dans un annuaire OpenLDAP peut s’effectuer également de deux façons : par le fichier "slapd.conf" ou via la méthode en ligne (OLC) en modifiant à chaud le DIT de configuration (cn=config) avec l’utilisation de la commande LDAP modify ou avec l’aide d’un navigateur LDAP.
La méthode en ligne (OLC) sera privilégiée pour le déploiement des ACL en modifiant ou en ajoutant l’attribut olcAccess provenant de la classe d’objet olcDatabaseConfig chargée par le schéma de base de l’application.
Cet attribut devra se positionner dans le DIT de configuration (cn=config) et plus précisément dans les entrées de l’annuaire de type olcDatabaseConfig.
L’annuaire LDAP créé et configuré précédemment possédera les différents DIT listés dans la figure 11-1. Il s’y trouvera les deux DIT par défaut que sont le "frontend" et le "config", et le DIT créé pour y stocker les données propres à l’exploitation des utilisateurs de l’entreprise.
ldapsearch -h localhost -D cn=config -W -b "cn=config" -s one  
objectclass=olcDatabaseConfig objectClass -LL 
Enter LDAP Password: 
 
dn: olcDatabase={-1}frontend,cn=config 
objectClass: olcDatabaseConfig 
objectClass: olcFrontendConfig 
 
dn: olcDatabase={0}config,cn=config 
objectClass: olcDatabaseConfig 
 
dn: olcDatabase={1}bdb,cn=config 
objectClass: olcDatabaseConfig 
objectClass: olcBdbConfig
Figure 11-1 : Liste des DIT de l’annuaire de démonstration
1. Configuration des ACL standard
À cet instant, aucune ACL n’a été placée dans ces différents DIT, cela signifie donc que l’ACL de base globale à savoir "lecture pour tout le monde sur la totalité de l’annuaire" (to * by * read) est appliquée, et ceci peut (et doit) être changé.
1.	Il faut donc commencer par interdire l’accès à tous les utilisateurs de visualiser le DIT de configuration (cn=config) en appliquant l’ACL suivante au niveau de l’entrée : dn: olcDatabase={0}config,cn=config.	
Exemple
dn: olcDatabase={0}config,cn=config 
objectClass: olcDatabaseConfig 
olcDatabase: {0}config 
olcAccess: {0}to *  by * none 
. . .
2.	Ensuite, il faudra sécuriser le DIT de l’entreprise (ex. dc=exemple, dc=com) afin que le changement des mots de passe ne puisse s’effectuer que par l’utilisateur lui-même et que ces mêmes mots de passe ne puissent être seulement utilisés par tous les utilisateurs de l’annuaire qu’à des fins d’authentification.	
Exemple
dn: olcDatabase={1}bdb,cn=config 
objectClass: olcBdbConfig 
objectClass: olcDatabaseConfig 
olcDatabase: {1}bdb 
olcDbDirectory: /var/lib/ldap 
olcAccess: {0}to attrs=userPassword by self write by * read 
...
2. Cloisonnement de l’annuaire par client
Il s’agira ensuite de positionner des ACL afin de faire en sorte que tous les clients LDAP (serveur, application) d’un même client du Datacenter ne puissent authentifier que des utilisateurs de ce client. Ceci afin de ne surtout pas avoir le cas de figure d’un utilisateur du clientA qui pourrait se connecter à un serveur du clientB.
¬
Cependant, cette problématique ne devrait pas se produire étant donné que chaque client accédera à ses propres serveurs par le biais de VPN et de règles de pare-feu qui rendent inaccessible l’accès aux serveurs d’un autre client. Mais on ne sait jamais et il vaut mieux s’en prémunir en cas par exemple d’une défaillance de la configuration du réseau ou du pare-feu.
La figure 11-2 permet de schématiser le résultat attendu. Mais pour le comprendre, il faut bien se rappeler qu’un client LDAP tel qu’un serveur, un équipement réseau ou bien une application se connectera à l’annuaire grâce à un utilisateur de liaison afin d’y rechercher par exemple un utilisateur qui tentera de se connecter sur celui-ci. Ainsi, il serait envisageable de créer un utilisateur de liaison par catégorie de client qui pourrait être par exemple :
	•	cn=device,ou=binds,ou=clientA,...,dc=exemple,dc=com pour les équipements matériels.
	•	cn=linux,ou=binds,ou=clientA,...,dc=exemple,dc=com pour les serveurs Linux.
	•	cn=sudo,ou=binds,ou=clientA,...,dc=exemple,dc=com pour le programme ’sudo’.
	•	...
Ainsi, les utilisateurs de liaison cn=device et cn=linux utilisés par les clients LDAP de type serveur et équipement matériel disposeront seulement d’autorisations de lecture, recherche et comparaison à partir de la branche ou=utilisateur et ou=group afin d’authentifier des utilisateurs. En revanche, le programme "sudo" par le biais de l’utilisateur de liaison cn=sudo, ne devra avoir accès en lecture, recherche et comparaison qu’à l’entrée cn=sudoers pour consulter ses configurations.
¬
À rappeler que l’utilisateur "rootdn" de l’annuaire n’a pas besoin de se voir attribuer d’ACL. Il reste maître de toutes les entrées de son annuaire.
¬
Figure 11-2 : Cloisonnement de l’annuaire de démonstration
Suivant les directives précédemment énoncées, voici un exemple de mise en œuvre des ACL :
dn: olcDatabase={1}bdb,cn=config 
objectClass: olcBdbConfig 
objectClass: olcDatabaseConfig 
olcDatabase: {1}bdb 
olcDbDirectory: /var/lib/ldap 
olcAccess: {0}to attrs=userPassword by self write by * read 
olcAccess: {1}to dn.subtree="ou=utilisateur,ou=clientA,...,dc=exemple,dc=com" 
by dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
by dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
olcAccess: {2}to dn.subtree="ou=group,ou=clientA,...,dc=exemple,dc=com" 
by dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
by dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
olcAccess: {3}to dn.subtree="cn=sudo,cn=applications,ou=clientA,...,dc=exemple,dc=com" 
by dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
[olcAccess: {4}to *  by * none]
¬
Rappel : la dernière ACL n’est pas à rajouter, car elle est implicite et permet ainsi de débloquer le contenu de l’annuaire à quiconque en dehors des règles qui ont été fixées précédemment.
3. Pour aller plus loin dans le cloisonnement
Cependant, la configuration de cloisonnement précédente, bien que restrictive, offre la possibilité à tous les utilisateurs du ClientA d’accéder à tous les clients LDAP de celui-ci parmi lesquels se trouvent des systèmes d’exploitation, des équipements réseau ou bien même des applications.
Car en effet, même si au niveau de l’annuaire LDAP il est possible de configurer des groupes pour classer les utilisateurs par équipe, il n’y a rien au niveau des clients LDAP de configurable pour interdire l’accès à tel ou tel groupe. Ceux-ci se révèlent utiles seulement ultérieurement dans le cadre de configuration de permissions (par exemple, sur un système) ou de configuration applicative (par exemple, le programme sudo).
Ainsi, cela implique qu’un administrateur système sera capable de se connecter à un équipement réseau alors qu’il ne devrait pas y être autorisé, ou bien qu’un utilisateur d’une application spécifique pourra se connecter à tous les serveurs de l’entreprise.
Pour ce faire, il va donc falloir utiliser de manière ’ingénieuse’ les ACL, mais aussi créer autant d’utilisateurs de liaison qu’il sera nécessaire afin d’obtenir les cloisonnements désirés.
En effet, si le but consiste à cloisonner les équipes applicatives, système et réseau, alors il faudra créer trois utilisateurs de liaison différents qui seront configurés sur chaque type de client LDAP. Et si les applications ont besoin également d’être cloisonnées, il faudra bien entendu en créer autant que nécessaire. Le tableau suivant montre, par exemple, l’attribution d’utilisateurs de liaison par nature de client LDAP.
Utilisateur de liaison	Nature du client LDAP	
dn: cn=linux,ou=bind, ou=clientA,...,dc=exemple,dc=com	Linux RHEL	
dn: cn=device,ou=bind, ou=clientA,...,dc=exemple,dc=com	Équipement hardware de type Routeur	
dn: cn=device,ou=bind, ou=clientA,...,dc=exemple,dc=com	Équipement hardware de type Switch	
dn: cn=sudo,ou=bind, ou=clientA,...,dc=exemple,dc=com	Programme sudo	
dn: cn=op5,ou=bind, ou=clientA,...,dc=exemple,dc=com	Application de monitoring (OP5)	
…	. . .	
Dès lors que les différents clients LDAP seront configurés avec chacun des utilisateurs de liaison, il faudra ensuite sélectionner les utilisateurs de l’entreprise qui seront identifiables par chacun des utilisateurs de liaison. Pour ce faire, il serait simple d’utiliser les informations des groupes mais durant l’authentification d’un utilisateur à son client LDAP, seules les informations contenues dans l’entrée de l’utilisateur sont utilisées. Ainsi, il faudra donc se servir d’un attribut contenant une information qui sera en corrélation avec son groupe et donc, en quelque sorte, d’un attribut faisant office « d’étiquette » qui servira de filtre. Par exemple, l’attribut description peut contenir la valeur SYSADMIN si l’utilisateur fait partie de l’équipe d’administrateur système de l’entreprise ou bien NETADMIN si l’utilisateur est un membre de l’équipe réseau. L’ajout de cet attribut doit donc être réalisé manuellement ou automatiquement à l’aide d’un script ou d’une infrastructure dédiée au peuplement de l’annuaire.
L’exemple précédent peut donc être complété comme ci-dessous :
Utilisateur de liaison	Valeur identifiable	
dn: cn=linux,ou=bind, ou=clientA,...,dc=exemple,dc=com	SYSADMIN	
dn: cn=device,ou=bind, ou=clientA,...,dc=exemple,dc=com	NETADMIN	
dn: cn=device,ou=bind, ou=clientA,...,dc=exemple,dc=com	NETADMIN	
dn: cn=sudo,ou=bind, ou=clientA,...,dc=exemple,dc=com	SUDOADMIN	
dn: cn=op5,ou=bind, ou=clientA,...,dc=exemple,dc=com	OP5ADMIN	
…	. . .	
Et ensuite, il faut configurer les ACL comme dans l’exemple ci-dessous :
Exemple
olcAccess: {0}to attrs=userPassword by self write by * read 
 
olcAccess: {1}to 
dn.subtree=ou=utilisateur,ou=clientA,...,dc=exemple,dc=com 
filter=(description=OP5ADMIN) by 
cn=cn=op5,ou=bind,ou=clientA,...,dc=exemple,dc=com read by * break 
 
olcAccess: {2}to 
dn.subtree=ou=utilisateur,ou=clientA,...,dc=exemple,dc=com 
filter=(description=NETADMIN) by 
dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read by * break 
 
olcAccess: {3}to 
dn.subtree=ou=utilisateur,ou=clientA,...,dc=exemple,dc=com 
filter=(description=SYSADMIN) by 
dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read by * break 
 
olcAccess: {4}to 
dn.subtree=ou=groups,ou=clientA,...,dc=exemple,dc=com by 
dn=cn=op5,ou=bind,ou=clientA,...,dc=exemple,dc=com read by 
dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read by 
dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
 
olcAccess: {5}to * by 
dn=cn=op5,ou=bind,ou=clientA,...,dc=exemple,dc=com search by 
dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com search by  
dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com search 
 
olcAccess: {6}to 
dn.subtree="cn=sudo,cn=applications,ou=clientA,...,dc=exemple,dc=com" 
by dn=cn=linux,ou=bind,ou=clientA,...,dc=exemple,dc=com read 
 
. . . 
 
[olcAccess: {X}to *  by * none]
En effet, afin de s’assurer que seuls les utilisateurs contenant une description avec une valeur NETADMIN seront autorisés à se connecter aux équipements réseau (switch et routeurs) via l’utilisateur de liaison cn=device,..., il faudra entrer la règle ACL suivante :
dn.subtree="ou=utilisateur,ou=clientA,...,dc=exemple,dc=com" 
filter=(description=NETADMIN) 
by dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read
Cependant, cette ACL est incomplète car elle pose problème dans le cas où un utilisateur possède deux fonctions avec deux valeurs pour l’attribut description. En effet, si un utilisateur possède les valeurs OP5ADMIN et NETADMIN, alors il ne sera jamais authentifiable sur un équipement réseau car l’utilisateur de liaison cn=device sera rejeté par la première règle olcAccess: {1}. Celle-ci trouvera l’entrée de l’utilisateur avec la valeur OP5ADMIN et comme l’utilisateur de liaison ne sera pas cn=op5, elle ne sera donc pas autorisée en ’lecture’ par l’utilisateur de liaison cn=device. Ceci étant tout simplement dû à la règle implicite qui s’ajoute à la fin de chaque ACL : [by * none ].
Afin d’outrepasser ce comportement par défaut et de permettre le traitement des ACL suivantes, Openldap offre la possibilité de casser le traitement de l’ACL en cours pour passer à la suivante.
Ainsi, la configuration définitive sera la suivante :
dn.subtree="ou=utilisateur,ou=clientA,...,dc=exemple,dc=com" 
filter=(description=NETADMIN) 
by dn=cn=device,ou=bind,ou=clientA,...,dc=exemple,dc=com read by * break
¬
L’attribut description est multi-valeur. Et dans notre implémentation, il est indispensable d’utiliser ce type d’attribut.
La figure 11-3 permet d’illustrer la façon dont les clients LDAP pourront filtrer, ou autrement dit, sélectionner les utilisateurs étant autorisés à s’y connecter.
¬
Cloisonnement de l’annuaire avancé
Ainsi, dans l’exemple ci-dessus, l’utilisateurA sera capable de se connecter seulement sur les équipements réseau alors que l’utilisateurZ pourra se connecter à la fois sur les équipements réseau et sur les serveurs Linux. En revanche, l’utilisateurB ne pourra ni se connecter sur les équipements réseau, ni sur les serveurs Linux.
¬
Le sens des flèches permet de bien comprendre que les ACL autorisent les clients LDAP à ne voir que les utilisateurs présentant les "étiquettes" correspondant à leur rôle. Ainsi, l’utilisateurZ pourra en réalité se connecter au serveur Linux, car seul l’utilisateur de liaison du serveur Linux sera capable de le voir.
Il est possible de tester la configuration de ce ’cloisonnement’ par ACL avec une simple commande ldapsearch.
Exemple
[root@ldap01Desktop]# ldapsearch -h localhost -D 
"cn=device,ou=binds,ou=clientA,…,dc=exemple,dc=com " -w "xxx" -b 
"ou=utilisateur,ou=clientA,…,dc=exemple,dc=com" -s sub 
objectclass=* -LLL 
 
dn: uid=userA,utilisateur,ou=clientA,…,dc=exemple,dc=com 
. . . 
uid: userA 
userPassword:: e1NBU0x9c3JvcGFyc0BnZW1hbHRvLmNvbQ== 
description: NETADMIN 
 
dn: uid=userZ,utilisateur,ou=clientA,…,dc=exemple,dc=com 
. . . 
uid: userZ 
userPassword:: e1NBU0x9c3Rlbm91QGdlbWFsdG8uY29t 
description: SYSADMIN 
description: NETADMIN