2.2.1 systèmes d'exploitation Windows
Windows NT: l'information est disséminée dans plusieurs outils et bases de données (gestionnaires de serveurs, gestionnaire wins, gestionnaire des utilisateurs …). Windows 2000: l'ensemble est regroupé dans un annuaire propriétaire ; Active Directory, mais compatible avec le protocole LDAP, il sera donc possible d'y accéder en lecture/écriture via LDAP grâce notament à l'interface de programmation ADSI.
2.2.2 Novell NDS
Novell à rendu son système d'annuaire indépendant du système d'exploitation (Netware). Novell Directory Service est un annuaire object disponible sur Netware, Solaris et Windows. Il supporte le standard LDAP v3 et les données au format LDIF ( Ldap Data Interchange Format, format texte de données d'import/export dans un annuaire LDAP ).
2.2.3 NIS
Dès 1985 Sun à introduit le Network Information Service, déjà destiné à centraliser l'administration des informations système. Les informations sont stockées sous forme de map (table de correspondance entre une clé et une valeur: clé titan , valeur 192.163.12.43) dans de simples bases indexées (db, dbm …), accessibles par des appels RPC (Remote Procedure Call). Dans un premier temps les map s'ajoutaient aux fichiers locaux (ajout d'un caractère + dans le fichier concerné pour rediriger la recherche vers les nis, remarque: depuis solaris 2 ce signe n'a plus cet effet. Avec solaris 2 et toutes ses sources d'information système (dns, nis+ …) il devenait difficile de programmer dans chaque service ou utilitaire système, le mode de recherche. Sun a créé une API qui se place entre ces programmes et les différentes sources d'information sur lesquelles ils s'appuient, cette API est le Name Service Switch. Avec cette API les programmes n'ont plus a connaître les détails d'implémentation des services d'information qu'ils contactent. Les appels à cette API sont du type getXbyY (gethostbyname), lisent le fichier /etc/nsswitch.conf dans lequel est associé à chaque type de service de nom une liste des sources disponibles;
exemple: passwd: files nis nisplus, host: files nis nisplus dns. La recherche se fait d'une source à l'autre dans l'ordre définis tant qu'une correspondance n'est pas trouvée, ce qui abouti à une erreur NOTFOUND en cas d'échec sur toutes les sources listées. On peut d'ailleurs utiliser l'option [NOTFOUND=return] afin d'indiquer aux programmes de consulter uniquement les sources listées à gauche de cette entrée, seulement en cas de disfonctionnement de ces sources celles de droite seront consultées. Exemple: networks: nis [NOTFOUND=return] files. Les NIS fonctionnent sur un système maître-esclave (les modifications se font sur le maître, elles sont répercutées sur le(s) esclave(s) du domaine nis), seulement ils ne sont pas adaptés à des volumes important de données, à chaque modification c'est l'ensemble de la base qui est transférée entre maitre-esclave. Il y à également un manque d'organisation des données sous forme hiérarchique. Enfin la sécurité d'accès à ce service est très faible
2.2.4 NIS+
Sun à réagit aux défauts de NIS par l'introduction dans solaris 2 des NIS+. Ils répondent aux trois remarques ci-dessus en introduisant un propagation des données entre maître-esclave de manière incrémentale, en ajoutant la notion de root domain master en haut de l'arbre hiérarchique sous lequel de trouvent des subdmain master pouvant eux-mêmes être au-dessus d'autres subdomain-master. Enfin la notion de ``certificat, identité (credential) via une paire de clé privée/publique vient combler le problème de sécurité. L'imposition d'une architecture hiérarchique de haut en bas des nis+ qui implique une coopération entre les administrateurs systèmes des différents départements d'une organisation, ainsi que la gestion des paires clé privée/public fut finalement un frein au passage des nis aux nis+. Pourtant ces derniers préfigurent beaucoups de concepts utilisés par la suite dans LDAP.
2.2.5 DNS
Le Domain Name Service à été crée pour palier à l'élargissement des échanges de fichiers hosts et à la répartition de leur administration déjà conséquente dans le réseau ARPANET, précurseur de l'Internet. C'est un système de nommage hiérarchique à l'échelle de l'Internet. Il dispose d'une redondance et depuis peu d'un minimum de sécurité/contrôle d'accès. Bien que très performant et adapté dans son rôle de service de noms IP, il est reste aussi très spécialisé.
2.2.6 logiciels du marché
Microsoft MS-exchange, Lotus cc:Mail, Novell Groupewise ou Netscape Messaging server utilisent des annuaires propriétaires , souvent liés à une base de donnée propre à leurs besoins pour la gestion de leurs ressources. Des interfaces d'accès (API) à ces bases sont disponibles (ADSI pour Microsoft, VIM pour Lotus).
2.2.7 logiciels spécifiques
Il existe souvent dans l'entreprise un nombre important de produits maison basés la plupart du temps sur des SGBD (Oracles, DB2, MySQL, Access …). Encore une fois, bien souvent une base de comptes est définis pour chacune de ces applications et les interfaces d'accès ne sont pas toujours simples (C, cobol …) et uniques.
===== 3 LDAP =====
Après le succès des NIS et beaucoup plus modérément des NIS+ par SUN, le CCITT et l'ISO se sont attelés à définir un standard d'annuaire, dont l'accès serait indépendant des RPC (SUN), il créèrent le protocole X.500. Bien qu'ayant de très bonnes spécifications, les détails d'implémentations n'étaient en revanche pas très heureux que se soit au niveau de la rigidité des règles d'implémentation ou de la pile de protocole envisagée (ISO plutôt que TCP/IP !). C'est dans ces conditions qu'est née une version allégée de X.500 basée sur TCP/IP; Lightweight Directory Acces Protocol qui peut être définis comme étant un protocole de réseaux standard spécialisé dans la manipulation d'annuaires adapté aux réseaux et systèmes en exploitation sur l'Internet.
==== 3.1 Modèles ====
Ce standard définis 4 modèles.
Le modèle d'information
qui définis la nature des données: classe, attribut, types…, l'arbre de données (DIT: Directory Information Tree).
Le modèle de nommage
qui organise et définis des règles de nommages des éléments de l'annuaire. Exemple; l'annuaire dispose d'un schéma, une classe d'objet doit être unique dans l'annuaire, elle est identifiée par un OID.
Le modèle fonctionnel
qui définis les services offerts, comment accéder aux informations et comment les mettre à jours.
Le modèle de sécurité
qui définis les droits d'accès et l'identification.
==== 3.2 Réplication LDAP ====
Mécanisme qui permet de copier automatiquement les données d'un annuaire vers un autre serveur d'annuaire. Cela permet d'améliorer les performance en répartissant plusieurs annuaires identiques sur un domaine, un client sera au plus près de son serveur, cela permet aussi une répartition de la charge.
==== 3.3 Subschema ====
Dans la norme V3 de LDAP le schéma doit être définis dans l'annuaire lui même. Par l'utilisation de classes (subschema) et attributs spécifiques on permet de lire et modifier le schéma de l'annuaire au moyen du protocole LDAP lui même.
On peut lire le schéma via l'URL:
ldap://localhost:port/cn=schema??base?obectclass=*
3.4 RootDSE
On parle de RootDSE (Directory Server Agent (Dsa), Specific Entry). Il comprendra des attributs de type: NamingContext, SupportedExtensions, SupportedControl,SupportedSALMechanism,SupportedLDAPVersion. C'est le seul objet qui n'a pas de nom. http://www.techgalaxy.net/Docs/Dev/LDAPv3%20RootDSE%20Overview.htm
3.5 Définitions
Règles
règles de comparaison d'attributs identifiés par un oid.
Règles:(caseignorematch,CaseExactMatch,TelephoneNumberMatch, IntegerMatch,BouleanMatch,DNMatch,OctetStringMatch …) cf RFC 2252.
Classes
Elles décrivent les entrées, entrées qui sont composées d'attributs. Elles peuvent être de différents types:
abstrait
n'ont pas d'instance, elles servent de réservoir de définition pour les autres classes (grâce à l'héritage): exemple classe top.
structurel
définis des objets instanciés, se sont les plus classiques: exemple Person.
auxiliaire
elles sont utilisées pour compléter les classes structurelles (afin de ne pas modifier directement ces dernières), pour ajouter des attributs à une classe déjà définie par exemple. Elles hérites de top.
L'ordre d'utilisation des classes n'est pas obligatoire avec LDAP. Ce n'est pas le cas dans X500: exemple country→organization→organizationalUnit, avec LDAP on peut avoir organization→country .
Extension
ce sont les opérations conformes LDAP V3 en plus des 9 opérations de base. Exemple: association de signature électronique à toute modification de l'annuaire, ou bien le support de Transaction à la façon SGBDR.
Scope
sélectionne la profondeur de recherche dans l'arbre (DIT).
BASE
indique une recherche uniquement sur la base sélectionnée (recherche sur une seule entrée)
ONELEVEL
toutes entrées se trouvants au niveau juste inférieur à la base sélectionnée
SUBTREE
recherche à partir de la base sélectionnée et parcoure toutes les branches en dessous.
URL
On peut interroger un annuaire Ldap avec un navigateur Internet. L'URL utilise la syntaxe suivante:
protocol:server:port/base?attributs à extraire?type de scope?critères. Exemple:
ldap://corbeau.int-evry.fr:389/dc=int-evry,dc=fr?host?sub?uid=test test host corne.int-evry.fr
cf RFC 2255: http://rfc.net/rfc2255.html
3.6 Habilitations, ACL
Les controles sont de la forme: accès à quoi, par qui → type d'accès pour cette paire. exemple: accès à l'attribut telephoneNumber par l'utilisateur lui même → écriture.
3.6.1 Quoi
Dans la partie quoi, on peut spécifier ;
une expression régulière
correspondant à un dn: dn=<regular expression>
une liste d'attributs
attrs=<attribute list>
un filtre
filter=<ldap filter>
L'accès à l'entrée elle même (attribut “entry”) est nécessaire pour donner des accès à un attribut individuel.
3.6.2 Qui
*
tous les utilisateurs, autant les anonymes que les authetnifiés
anonymous
utilisateur non authentifiés
users
utilisateurs authentifiés
dn=<regex>
utilisateurs correspondants à une expression régulière, le dn ne doit pas contenir de blancs (il est “normalized”)
remarque: toute directive de type d'accès (access to) finie par un by * none implicite ainsi que toute ACL (access list) finie par un access to * by * none implicite.
3.6.3 Type d'accès
none
pas d'accès
auth
= x permet de faire un bind authentifié,
compare
= cx pour la comparaison,
search
=scx pour l'application de filtre de recherche,
read
=rscx pour lire les resulats de recherche,
write
=wrscx pour modifier ou renommer.
3.6.4 Evaluation
L'évaluation des controles d'accès se fait dans l'odre ou les regles sont définies dans le fichier de configuration avec un arret d'évaluation à la première correspondance (“first match”). slapd compare d'abord le quoi, puis le qui et décide enfin si la requête du client est confome (inférieure ou égale) au type d'accès définis dans ces circonstances (quoi/qui).
3.7 Connexion à l'annuaire (bind)
3.7.1 Authentification Simple
Il suffit de fournir à l'annuaire un Distinguish Name (dn) et le mot de passe associé (ou bien se connecter en annonymous), on parle d'attachement au serveur ou Bind. Par défaut cette authentification simple laisse circuler en clair les échanges LDAP avec le serveur sur le réseau. Il faut ajouter des mécanismes de sécurité comme SSL ou SASL pour crypter ces échanges.
4 Compilation, Installation d'Openldap 2.X.X
4.1 Contraintes de migration 2.0.X à 2.1.X et 2.2.X
Un certains nombre de contraintes ont été ajoutées dans les versions 2.1.x et 2.2.X pour un meilleurs respet des RFC notament. Voici la liste de celles que j'ai rencontré:
objectclass strutural
un objet (une entrée) ne peut dépendre que d'une seule objectclass structurelle, sauf si ces objectclass sont dans la même descendance ,
attribut systeme structuralObjectClass
cet attribut apparait sur chaque nouvelle entrée ldap, cela explique pourquoi on ne peux avoir un master en 2.0.X et un slave en 2.1.X → error: “No structuralObjectClass operational attribute”,
bind v2
n'est plus disponible par défaut, il faut le forcer dans le slapd.conf si nécessaire: allow bind_v2,
bind non dn et defaultaccess
par défaut il y a maintenant un disallow bind_anon_dn et defaultaccess none est positionné par défaut,
entryUUID/entryCSN
ces deux nouveaux attributs opérationnels sont automatiquement mis à jour → utiles pour un futur multi-master …
RDN
la valeur de l'attribut RDN doit être reprise a l'identique dans l'entrée, exp: dn: cn=JP_Bar,ou=people,dc=int-evry,dc=fr puis dans les attrribut de cet objet → cn: Jean-Pierre Bar, ne sera pas valide ! il doit être identique au RDN → cn: JP_Bar .
ACL
Les valeurs par defaut dans les ACL ont changés entre la 2.1.X et 2.2.X , voir http://www.openldap.org/faq/data/cache/1082.html
Voir a ce sujet http://www.openldap.org/faq/data/cache/35.html
4.2 Berkeley DB
La base LDAP est ici au format berkeley DB (BDB),
cf http://www.sleepycat.com/, qui peut être utilisée dans un backend-bdb ou backend-ldbm with-ldapm-api=berkeley
4.2.1 L'essentiel de BDB
Sur ce lien je reprend les principales caracteristiques de BDB, et les notions fondamentales, c'est un copier-collé de la doc sleepycat qui résume ce qui m'a semblé important, pour ma propre information mais aussi pour le lecteur … http://www.int-evry.fr/mci/user/procacci/ldap/BDB.txt
4.2.2 Compilation et installation BDB
Afin de rendre les binaires openldap indépendants des modifications de versions des librairies BDB système (BDB étant utilisé par ailleurs par le système) nous prenons une version à jour de BDB et l'installons à part. La compilation d'openldap fera par la suite référence à cette installation: cf CPPFLAGS et LDFLAGS de la configuration de la compilation d'openldap ci-après. On pourra également utiliser des packages RPM qui compilent en statique BDB dans les binaires (c'est ce qui sera utilisé en exploitation !) ainsi openldap et ses utilitaires restent indépendant de la bibiothèque BDB système.
[jehan@corbeau /usr/local/src/db-4.1.24.NC/dist]
$./configure
$make
[jehan@corbeau /usr/local/src/db-4.1.24.NC/dist]
$make install prefix=/usr/local/jehan/bdb-4.1.24
4.2.3 Restauration de la base de donnée en cas de plantage
Avec un backend de type back-BDB il est possible de restaurer la base de donnée depuis un état stable (le dernier checkpoint valide) grace aux fichiers de log exp: log.0000000007 … Procédure: arreter le service, lancer un db_recover, ici en verbose (-v) et en conservant l'environement DB (-e), redonner les droits à l'utilisateur ldap sur tous les fichiers (notamment les fichiers d'environement db* qui passent sous root lors d'un recover en tant que root !), enfin relancer le service.
[root@openldap ~]
$ /etc/init.d/ldap stop
Stopping slapd: [ OK ]
Stopping slurpd: [ OK ]
[root@openldap ~]
$ cd /var/lib/ldap/int
[root@openldap /var/lib/ldap/int]
$ /usr/sbin/slapd_db_recover -e -v
db_recover: Finding last valid log LSN: file: 16 offset 8839464
db_recover: Recovery complete at Mon Mar 1 09:39:23 2004
db_recover: Maximum transaction id 80000000 Recovery checkpoint [16][8839416]
[root@openldap /var/lib/ldap/int]
$ chown ldap:ldap *
[root@openldap /var/lib/ldap/int]
$ /etc/init.d/ldap start
Starting slapd: [ OK ]
Starting slurpd: [ OK ]
4.2.4 Gestion des fichiers de Log
Ici on utilise les utilitaires db (http://www.sleepycat.com/docs/utility/) notament db_archive fournis par les packages RPM RedHat (pour ma part:http://www.int-evry.fr/mci/user/procacci/SRPMS/), on retrouve en effet les binaires dans /usr/sbin/slapd_db* car ils sont compilées en statique avec la version BDB qui va bien !
$ /usr/sbin/slapd_db_archive -V
Sleepycat Software: Berkeley DB 4.2.52: (December 3, 2003)
$ ldd /usr/sbin/slapd_db_archive
libpthread.so.0 ⇒ /lib/tls/libpthread.so.0 (0x40028000)
libc.so.6 ⇒ /lib/tls/libc.so.6 (0x42000000)
/lib/ld-linux.so.2 ⇒ /lib/ld-linux.so.2 (0x40000000)
Lister les fichiers de log
[root@openldap /var/lib/ldap/int]
$ /usr/sbin/slapd_db_archive -l
log.0000000001
log.0000000002
log.0000000003
log.0000000004
log.0000000005
log.0000000006
log.0000000007
log.0000000008
log.0000000009
log.0000000010
log.0000000011
log.0000000012
log.0000000013
log.0000000014
log.0000000015
log.0000000016
Lister les fichiers de log à archiver (ou supprimer …)
$ /usr/sbin/slapd_db_archive -a
/var/lib/ldap/int/log.0000000001
/var/lib/ldap/int/log.0000000002
/var/lib/ldap/int/log.0000000003
/var/lib/ldap/int/log.0000000004
/var/lib/ldap/int/log.0000000005
/var/lib/ldap/int/log.0000000006
/var/lib/ldap/int/log.0000000007
/var/lib/ldap/int/log.0000000008
/var/lib/ldap/int/log.0000000009
/var/lib/ldap/int/log.0000000010
/var/lib/ldap/int/log.0000000011
/var/lib/ldap/int/log.0000000012
/var/lib/ldap/int/log.0000000013
/var/lib/ldap/int/log.0000000014
/var/lib/ldap/int/log.0000000015
Lister les fichiers de database (bdb) qui doivent être archivés en cas de catastrophic recovery (db_recover -c)
$ /usr/sbin/slapd_db_archive -s
IntEPersInetServ.bdb
cn.bdb
dn2id.bdb
gidNumber.bdb
givenName.bdb
id2entry.bdb
mail.bdb
objectClass.bdb
sn.bdb
uid.bdb
uidNumber.bdb
Supprimer les fichiers de log anciens (attention cela peut empecher de procéder à une catastrophic recovery !) Exemple:
$ /usr/sbin/slapd_db_archive -l
log.0000000005
log.0000000006
log.0000000007
$ /usr/sbin/slapd_db_archive -d
$ /usr/sbin/slapd_db_archive -l
log.0000000007
Ici le log 7 est encore ``actif .
4.3 Openldap
Exemple de compilation et installation dans une arborescence de test, dans l'objectif par la suite de construire un package RPM pour une installation système propre.
[jehan@corbeau /usr/local/src/openldap-2.1.8]
$ CPPFLAGS=-I/usr/local/jehan/bdb-4.1.24/include \
LDFLAGS=-L/usr/local/jehan/bdb-4.1.24/lib \
./configure –enable-debug –enable-crypt –enable-bdb –enable-ldbm \
–with-ldbm-api=berkeley –enable-monitor –enable-local –enable-cldap \
–disable-rlookups –with-tls –with-cyrus-sasl –enable-passwd \
–enable-shell –enable-cleartext –enable-spasswd –enable-meta –enable-ldap –enable-rewrite
$ make depend
$ make
$ make test
$ make install prefix=/usr/local/src/jehan/openldap-2.1.8
4.3.1 Configuration
Adaptation du schema
Penser (pour une config redhat avec autofs et kerberos) à recréer l'arborenscence de schema redhat pour les schemas autofs et kerberos aisni que de modifier le schema de base afin de tenir compte du fait qu'une entrée ldap ne peu dépendre que d'une classe structurelle (sauf si cette classe hérite d'une autre classe structurelle de la meme lignée → Person → InetOrgPerson )
[jehan@corbeau /usr/local/src/jehan/openldap-2.1.8/etc/openldap/schema]
$ mkdir redhat
$ cp /tmp/autofs.schema ./redhat/
$ cp /tmp/kerberosobject.schema ./redhat/
$ cp /tmp/int-evry.schema .
Ajout de l'attribut krbName a kerberosobject.schema,
attribut qui était avant définit dans core.schema et reclassement
en AUXILIARY de l'objectclass kerberosSecurityObject qui etait STRUCTURAL !.
attributetype ( 1.3.6.1.4.1.250.1.32
NAME ( 'krbName' 'kerberosName' )
DESC 'Kerberos Name'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26
SINGLE-VALUE )
objectclass ( 1.3.6.1.4.1.2312.4.2.4 NAME 'kerberosSecurityObject'
SUP top AUXILIARY
DESC 'A uid with an associated Kerberos principal'
MUST ( krbName ) )
Redéfinition de l'objectclass account de STRUCTURAL vers AUXILIARY
$ vi cosine.schema
objectclass ( 0.9.2342.19200300.100.4.5 NAME 'account'
SUP top AUXILIARY
Adaptation du fichier de configuration
Modification du slapd.conf pour s'adapter à l'arborescence de test
ucdata-path /usr/local/src/jehan/openldap-2.1.8/share/openldap/ucdata
include /usr/local/src/jehan/openldap-2.1.8/etc/openldap/schema/core.schema
include ….
allow bind_v2
database bdb
directory /usr/local/src/jehan/openldap-2.1.8/var/openldap-data/int
Test
Restauration d'une base
[jehan@corbeau /usr/local/src/jehan/openldap-2.1.8]
$ ./sbin/slapadd -l /tmp/dump_int.ldif21Nov200219:59:03
-f ./etc/openldap/slapd.conf
$ ls var/openldap-data/int/
cn.bdb db.005 IntEPersInetServ.bdb log.0000000005 uid.bdb
db.001 dn2id.bdb log.0000000001 log.0000000006 uidNumber.bdb
db.002 gidNumber.bdb log.0000000002 mail.bdb
db.003 givenName.bdb log.0000000003 objectClass.bdb
__db.004 id2entry.bdb log.0000000004 sn.bdb
Lancement du serveur
[jehan@corbeau /usr/local/src/jehan/openldap-2.1.8]
$ ./libexec/slapd -4 -d 256 -f etc/openldap/slapd.conf \
-h ldap://localhost:9009/
bdb_open: Sleepycat Software: Berkeley DB 4.1.24: (September 13, 2002)
…
Requête
[jehan@corbeau /usr/local/src/jehan/openldap-2.1.8]
$ ./bin/ldapsearch -x uid=procacci -b “dc=int-evry,dc=fr” -p 9009 -h localhost
Utilitaires BDB
[jehan@corbeau /usr/local/src/jehan/openldap-2.1.8/var/openldap-data/int]
$ /usr/local/src/jehan/bdb/bin/db_stat -m
….
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Pool File: id2entry.bdb
16384 Page size.
0 Requested pages mapped into the process' address space.
12 Requested pages found in the cache (1%).
1405 Requested pages not found in the cache.
0 Pages created in the cache.
1405 Pages read into the cache.
3 Pages written from the cache to the backing file.
$ /usr/local/src/jehan/bdb/bin/db_verify id2entry.bdb -o
$ /usr/local/src/jehan/bdb/bin/db_dump -f mail.bdb.dump mail.bdb
$ rm mail.bdb
$ /usr/local/src/jehan/bdb/bin/db_load -f mail.bdb.dump mail.bdb
db_load: Lock table is out of available locks
db_load: Cannot allocate memory
???
$ /usr/local/src/jehan/bdb/bin/db_recover -v
db_recover: Finding last valid log LSN: file: 6 offset 6567774
db_recover: Recovery starting from [6][6567605]
db_recover: Recovery complete at Sun Nov 17 19:49:04 2002
db_recover: Maximum transaction ID 80001453 Recovery checkpoint [6][6567774]
db_recover: Recovery complete at Sun Nov 17 19:49:04 2002
db_recover: Maximum transaction id 80000000 Recovery checkpoint [6][6567774]
4.4 Package Openldap RPM
4.4.1 Introduction
Installation d'openldap à partir de source RPM. Partir des packages source permet entre autre de modifier le mode de compilation d'openldap. On voudra par exemple forcer la compilation avec les supports des threads (pas de threads par defaut dans les versions 2.0.1x des packages RedHat d'openldap !) ou bien avec le support des berkeley DB ou des fonctionnalités méta etc … On retrouve donc toutes les options de compilation des sources au format tar.gz, puisque qu'un package source n'est autre qu'une automatisation de la configuration-compilation-installation d'une application. cf RPM-HOWTO: http://www.linux.org/docs/ldp/howto/RPM-HOWTO/
4.4.2 Configuration avant construction
A la base nous sommes partis d'un package source 2.1.3 RedHat, en y incluant régulièrement les différentes versions d'openldap, dernièrement le tar.gz 2.1.20 d'openldap (l'exemple ci-dessous etant sur la 2.1.15 !) , avec les adaptations qui vont bien, cf commentaires ci-dessous.
$ rpm -i /home/jehan/openldap-2.1.3-4-RH.src.rpm
Modification des options de compilation et adaptation du package source 2.1.3 vers 2.1.15. Essentiellement, il s'agit de prendre en compte les berkeley DB → backend berkeley puis quelques modifications (patch de la 2.1.3 devenus inutiles, ou idéfinis !? en 2.1.15) et options de compilation pour la prise en charge de fonctionnalitées supplémentaires: –enable-monitor –enable-meta etc …
$ vi /usr/src/redhat/SPECS/openldap-2.1.15.spec
%define migtools_ver 44
%define db_version 4.1.25.NC
#%define backend gdbm
%define backend berkeley
Summary: The configuration files, libraries, and documentation for OpenLDAP.
Name: openldap
#Version: 2.1.3
Version: 2.1.15
#Release: 4
Release: 1
…
#Modification des patch de la 2.1.3 vers la 2.1.8; on en retire 2 !.
Patch0: openldap-2.1.3-config.patch
#Patch1: openldap-2.1.2-redhat.patch
Patch2: openldap-1.2.11-cldap.patch
#Patch3: openldap-2.1.2-syslog.patch
Patch3: openldap-2.1.13-syslog.patch
Patch4: openldap-2.1.2-sendbuf.patch
Patch5: openldap-2.0.11-ldaprc.patch
Patch7: openldap-2.1.12-subdir.patch
…
%setup -q -a 1 -a 3
%patch0 -p1 -b .config
#%patch1 -p1 -b .redhat
%patch2 -p1 -b .cldap
%patch3 -p1 -b .syslog
%patch4 -p1 -b .sendbuf
%patch5 -p1 -b .ldaprc
#%patch6 -p1 -b .debug
%patch7 -p1 -b .subdir
…
%configure \
–with-slapd –with-slurpd –without-ldapd \
–with-threads=posix –enable-static \
\
–enable-local –enable-cldap –disable-rlookups \
\
–with-tls \
–with-cyrus-sasl \
\
–enable-wrappers \
\
–enable-passwd \
–enable-shell \
–enable-cleartext \
–enable-crypt \
–enable-spasswd \
–enable-modules \
–enable-lmpasswd \
–enable-monitor \
–enable-rewrite \
–enable-ldap \
–enable-meta \
–enable-shell \
–enable-password \
–enable-debug \
\
–libexecdir=%{_sbindir} \
–localstatedir=/%{_var}/run \
$@ \$@
4.4.3 Construction
Construction des packages openldap, attention depuis la version 8.0 de RedHat la commande est maintenant rpmbuild -ba et non plus rpm -ba !.
[root@corbeau /usr/src/redhat/SPECS]
$ rpmbuild -ba openldap-2.1.15.spec
…
Wrote: /usr/src/redhat/SRPMS/openldap-2.1.15-1.src.rpm
Wrote: /usr/src/redhat/RPMS/i386/openldap-2.1.15-1.i386.rpm
Wrote: /usr/src/redhat/RPMS/i386/openldap-devel-2.1.15-1.i386.rpm
Wrote: /usr/src/redhat/RPMS/i386/openldap-servers-2.1.15-1.i386.rpm
Wrote: /usr/src/redhat/RPMS/i386/openldap-clients-2.1.15-1.i386.rpm
liste des packages ldap sur la machine
$ rpm -qa | grep ldap
openldap-devel-2.1.15-1
nss_ldap-198-3
php-ldap-4.2.2-8.0.5
openldap-2.1.15-1
openldap-clients-2.1.15-1
openldap-servers-2.1.15-1
4.4.4 Installation
Installation des packages binaires
$ cd /usr/src/redhat/RPMS/i386/
[root@corbeau /usr/src/redhat/RPMS/i386]
$ rpm -Uvh openldap-*2.1.15-1.i386.rpm
Preparing… ########################################### [100%]
1:openldap ########################################### [ 25%]
2:openldap-servers ########################################### [ 50%]
3:openldap-clients ########################################### [ 75%]
4:openldap-devel ########################################### [100%]
4.5 Disponibilite des RPM
Je met régulièrement en ligne mes compilations de RPM sur: http://www.int-evry.fr/mci/user/procacci/SRPMS/
4.5.1 Changelog
Ci dessus un extrait du changelog qui indique les modifications realisées dans chaque version de package, il est extrait le fichier openldap-X.X.X.spec que l'on trouve dans les packages source .
%changelog
* Wed May 28 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.20-1
- upgraded to 2.1.20
* Fri May 02 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.17-2
- adapted spec file for RedHat 9:
- 1) resolved pb with kerberos/ssl headers not found
- CFLAGS/LDFLAGS in the clients package
- 2) resolved “error: Installed (but unpackaged) file(s) found:”
- generated by feature of RPM >= 4.1: “/usr/lib/rpm/check-files”
- added missing files in %files section in consequence
* Mon Apr 07 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.17-1
- upgraded to 2.1.17
- remove part of openldap-2.1.3-config.patch regarding default database\
(bdb vs ldmb) in slapd.conf (see “@@ -43,15 +59,26 @@” in previous patch)
* Tue Mar 18 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.16-1
- upgraded to 2.1.16
* Wed Mar 12 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.15-1
- upgraded to 2.1.15
* Mon Mar 03 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.14-2
- upgraded to 2.1.14
- removed patch for schema-check (already patched in 2.1.14 !)
- removed make test openldap build to accelerate rpmbuild !
* Thu Feb 28 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.13-3
- from Francis Swasey Frank.Swasey@uvm.edu 2.1.12-uvm2.8.0:
- sleepycat bdb 4.1.25 plus locking patch
- add patch for schema-check
- add patch for slapd lock-release in group acl processing
- add patch for slapcat a subtree
- add make test to openldap build
* Tue Feb 25 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.13-1
- replace openldap source (tgz) from 2.1.12 to 2.1.13
* Mon Jan 20 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.12-1
- replace openldap source (tgz) from 2.1.11 to 2.1.12
* Wed Jan 08 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.11-2
- compiled with back-monitor not beeing a dynamic module.
- error is with:modulepath /usr/sbin/openldap & moduleload \
back_monitor.la in slapd.conf
slapd[1992]: lt_dlopen failed: (back_monitor.la) back_monitor.a: \
cannot open shared object file: No such file or directory
slapd[1992]: /etc/openldap/slapd.conf: line 33: \
failed to load or initialize module back_monitor.la ??
* Tue Jan 07 2003 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.11-1
- replace openldap source (tgz) from 2.1.9 to 2.1.11
- replace BDB from 4.1.24-NC to 4.1.25-NC
* Wed Dec 11 2002 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.9-3
- added backends, ldap meta shell password without modules
* Sat Dec 07 2002 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.9-2
- added backends, ldap meta shell password with module=dynamic
* Thu Dec 04 2002 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.9-1
- replace openldap source (tgz) from 2.1.8 to 2.1.9
* Mon Nov 25 2002 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.8-2
- removed offending patch in regards to RFCs on cosine.schema
* Thu Nov 21 2002 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.8-1
- changed kerberosobject.schema to include krbName attr from old core.schema
- changed kerberosobject.schema to AUXILIARY
- patched cosine.schema, account objectclass from STRUCTURAL to AUXILIARY
- Includes –enabled-modules and back-monitor as a dynamic module(didn't test!)
- Includes BDB 4.1.24-NC
* Fri Aug 2 2002 Nalin Dahyabhai nalin@redhat.com 2.1.3-4
- enable the ldbm/berkeley backend as well
- use an ldbm/berkeley database as the default (fyi bdb's still available)
- don't install slapadd-gdbm
5 Packages 2.2.X relocatable
5.1 Motivations
Depuis la sortie d'openldap 2.2.X, j'ai rencontrer le problème du changement de version majeur des librairies liblber.so.2 et libldap.so.2, ce qui crée un sérieux problème de dependance sur un système à base de RPM; voir à ce sujet le thread de discussion sur la liste openldap (http://www.openldap.org/lists/openldap-software/) ayant pour sujet ``LDAP library version number
.
5.2 Relocatable
Qu'entend t-on par ``relocatable ? . cela signifie que le package va pourvoir s'installer dans son entier, dans une sous-arborescence, un peu à la façon d'un tar.gz. Cependant ici on conserve les avantages des packages RPM (installation, desintallation, recompilation, informations etc …) tout en évitant les problèmes de dépendance. En effet openldap depend d'autres packages (BDB, sasl, etc …) système sensibles à un upgrade sauvage, et aussi beaucoup d'autres packages dependent d'openldap. Ainsi on conserve les packages openldap qui vont bien avec la distibution, et on peux disposer de la dernière version ``uptodate
d'openldap afin de profiter des dernieres fonctionnalitées, corrections de bug à des fins de test ou de production !.
5.3 Utilisation
Les packages que j'ai compilé s'installent dans leur intégralité par défaut dans /usr/local. C'est ce chemin qui est modifiable. Exemple ici je vais declarer un prefix sur la commande d'installation.
[root@corbeau /usr/src/redhat/RPMS/i386]
rpm -ivh –prefix=/usr/local/openldap-2.2.15-1 openldap-*2.2.15-1*.rpm
Ainsi ce package openldap ira dans /usr/local/openldap-2.2.15-1 Cela implique bien entendu un certain nombre d'ajustement sur le fichier configuration slapd.conf et le fichier de demarrage init.d/ldap ainsi que le chargeur de librairie ldconfig; /etc/ld.so.conf . Tout ceci est détaillé dans ce README http://www.int-evry.fr/mci/user/procacci/SRPMS/README-openldap-2.2.15-jehan.txt que je conseil fortement de lire avant d'utiliser ou de recompiler ce package relocatable.
5.4 Disponibilité
Source; http://www.int-evry.fr/mci/user/procacci/SRPMS/
Binaires pour fedora core 2: http://www.int-evry.fr/mci/user/procacci/SRPMS/FC2/
5.5 Changelog
Voici les modifications que j'ai apporté par rapport au package Redhat 2.1.29-1
%changelog
* Thu Aug 05 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.15-2
- added openldap-2.2.15-configure.patch to correct pb of configure
“checking for Berkeley DB version match” I blindly added
export LD_LIBRARY_PATH=../db-4.2.52/build-rpm/.libs/
to use embeded BDB package for ./conftest test !
* Thu Aug 05 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.15-1
- updated to openldap 2.2.15
- effectively include .rpmmacros in SOURCES (forgot in 2.2..14-2)
* Thu Jul 08 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.14-2
- link slapd utilities (slapadd slapindex etc …) to slapd (done since 2.2.7 !)- added README-jehan.txt and .rpmmacros in SOURCES directory
* Thu Jul 01 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.14-1
- upgraded to 2.2.14
- adjusted some doc files for relocatable
- adapted openldap-2.1.17-syslog.patch to reflect changes in servers/slapd/main.c
* Wed Jun 09 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.12-1
- relocatable package from /usr/local to be system independant
- upgraded to openldap 2.2.12
* Mon Apr 26 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.2.11-1
- upgraded to openldap 2.2.11
* Thu Apr 15 2004 Jehan Procaccia jehan.procaccia@int-evry.fr 2.1.29-2
- removed openldap 2.0 and DB 4.0 compatibilities
* Wed Apr 14 2004 Nalin Dahyabhai nalin@redhat.com 2.1.29-1
- rebuild
* Tue Apr 6 2004 Nalin Dahyabhai nalin@redhat.com 2.1.29-0
- update to 2.1.29 (stable 20040329)
6 Exploitation
6.1 Modifier le schéma
Il est possible de personnaliser le schéma par ajout d'attribut/objectclass.
6.1.1 Définition d'objets
Une syntaxe particulière est utilisée pour définir des attributs/objectclass. Ici nous employons la syntaxe LdapV3. il existe aussi une syntaxe ASN1, ou X500 .
Cela commence par le mot clé attributetype ou objectclass suivi de son oid du nom NAME et d'une éventuelle DESCription.
On trouve ensuite la règle de comparaison entre attributs, EQUALITY caseIgnoreMatch par exemple éventuellement suivit d'une règle de correspondance sur les opérations de recherche, SUBSTR caseIgnoreSubstringsMatch par exemple.
Enfin une SYNTAXE identifiée par un oid définit le type d'un attribut.
Types:(binary,boolean,dn,diretory string (chaine UTF8), integer, telephoneNumber…) cf RFC 2252 et 2256.
6.1.2 Exemple de schema
Ici nous utilisons une objectclass auxiliary dont l'objectif est d'apporter des modifications à une classe structurelle standard.
[root@mci21056 /etc/openldap/schema]
$ more int-evry.schema
#definitions propres à l'int
attributetype (1.3.6.1.4.1.7391.2.2.1.1.1.5
NAME ('IntEPersInetServDemande')
DESC 'Services Internet autorises'
EQUALITY caseIgnoreIA5Match
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
objectclass ( 1.3.6.1.4.1.7391.2.1.1.1.1.1
NAME 'IntE-user'
SUP TOP
AUXILIARY
MAY ( IntEPersInetServDemande )
)
OID
L'INT-Evry s'est vu attribué par l'IANA (http://www.iana.org/) l'oid 7391, donc la branche d'oid 1.3.6.1.4.1.7391. Ici suivant l'exemple de la doc openldap nous commençons l'arbre privé par 2 (pour ldap, 1 pour snmp) puis 2 pour les attributs ou 1 pour les objectclass. Ensuite on peut imaginer une branche système_informatique 1, mci 1, comptes 1; d'où le 7391.2.1.1.1.1.1 pour l'attribut IntEPersInetServDemande.
Autre exemple; utilisation du SubstringsMatch pour matcher une sous-chaine dans une liste ou aussi des types boolean; attention la case est importante: TRUE ou FALSE ou ON et OFF
$more /etc/openldap/schema/int-evry.schema
#definitions propres à l'int
attributetype (1.3.6.1.4.1.7391.2.2.1.1.1.4
NAME ('IntEPersInetServ')
DESC 'Services Internet autorises'
EQUALITY caseIgnoreIA5Match
SUBSTR caseIgnoreIA5SubstringsMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
)
attributetype (1.3.6.1.4.1.7391.2.2.1.1.1.9
NAME ('IntEPersPublic')
DESC 'Services Internet demandes'
EQUALITY booleanMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
)
6.1.3 Exemple d'entrée
Exemple d'entrée ldif pour un compte utilisateur INT-evry. Dans cet exemple les attributs IntEPersxxxx (Int Evry Personne nom d'attribut) sont propres au schéma interne de l'INT.
dn: uid=procacci,ou=People,dc=int-evry,dc=fr
uid: procacci
cn: Jehan PROCACCIA
telephoneNumber: 01 60 76
givenName: Jehan
sn: PROCACCIA
objectClass: inetLocalMailRecipient
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: account
objectClass: posixAccount
objectClass: IntE-user
objectClass: labeledURIObject
objectClass: strongAuthenticationUser
objectClass: certificationAuthority
objectClass: top
objectClass: kerberosSecurityObject
objectClass: shadowAccount
mail: Jehan.Procaccia@int-evry.fr
mailLocalAddress: procacci@mci.int-evry.fr
mailRoutingAddress: email@email
mailHost: smtp-mci
departmentNumber: MCI
employeeType: permanent
IntEPersUserQuota: 10000
IntEPersUserParrain: Eric.Collery
IntEPersUserExpire: 2999/12/31
IntEPersUserPTM: mci
IntEPersCreationDate: 2001/07/31-17:22:20
IntEPersLastModificationDate: 2001/07/31-17:22:20
IntEPersUserNature: permanent
IntEPersUserLogin: procacci
IntEPersUserUid: 145032
IntEPersUserGroup: mci
IntEPersUserShell: ksh
IntEPersUserPrenom: Jehan
IntEPersUserNom: PROCACCIA
IntEPersUserGecos: Jehan PROCACCIA
IntEPersUserEntite: MCI
IntEPersUserEmail: Jehan.Procaccia
IntEPersUserSmtp: smtp-mci
IntEPersUserMailLogin: procacci
IntEPersUserMbox: pop-mci
IntEPersUserMX: mci
o: INT Evry FRANCE
ou: MCI
shadowLastChange: 10000
krbName: procacci@INT-EVRY.FR
loginShell: /usr/local/bin/ksh
uidNumber: 145032
gidNumber: 145
homeDirectory: /mci/mci/procacci
gecos: Jehan PROCACCIA
host: .int-evry.fr
title: procacci
roomNumber: B001
jpegPhoto;binary:: /9j/4AAQSkZJRgABAQEAAQABAAD/2w……
labeledURI: http://www.int-evry.fr
facsimileTelephoneNumber: 01 60 76 xx xx
postalCode: 91011 EVRY CEDEX
postalAddress: 9 rue Charles Fourier
homePhone: 00 00 00 00 00
homePostalAddress: xx xxx
secretary: uid=secretary-name,ou=People,dc=int-evry,dc=fr
userCertificate;binary:: YWJjZGVmZ2hpamts
authorityRevocationList;binary:: YWJjZGVmZ2hpamts
certificateRevocationList;binary:: YWJjZGVmZ2hpamts
cACertificate;binary:: YWJjZGVmZ2hpamts
IntEPersInetServ: unix-int mail-int
IntEPersInetServDemande: unix-int mail-int ras-int
IntEPersACLDroit: telephoneNumber homePostalAddress
IntEPersPublic: FALSE
IntEPersUserPasswordFlag: FALSE
IntEPersUserLastPasswordChange: 1900/01/01-00:00:00
6.2 Modifier une entrée, outils shell ldap*
syntaxe
changetype: <[modify|add|delete|modrdn]>
Après la prise en compte de l'objectclass ci-dessus ( slapd.conf: include int-evry.schema) il est possible d'ajouter l'attribut IntEPersInetServ:
$ more add_IntEPersInetServ.ldif
dn: uid=testlinu,ou=staff,ou=People,dc=int-evry,dc=fr
changetype: modify
add: objectclass
objectclass: int-evry-user
-
add: IntEPersInetServ
IntEPersInetServ: unix-int mail-int
$ ldapmodify -D “cn=admin,dc=int-evry,dc=fr” -W -p 9009 -h corbeau -x \
-f ./add_IntEPersInetServ.ldif
Enter LDAP Password:
modifying entry “uid=testlinu,ou=staff,ou=People,dc=int-evry,dc=fr”
Suppression:
$ more del_IntEPersInetServ.ldif
dn: uid=testlinu,ou=staff,ou=People,dc=int-evry,dc=fr
changetype: modify
delete: IntEPersInetServ
IntEPersInetServ: unix-int mail-int
-
delete: objectclass
objectclass: int-evry-user
$ ldapmodify -D “cn=admin,dc=int-evry,dc=fr” -W -p 9009 \
-h corbeau -x -f ./del_IntEPersInetServ.ldif
Enter LDAP Password:
modifying entry “uid=testlinu,ou=staff,ou=People,dc=int-evry,dc=fr”
Pour supprimer une entrée complète:
dn: uid=testlinu,ou=staff,ou=People,dc=int-evry,dc=fr
changetype: delete
6.3 Dump et restore de la base
6.3.1 dump
Après avoir arreter le serveur, du moins pour les backend ldbm, normalement cela n'est plus nécessaire avec back-bdb (openldap 2.1.X), on peux faire un dump de la base au format ldif.
$ /etc/init.d/ldap stop
Stopping slapd: [OK]
$/usr/sbin/slapcat -l /tmp/dump_int.ldif \
-f /etc/openldap/slapd.conf -b “dc=int-evry,dc=fr”
$more /tmp/dump_int.ldif
dn: dc=int-evry,dc=fr
dc: int-evry
objectClass: top
objectClass: domain
objectClass: domainRelatedObject
associatedDomain: int-evry.fr
creatorsName: cn=admin, dc=int-evry, dc=fr
createTimestamp: 20010718150911Z
modifiersName: cn=admin, dc=int-evry, dc=fr
modifyTimestamp: 20010730082211Z
…
6.3.2 Restore
Si on remplace une base existante, on commence par la supprimer. Méthode rapide: supprimer les fichiers
$ /etc/init.d/ldap stop
Stopping slapd: [ OK ]
[root@openldap /var/lib/ldap/int]
$ rm -f *
Insertion sous forme de fichiers .gdbm, .dbb ou .bdb du dump.
$ /usr/sbin/slapadd -l /tmp/dump_int.ldif -f /etc/openldap/slapd.conf \
-b “dc=int-evry,dc=fr”
[root@corbeau /var/lib/ldap/int]
$ ls -al
total 11130
drwxr-xr-x 2 ldap ldap 1024 Aug 2 17:46 .
drwx—— 6 ldap ldap 1024 Aug 2 17:15 ..
-rw——- 1 root root 1716224 Aug 2 17:46 cn.dbb
-rw——- 1 root root 700416 Aug 2 17:46 dn2id.dbb
-rw——- 1 root root 31304 Aug 2 17:46 gidNumber.dbb
-rw——- 1 root root 495920 Aug 2 17:46 givenName.dbb
-rw——- 1 root root 7448938 Aug 2 17:46 id2entry.dbb
-rw——- 1 root root 1728600 Aug 2 17:46 mail.dbb
-rw——- 1 root root 12296 Aug 2 17:46 nextid.dbb
-rw——- 1 root root 421909 Aug 2 17:46 objectClass.dbb
-rw——- 1 root root 860200 Aug 2 17:46 sn.dbb
-rw——- 1 root root 188416 Aug 2 17:46 uid.dbb
-rw——- 1 root root 196608 Aug 2 17:46 uidNumber.dbb
Remarque: l'insertion c'est faite sous le compte root, il faut rendre ldap propiétaire des fichiers sans quoi slapd ne pourra rien lire !.
$ chown ldap:ldap *
[root@corbeau /var/lib/ldap/int]
$ ls -l
total 11128
-rw——- 1 ldap ldap 1716224 Aug 2 17:46 cn.dbb
-rw——- 1 ldap ldap 700416 Aug 2 17:46 dn2id.dbb
-rw——- 1 ldap ldap 31304 Aug 2 17:46 gidNumber.dbb
-rw——- 1 ldap ldap 495920 Aug 2 17:46 givenName.dbb
-rw——- 1 ldap ldap 7448938 Aug 2 17:46 id2entry.dbb
-rw——- 1 ldap ldap 1728600 Aug 2 17:46 mail.dbb
-rw——- 1 ldap ldap 12296 Aug 2 17:46 nextid.dbb
-rw——- 1 ldap ldap 421909 Aug 2 17:46 objectClass.dbb
-rw——- 1 ldap ldap 860200 Aug 2 17:46 sn.dbb
-rw——- 1 ldap ldap 188416 Aug 2 17:46 uid.dbb
-rw——- 1 ldap ldap 196608 Aug 2 17:46 uidNumber.dbb
$ /etc/init.d/ldap start
Starting slapd: [ OK ]
et c'est reparti .
7 Développement
API Ldap en C cf draft-ietf-ldap-c-api-01.txt
7.1 concepts
Toute interaction avec un serveur se fait sur la base d'une recherche. Il n'y a pas de fonction de navigation ou d'interrogation. Les fonctions peuvent être synchrones, dans ce cas le programme client est bloqué en l'attente d'une réponse du serveur LDAP. Elle peuvent être asynchrones, le programme client peut alors faire autre chose en attendant que le serveur réponde, il faudra cependant “poller” régulièrement pour vérifier la presence d'une réponse. Les fonctions synchrones finissent toujours par un s: ldap_simple_bind_s
7.1.1 code de connexion
0 #include <stdio.h>
1 #include <ldap.h>
2
3 main (int argc, int argv) {
4 Structure de donnée LDAP qui enregistre la connexion
5 LDAP *ld;
6 int rc = 0;
7 printf(“Test de connexion Ldap en C\n”);
8 /* initialisation de la connexion,
9 retour d'un handle de connexion dans la structure LDAP.
10 l'init est tj synchrone. */
11 if 1) != NULL)
102 {
103 parcours eventuel des attributs multivalués,sinon une seule valeur
104 for (i=0; vals[i] != NULL; i++)
105 {
106 printf (“\t%s: %s\n”,attribute,vals[i]);
107 }
108 libération de la mémoire allouée aux valeurs d'attribut
109 ldap_value_free(vals);
110 }
111 liberation de la mémoire allouée à l'attribut
112 ldap_memfree(attribute);
113 }
114
115 libération de la mémoire utilisée pour stocker
116 la structure de valeur (ber) de l'attribut
117 if (ber != NULL)
118 {
119 ber_free (ber, 0);
120 }
121
122 }
123
124 test du rc de for (e=ldap_first_entry(ld,result)… ci dessus
125 if (rc != LDAP_SUCCESS)
126 {
127 fprintf(stderr, “ldap_search_ext: %s\n”, ldap_err2string(rc));
128 }
129
130 ldap_msgfree ( result);
131 printf (“Search réussi !\n”);
132 }
133
compilation
$ gcc ldap_search.c -lldap -llber -o ldap_search.bin
exécution
$ ./ldap_search.bin
Initialisation de la connexion
Connecté au serveur ldap corbeau sur le port 9009
Nombre d'entrées sélectionnées: 2
DN: uid=testlinu,ou=Staff,ou=People,dc=int-evry,dc=fr
cn: Compte_test LINUX
mail: Compte_test.LINUX@int-evry.fr
DN: uid=procacci,ou=Staff,ou=People,dc=int-evry,dc=fr
cn: Jehan PROCACCIA
mail: Jehan.PROCACCIA@int-evry.fr
Search réussi !
8 Authentification système Unix, connexion à un système
8.1 Objectifs
l'authentification système par un annuaire LDAP permet d'unifier les bases de données utilisateur. De plus le système de répartition et de réplication que procure ce type d'annuaire permet une meilleure tolérance aux pannes. Enfin d'autres services peuvent tirer partie de cette base commune d'authentification (email, accès web, ftp, carnet d'adresse …). C'est aussi la disponibilité d'outils d'administration et de surveillance de la journalisation.
8.2 Authentification système traditionnelle Unix
Le système unix utilise depuis longtemps un système d'authentification basé sur une algorithme de hachage nommé crypt(3) disponible aux programmeurs C par la librairie libcrypt.a, a ne pas confondre avec l'application d'encryptage/décryptage de fichiers /usr/bin/crypt. Avec crypt(3) la chaine texte saisie par l'utilisateur est hachée (one-way-encrypted) par l'algorithme crypt qui introduit en plus de cette chaîne un grain de sel (il s'agit des 2 premiers caractères de la version cryptée des 13 caractères ASCII du password, ils sont choisis aléatoirement afin de différencier différente occurrence d'une même chaine: salt).
Lors de l'authentification l'utilisateur saisi son login, ce qui permet au système de rechercher la chaine cryptée (password) qui est associée à ce login. Ensuite l'utilisateur est invité à saisir son password, celui ci sera crypté par l'algorithme crypt(3) avec les 2 premiers caractères du password crypté récupéré lors du login comme salt. Enfin une correspondance positive entre ce cryptage de la saisie et la chaîne cryptée récupérée lors du login attestera de l'identité de l'utilisateur.
8.3 Authentification système NIS+
La méthode ci-dessus ne permet pas de contrôler d'où se connecte l'utilisateur puisque cette information n'est stockée nulle part, de plus elle est basée sur un algorithme qui utilise une clé sur 56 bit relativement ancien. Dans NIS+ des ``certificats (user credentials) sont crées sous une forme unix.userid@domainname et stockés dans la table cred. Quand un utilisateur se connecte, les credentials sont retirés depuis la table cred. Cette table contient le mot de passe réseau de l'utilisateur sous forme de paire clé privée/publique.
8.4 PAM
Tout comme les Name Service Switch NSS viennent s'intercaler entre les programmes faisant accès à des sources d'information et ces sources, Pluggable Authentification Module fournis un cadre permettant à de nouvelles technologies d'authentification de s'interfacer avec les programmes qui les utilisent. On va par exemple avec un module PAM_LDAP, permettre à des programmes tels que login, telnet, ftp…, d'aller chercher et vérifier l'information d'authentification auprès d'un annuaire LDAP. Ces programmes doivent être ``pam-enabled
c'est à dire lié à la librairie pam libpam.so pour utiliser ce cadre d'authentification. Reste à l'administrateur du système de définir les modules à utiliser, ce qui peut être définis de manière individuelle pour chaque application, ou communément pour un ensemble d'application. L'administrateur pourra empiler et définir un ordre d'importance à chacun des modules d'une manière propre pour chacun des programmes. C'est une structure d'authentification extrêmement modulaire et donc très évolutive.
8.4.1 Type de modules PAM
On distingue 4 fonctions qui peuvent être implémentés par un module.
authentification
ce type de module permet l'authentification et positionne l'identité d'un utilisateur.
account managment
une fois authentifier, ce type de module permet de valider l'accès de l'utilisateur aux ressources sur des critères tels que le vieillisement du mot de passe, l'expiration du compte, heures de restriction….
session management
gère certaines fonctions pendant la session de l'utilisateur, notament lors de l'ouverture et la fermeture de la session.
password management
gère les modifications de mot de passe.
8.4.2 Empilage et drapeaux de contrôle
Pour un service donné (ou plusieurs) différent modules peuvent être empilés, un mécanisme de drapeaux de contrôle (control flags) permet de donner plus ou moins d'importance au succès ou échec d'authentification sur chacun des modules empilés.
required
dans le cas d'un module déclaré required, en cas d'échec sur celui-ci le reste de la pile est consulté,mais le retour final sera un échec quelquesoit le résultat des modules suivants traversés.
requisite
en cas d'échec sur un module déclaré requisite, une erreur est immédiatement retournée sans poursuivre l'empilement des modules.
sufficient
si ce module retourne un succès, alors un succès général est immédiatement retourné sans poursuivre l'empilement.
optional
si ce module échoue, un autre peut retourner un succès, cet échec ne sera pas pris en compte dans le résultat final.
8.4.3 pam.conf ou pam.d/service
Exemple de fichier /etc/pam.d/login commenté
#%PAM-1.0
###############################################################################
#auth: actual authentification, ask and check password and set credentials as
#group membership or kerberos tickets
#securetty check that root logs from the console
auth required /lib/security/pam_securetty.so
#warn log info to syslog
auth required /lib/security/pam_warn.so
#check presence of /etc/nologin file
auth required /lib/security/pam_nologin.so
#pam ldap
auth sufficient /lib/security/pam_ldap.so debug
#pam_unix: This is the standard Unix authentication module.
# It uses standard calls from the system's libraries to retrieve
#and set account information as well as authentication
#arguments: debug; audit; use_first_pass; try_first_pass; nullok; nodelay
auth required /lib/security/pam_unix_auth.so try_first_pass audit
#############################################################################
#Account: non-authentification account management
#restrict access on time of day, available system ressources …
account required /lib/security/pam_warn.so
account sufficient /lib/security/pam_ldap.so
#pam_unix: Recognized arguments: debug; audit
account required /lib/security/pam_unix_acct.so audit
##############################################################################
#password: for updating the authentification, if an auth module has determined
#that the password needs to be changed e.g expired …
#if pam_unix present in the module type password
#arguments: debug; audit; nullok; not_set_pass; use_authtok; try_first_pass;
use_first_pass; md5; bigcrypt; shadow; nis; remember
password required /lib/security/pam_warn.so
#cracklib, checks tha newly entered password does not appear in a dictionnary
password required /lib/security/pam_cracklib.so
password sufficient /lib/security/pam_ldap.so debug
#pwdb modules: is a pluggable replacement for the pam_unix_.. modules.
#Based on the following pwdb_elements: expire; last_change; max_change;
#defer_change; warn_change,
# this module performs the task of establishing the status of the user's
#account and password
#The default action of this module is to not permit the user access to a
#service if their official password is blank.
#The nullok argument overrides this default.
#the argument try_first_pass, before prompting the user for their password,
#the module first tries the previous stacked auth-module's password in case
#that satisfies this module as well.
#The argument use_first_pass forces the module to use such a recalled password
#and will never prompt the user - if no password is available or the password
#is not appropriate, the user will be denied access.
#arguments: debug; nullok; not_set_pass; use_authtok; try_first_pass;
#use_first_pass; md5; bigcrypt; shadow; radius; unix
password required /lib/security/pam_pwdb.so use_first_pass debug
###########################################################################
#session: for doing things before/after users can be given a service
#e.g: logging of information, mounting directory …
session required /lib/security/pam_warn.so
session required /lib/security/pam_unix_session.so
session optional /lib/security/pam_console.so
8.4.4 configuration PAM sous RedHat
Exemple de la version RH 8.0, pam-0.75-40, l'empilement des modules pam pour la plupart des services est centralisé dans le fichier system-auth.
$ cat /etc/pam.d/login
#%PAM-1.0
auth required /lib/security/pam_securetty.so
auth required /lib/security/pam_stack.so service=system-auth
auth required /lib/security/pam_nologin.so
account required /lib/security/pam_stack.so service=system-auth
password required /lib/security/pam_stack.so service=system-auth
session required /lib/security/pam_stack.so service=system-auth
session optional /lib/security/pam_console.so
$ cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth required /lib/security/pam_env.so
auth sufficient /lib/security/pam_unix.so likeauth nullok
auth sufficient /lib/security/pam_ldap.so use_first_pass
auth required /lib/security/pam_deny.so
account required /lib/security/pam_unix.so
#ajouter pour la connexion de compte locaux quand il n'y a pas de serveur LDAP
account sufficient /lib/security/pam_localuser.so
account [default=bad success=ok user_unknown=ignore \
service_err=ignore system_err=ignore] /lib/security/pam_ldap.so
password required /lib/security/pam_cracklib.so retry=3 type=
password sufficient /lib/security/pam_unix.so nullok use_authtok md5 \
shadow
password sufficient /lib/security/pam_ldap.so use_authtok
password required /lib/security/pam_deny.so
session required /lib/security/pam_limits.so
session required /lib/security/pam_unix.so
session optional /lib/security/pam_ldap.so
8.5 NSS et Pam ldap, outils d'authentification système par LDAP
NSS et PAM ldap
Il existe deux outils sous unix pour authentifier via un annuaire ldap, il s'agit de nss_ldap et pam_ldap.
Le premier est utilisé par les services/programmes qui ne sont pas compatibles PAM; exemple /usr/bin/id qui fait un appel getpwent() (accès à /etc/passwd et /etc/shadow).
Les Name Service Switch (/etc/nsswitch.conf) redirigent cet appel vers différentes sources: files, nis, dns et grâce à nss_ldap vers ldap . Pour les applications compatibles PAM (pam-enabled) il est possible d'utiliser pam_ldap, cela permet d'individualiser le fichier de configuration d'accès à l'annuaire par service, donc d'utiliser aussi une méthode d'authentification différente suivant le service, il apporte pour cela d'autres méthodes d'authentification que crypt.
9 Mise en oeuvre de l'authentification système par LDAP
9.1 Tcpd
Certaines versions de packages sont ou peuvent être compilées avec la libwrap , donc utilise les tcp-wrappers. Il faut penser à configurer les fichiers de contrôle d'accès en conséquence.
$vi /etc/hosts.allow
slapd: .int-evry.fr
Sans cette ligne slapd, nous aurions un “access denied ”.
9.2 lancement
$more /etc/rc.d/init.d/ldap
daemon ${slapd} -u ldap -f /etc/openldap/slapd.conf \
-h “ldap://ldap1.int-evry.fr:389/” -l LOCAL3 $OPTIONS $SLAPD_OPTIONS
Les log seront dans local3 redirigés vers /var/log/ldap.log par /etc/syslog.conf, le port standard en 389 sur le host ldap1.
9.3 configuration
Personnalisation du fichier de configuration slapd.conf
Ajouts aux directives par défaut:
#et les attributs/objectclass propre à l'INT
include /etc/openldap/schema/int-evry.schema
#check du schema
schemacheck on
# The next line allows LDAPv2 bind requests, which are disabled by default.
allow bind_v2
#on augmente le nombre max d'entré retourné lors d'une requète 'large'
sizelimit 15000
#le directory et les index seront dans
directory /var/lib/ldap/int
# modif performance ed
cachesize 10000
dbcachesize 1500000
9.4 Mot de passe administrateur
Définition du password “root”:
[root@openldap ~]
$perl -e 'print crypt(“plaintext”, “somerandomsalt”), qq(\n)'
$perl -e 'print crypt(“padle”, “gd”), qq(\n)'
gdRK6cNklXSV6
donc dans slapd.conf
rootdn “cn=admin,dc=int-evry, dc=fr”
rootpw {crypt}abcd123XQ1234
Il faut définir les droits unix sur ce directory personnalisé:
$chown ldap:ldap /var/lib/ldap/int
9.5 Première initialisation des données
Format utf8
Il faut avant tout convertir le fichier ldif en utf8 (accents sur ``télécom par exemple…)
[root@openldap /usr/local/Migratemci/Ldif]
$iconv arbre.ldif -f LATIN1 -t UTF8 -o arbre_utf8.ldif –verbose
Démarrage du serveur
On démarre le serveur afin d'y insérer les données.
$/etc/rc.d/init.d/ldap start
Starting slapd: [ OK ]
Ossature
On ajoute l'ossature du DIT (arbre).
[root@servfax /usr/local/Migratemci/Ldif]
$ldapadd -f arbre_utf8.ldif -x -D “cn=admin,dc=int-evry,dc=fr” -W -p
389 -h ldap1
Enter LDAP Password:
adding new entry “dc=int-evry,dc=fr”
adding new entry “ou=People,dc=int-evry,dc=fr”
adding new entry “ou=Group,dc=int-evry,dc=fr”
adding new entry “ou=Staff,ou=People,dc=int-evry,dc=fr”
adding new entry “ou=Students,ou=People,dc=int-evry,dc=fr”
adding new entry “ou=Stagiaires,ou=People,dc=int-evry,dc=fr”
adding new entry “ou=Thesards,ou=People,dc=int-evry,dc=fr”
Contrôle avec un browser LDAP
Visualisation avec le ldap browser (java): http://www.iit.edu/~gawojar/ldap
$cd /usr/local/ldapbrowser/
[root@ldap1 /usr/local/ldapbrowser]
$./lbe.sh
9.6 Migration des Données système (nis) vers ldap
9.6.1 Users
Exemple restreint
Migration de /etc/passwd et /etc/shadow (depuis /var/yp/src/passwd et shadow.
[root@ldap1 /usr/local/MigrationToolsJP]
$./migrate_passwd_staff.pl ./Files/passwd.mci ./Ldif/passwd_mci.ldif
Le nom des fichiers est important (cf source perl des scripts). Le script déduit de la chaine passwd_staff le namingcontext du fichier migrate_common_mci.ph (gestion de l'ou=staff dans notre exemple de schéma personnalisé). La presence d'un fichier shadow (ici dans ./Files/shadow.mci) est importante aussi pour qu'il intègre les attributs d'authentification shadowaccount.
Exploitation
Finalement en exploitation nous utiliserons un schema standard (ou=people, puis tout les login à plat dessous): Migration depuis ypcat passwd.
[root@ldap1 /usr/local/Migratemci]
$./migrate_passwd.pl ./Files/yppasswd ./Ldif/people.ldif
Ajout des entrées utilisateurs
[root@ldap1 /usr/local/MigrationToolsJP]
$ldapadd -f ./Ldif/passwd_mci.ldif -x -D “cn=admin,dc=int-evry,dc=fr”
-W -p 389 -h ldap1
Enter LDAP Password:
adding new entry “uid=gilles,ou=Staff,ou=People,dc=int-evry,dc=fr”
adding new entry “uid=petit,ou=Staff,ou=People,dc=int-evry,dc=fr”
…
9.6.2 Groups
Migration des groups
[root@ldap1 /usr/local/MigrationToolsJP]
$./migrate_group.pl ./Files/group ./Ldif/groups.ldif
Ajout à l'annuaire
[root@ldap1 /usr/local/MigrationToolsJP]
$ldapadd -f ./Ldif/groups.ldif -x -D “cn=admin,dc=int-evry,dc=fr” -W -p
9009 -h ldap1
Enter LDAP Password:
adding new entry “cn=admins,ou=Group,dc=int-evry,dc=fr”
adding new entry “cn=guests,ou=Group,dc=int-evry,dc=fr”
….
9.6.3 L'ensemble dans un fichier ldif global
Plutot que de migrer les fichiers sources un a un , l'esemble de la migration peut se faire via migrate_all_offline.sh.
[mciadmin@openldap /usr/local/Migratemci]
$./migrate_all_offline.sh
Creating naming context entries…
Migrating aliases…
Migrating groups…
Migrating hosts…
Migrating networks…
Migrating users…
Migrating protocols…
Migrating rpcs…
Migrating services…
Migrating netgroups…
Importing into LDAP…
Migrating netgroups (by user)…
Migrating netgroups (by host)…
Preparing LDAP database…
/etc/openldap/slapd.conf: Permission denied
No databases found in config file
A partir de “Importing into LDAP” le script plante volontairement, dans la phase de debuggage nous voulions disposer d'un ficher ldif, puis de l'inserer dans l'annuaire mannuellement.
$ls -ltra /tmp | tail -1
-rw——- 1 mciadmin mciadmin 3578259 aoû 1 13:42 nis.ldif.DRnZGR
$more /tmp/nis.ldif.DRnZGR
dn: dc=int-evry,dc=fr
dc: int-evry
objectClass: top
objectClass: domain
objectClass: domainRelatedObject
associatedDomain: int-evry.fr
dn: ou=People,dc=int-evry,dc=fr
ou: People
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: int-evry.fr
dn: ou=Rpc,ou=System,dc=int-evry,dc=fr
ou: Rpc,ou
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: int-evry.fr
…..
Il ne reste plus qu'a faire l'insertion manuelle:
$ldapadd -f/tmp/nis.ldif.DRnZGR -x -W -D“cn=admin,dc=int-evry,dc=fr” -h ldap1
ldap_bind:
….
9.7 Authentification système
9.7.1 Installation
Installation de nss_ldap et éventuellement pam_ldap. Avec la distribution RedHat, le module pam_ldap est intégré dans le package nss_ldap.
$ rpm -qli nss_ldap-198-3 | grep pam_ldap
This package includes two LDAP access clients: nss_ldap and pam_ldap.
/lib/security/pam_ldap.so
des exemples de configuration pam pour les services sont disponibles:
/usr/share/doc/nss_ldap-198/pam.d/login
/usr/share/doc/nss_ldap-198/pam.d/passwd
/usr/share/doc/nss_ldap-198/pam.d/pop
….
Pour connaitre la version de pam_ldap incluse dans le package nss_ldap RedHat:
$ rpm -q nss_ldap –changelog | grep pam_ldap
- update to nss_ldap 197, pam_ldap 150
…
[root@servfax /etc]
$vi ldap.conf
host ldap1.int-evry.fr ldap2.int-evry.fr
base dc=int-evry,dc=fr
ldap_version 3
port 389
binddn cn=binduser,ou=system,dc=int-evry,dc=fr
bindpw secret
pam_password crypt #pour la commande/usr/bin/passwd.
pam_filter IntEPersInetServ=*unix-int* #filtre propre à l'INT
[root@servfax /etc]
$vi nsswitch.conf
passwd: files nisplus ldap
shadow: files nisplus ldap
group: files nisplus ldap
automount: files nisplus ldap
9.7.2 Exemple d'authentification
$telnet servfax
Connected to servfax.int-evry.fr.
Escape character is '^]'.
Red Hat Linux release 7.2 (Enigma)
Kernel 2.4.14 on an i686
login: procacci
Password:
Last login: Sun Jan 27 18:06:53 on :0
No directory /mci/mci/procacci!
Logging in with home = “/”.
ksh-2.04$
Sans automount pas de home directory ! cf ci-dessous pour l'automount.
9.8 Automount
9.8.1 Principes
Nous prenons ici l'option de ne monter que le homedir complet d'un utilisateur et non son directory parent. Cette implémentation non documentée a été réalisé en étroite collaboration avec Nalin Dahyabhai nalin@redhat.com. Cela suppose de créer un automounter “master”, exemple /citi ici, qui lancera un automounter par sous-répertoire; /citi/citi1 ou /citi/citi2, enfin un wildcard sur cn=/ montera le directory prorpre à l'utilisateur; /citi/citi1/testciti par exemple.
Après modification de migrate_automount.pl nous arrivons à ce qui est décrit ci-dessus.
9.8.2 Mise en oeuvre
[mciadmin@openldap /usr/local/Migratemci]
$./migrate_automount.pl /usr/local/Migratemci/Files/auto.citi \
./Ldif/auto-citi-tree.ldif
$more ./Ldif/auto-citi-tree.ldif
#The auto.master
dn: ou=auto.master,dc=int-evry,dc=fr
objectClass: top
objectClass: automountMap
ou: auto.master
#auto.master points to cn /citi, that latest managing subdirectories
#hence /citi is the root directory of homes served by this automount
#this entry points to 'ou=auto.citi,ou=automount,dc=int-evry,dc=fr'
dn: cn=/citi,ou=auto.master,dc=int-evry,dc=fr
objectClass: top
objectClass: automount
automountInformation: ldap:ou=auto.citi,ou=automount,dc=int-evry,dc=fr
cn: /citi
# This entry is more or less a place-holder for automount entries for directories \
#which get mounted under /citi.
#this is the ou pointed just above by: 'automountInformation: ldap:ou=auto.citi'
dn: ou=auto.citi,ou=automount,dc=int-evry,dc=fr
objectClass: top
objectClass: organizationalUnit
ou: auto.citi
# This entry causes autofs to start up another automounter on /citi/citi1.
# Here we create a subautomounter for every [sub]directory on the NFS server
# this 'cn=citi1' is not necesarily related to the real [sub]directory name
# on the nfs server (here it is /home on nfs server)
Dn: cn=citi1,ou=auto.citi,ou=automount,dc=int-evry,dc=fr
objectClass: top
objectClass: automount
cn: citi1
automountInformation: -fstype=autofs \
ldap:ou=auto.citi.citi1,ou=auto.citi,ou=automount,dc=int-evry,dc=fr
# This entry is more or less a place-holder for automount entries for directories \
#which get mounted under /citi/citi1.
# it is actually the ou just pointed above: 'ldap:ou=auto.citi.citi1'
dn: ou=auto.citi.citi1,ou=auto.citi,ou=automount,dc=int-evry,dc=fr
objectClass: top
objectClass: organizationalUnit
ou: auto.citi.citi1
# This is a wildcard entry for any user whose home directory is under
# /citi/citi1
# homedir for users here is: /citi/citi1/login
# a equivalent to 'mount nfsserver:/home/login /citi/citi1/login' will
# be done bye autofs,
# neither /citi nor /citi/citi1 needs to preexist on the client station !
# autofs is in charge of creating them .
dn: cn=/,ou=auto.citi.citi1,ou=auto.citi,ou=automount,dc=int-evry,dc=fr
objectClass: top
objectClass: automount
cn: /
automountInformation: -rw,intr,soft,quota nfsserver:/home/&
9.8.3 Configuration système
Ici nous prenons en compte la presence de replicas. On trouvera dans /etc/ldap.conf la liste des serveurs LDAP à interroger pour l'authentification pam, et dans /etc/openldap/ldap.conf la liste des serveurs LDAP (les même) pour automount , ainsi que pour les outils shell openldap (ldapsearch, ldapmodify …) .
$grep host /etc/ldap.conf
host ldap1.int-evry.fr ldap2.int-evry.fr
$grep HOST /etc/openldap/ldap.conf
HOST ldap1.int-evry.fr ldap2.int-evry.fr
9.8.4 Exemple d'utilisation
#L'utilisateur testciti (nfs-automount homedir) se connecte:
$ pwd
/citi/citi1/testciti
#Autofs status
$ /etc/init.d/autofs status
Configured Mount Points:
————————
/usr/sbin/automount /citi ldap ou=auto.citi,ou=automount,dc=int-evry,dc=fr
Active Mount Points:
——————–
/usr/sbin/automount /citi ldap ou=auto.citi,ou=automount,dc=int-evry,dc=fr
/usr/sbin/automount –submount /citi/citi1 ldap \
ou=auto.citi.citi1,ou=auto.citi,ou=automount,dc=int-evry,dc=fr
ldap log
Mar 14 11:19:52 corne automount[2670]: starting automounter version 3.1.7, \
path = /mci/mci, maptype = ldap, mapname = \
ou=auto.citi.citi1,ou=automount,dc=int-evry,dc=fr
Mar 14 11:19:52 corne automount[2670]: Map argc = 1
Mar 14 11:19:52 corne automount[2670]: Map argv[0] = \
ou=auto.citi.citi1,ou=automount,dc=int-evry,dc=fr
Mar 14 11:19:52 corne automount[2670]: lookup(ldap): server = “(default)”, \
base dn = “ou=auto.citi.citi1,ou=automount,dc=int-evry,dc=fr”
9.8.5 Contrôle d'accès aux stations et serveurs NFS
Sur le principe décrit dans la section suivante ``contrôle d'acces aux services
, on ajoute un filtre pam dans le fichier /etc/ldap.conf pour contrôler les accès login et NFS sur le stations. Ce filtre diffèrera suivant que l'on se trouve sur une station salles TP ou une station dans un département par exemple:
stations département citi
$ grep pam_filter /etc/ldap.conf
pam_filter IntEPersInetServ=*unix-citi*
stations salles TP
$ grep pam_filter /etc/ldap.conf
pam_filter IntEPersInetServ=*unix-int*
9.8.6 Gestion de differents homedir
L'objectif est de mettre à disposition des utlisateurs des répertoires d'accueil (homedir) sur different serveurs NFS. Le serveur NFS (homedir) sera choisi en fonction de la localité de la station de travail où l'utilisteur se connecte, dans un département ou en salle de TP par exemple.
#A user ldap entry can contain 2 (or more ) homeDirectory attributes
homeDirectory: /mci/citi/testciti
homeDirectoryDept: /citi/citi1/testciti
#On departement citi client machines, the homeDirectory attr is remapped,
#so that users get their homes from the citi nfsserver.
$ grep homeDirectoryDept /etc/ldap.conf
nss_map_attribute homeDirectory homeDirectoryDept
$ ssh testciti@citi_client_machine
$ pwd
/citi/citi1/testciti
#On departement mci client machines, traditional homeDirectory attr is seacrh,\
#they get their homes from mci nfsserfer (cf ldap automount maps)
$ ssh testciti@mci_client_machine
$ pwd
/mci/citi/testciti
9.9 Contrôle d'accès host
On desire contrôler sur quels hosts un utilisateur peut se connecter. On peut utiliser l'attribut host (objectclass account de cosine.schema) pour cela, il suffit de lister les serveurs (un par occurence de l'attribut) sur lesquels un utilisateurs peut se connecter. Restera sur les serveurs en question à definir un filtre sur leur propre nom dans /etc/ldap.conf. Depuis pam_ldap 130 voir l'option pam_check_host_attr. Entre les versions pam_ldap 125 et 129, la simple présence de l'attribut host dans une entrée ldap impossait le contrôle du nom de host sur lequel l'utilisateur se connecte.
9.9.1 exemple d'entrée ldif
$ ldapsearch -h ldap1 -p 9009 -x -b“dc=int-evry,dc=fr” “(host=*)”
….
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
….
host: mci21056.int-evry.fr
host: servfax.int-evry.fr
#host: *.int-evry.fr #* dans l'entree ne fonctionne pas
#en revanche cela fonctionne dans le filtre /etc/ldap.conf
9.9.2 Configuration du serveur
Version ancienne de pam_ldap(< 125 ?)
[root@mci21056 /usr/local/Migratemci/Ldif]
$ more /etc/ldap.conf
…
# Filter to AND with uid=%s
#pam_filter objectclass=account
pam_filter host=servfax.int-evry.fr
…
Puis, contrôle par défaut pour les versions pam_ldap 124 à 129, depuis la version pam_ldap 130 utilisation de la directive pam_check_host_attr dans /etc/ldap.conf.
9.9.3 ACL
Du fait de l'empilement des modules pam, le module pam_unix basé sur les nss, contourne le filtre pam_ldap definit dans /etc/ldap.conf. En effet , nss_ldap va directement lire l'annuaire te ne tiens pas compte des filtres de pam_ldap, ainsi l'utilisateur sera authentifié par pam_unix, même si pam_ldap échoue grâce au contrôle d'accès host !. Il faut alors interdir à nss_ldap d'authentifier en tant qu'anonymous (car le bind ce fait en anonymous au login). Pour cela on spécifie des ACL dans le slapd.conf afin de ne pas permettre au compte anonymous l'accès read sur l'attribut userpassword mais seulement le droit auth (nécessaire pour faire un bind).
access to attr=userPassword
by self write
by anonymous auth
by dn=“cn=root,dc=int-evry,dc=fr” write
by * none
access to *
by self write
by dn=“cn=root,dc=int-evry,dc=fr” write
by * read
9.9.4 démonstration
Avant et après changement des ACL.
[procacci@mci21056 ~]
$su - testlinu
Password:
su: incorrect password
#changement ACL
[procacci@mci21056 ~]
$su - testlinu
Password:
ksh-2.04$
Remarque: le message d'erreur su: incorrect password peut être trompeur !
Les log confirment le filtre demandé dans /etc/ldap.conf:
Jun 25 14:22:08 mci21056 slapd[8205]: conn=1 op=1 SRCH base=“dc=int-evry,dc=fr”
scope=2 filter=“(&(host=servfax.int-evry.fr)(uid=testlinu))”
10 Contrôle d'accés aux services
Ici nous gérons l'accés aux différents services basés sur ldap (connexion unix, mountage nfs, accés web, accés messagerie etc …) par le biais d'un attribut (perso) multivalué (IntEPersInetServ)qui liste l'ensemble des services ouverts à un individu:
$ ldapsearch -x uid=testciti -D “cn=admin,dc=int-evry,dc=fr” -W IntEPersInetServ -LLL
Enter LDAP Password:
dn: uid=testciti,ou=People,dc=int-evry,dc=fr
IntEPersInetServ: unix-int mail-int unix-citi unix-citi cours
Dans cet exemple, l'individu a accés aux services de connexion et de disque (NFS) sur le machines unix central (unix-int) , au mail central (mail-int) , aux services de connexion et disque du département citi (unix-citi) et enfin à la publication de cours en ligne (cours-int).
C'est un filtre (SubStringMatch !) sur une des valeures de cet attribut qui donnera ou non accés au service. Pour pam le filtre est realisé dans /etc/ldap.conf , pour le web dans la configuration du module apache en question, et pour toute application interne → à définir dans le code source !. La plupart des applications ``ldap enable proposants l'ajout d'un filtre aux requètes de base, nous pouvons largement étendre les fonctionnalités de cet attribut.
Avertissement
La combinaison de pam et nss ldap peut provoquer des résultats inattendus. Par exemple pam_unix peut valider une connexion via ldap (/etc/nsswitch.conf → passwd: ldap) alors que l'on voulais forcer un filtre via pam_ldap (/etc/ldap.conf →pam_filter IntEPersInetServ=*unix-int*). Cela impose donc une grande rigueur sur l'empilement des modules dans pam et sur la qualité des controles qu'on leur applique (required, sufficient ….).
11 Solaris 9
L'objectif de ce chapitre est de montrer comment authentifier un client solaris 9 sur un serveur openldap.
11.1 modification openldap
Pour cela il faut apporter quelques modifications sur le serveur openldap.
11.1.1 patch LDAP ROOT DSE
Le client solaris doit avoir un acces particulier (a preciser ?) au root_dse, d'ou la necessité d'appliquer ce patch a la compilation d'openldap
$ cat /usr/src/redhat/SOURCES/openldap-2.1.22-solaris.patch
— servers/slapd/result.c 2003-02-28 18:07:14.000000000 +0100
+++ servers/slapd/result.c 2003-07-16 15:30:01.000000000 +0200
@@ -885,7 +885,9 @@
if ( attrs == NULL ) {
/* all attrs request, skip operational attributes */
if( is_at_operational( desc→ad_type ) ) {
- continue;
+ if (strcasecmp( e→e_dn, LDAP_ROOT_DSE )) {
+ continue;
+ }
}
} else {
@@ -1080,7 +1082,9 @@
if ( attrs == NULL ) {
/* all attrs request, skip operational attributes */
if( is_at_operational( desc→ad_type ) ) {
- continue;
+ if (strcasecmp( e→e_dn, LDAP_ROOT_DSE )) {
+ continue;
+ }
}
} else {
Un package source rpm est disponible sur http://www.int-evry.fr/mci/user/procacci/SRPMS/openldap-2.1.22-2.src.rpm qui comprend l'inclusion de ce patch, cf %patch8 -p0 -b .solaris dans le fichier openldap.spec
11.1.2 Ajout de schemas
Inclure DUAconfig.schema : http://sapiens.wustl.edu/~sysmain/info/openldap/schemas/DUAConfig.schema et solaris.schema : http://www.int-evry.fr/mci/user/procacci/ldap/solaris.schema, une autre version mais qui ne contient pas nisDomain entre autre !?: http://sapiens.wustl.edu/~sysmain/info/openldap/schemas/solaris.schema
$ grep solaris /etc/openldap/slapd.conf
include /etc/openldap/schema/solaris/solaris.schema
include /etc/openldap/schema/solaris/DUAConfig.schema
11.1.3 Ajout ldif
Une fois les schemas ci-dessus inclus, on peut ajouter les objects ldap attenduspar les commandes natives ldap de solaris9.
On va créer un profile, de façon à initialiser le service d'authentification ldap sur solaris avec la commande ldapclient init. Pour cela on peut demander à solaris de générer le fichier ldif de ce profile de configuration ldap.
[root@solaris9ldap /]
$ ldapclient genprofile -a profilename=profile-mci -a defaultsearchbase=dc=int-evry,dc=fr \
-a authenticationmethod=simple -a credentiallevel=proxy 157.159.55.199
dn: cn=mciprofile,ou=profile,dc=int-evry,dc=fr
ObjectClass: top
ObjectClass: DUAConfigProfile
defaultServerList: 157.159.55.199
defaultSearchBase: dc=int-evry,dc=fr
authenticationMethod: simple
cn: profile-mci
credentialLevel: proxy
ou bien on crée directement le fichier ldif avec toutes les options qui nous interessent
$ cat solaris-base-profile.ldif
dn: ou=Profile,dc=int-evry,dc=fr
ou: Profile
objectClass: top
objectClass: organizationalUnit
dn: cn=profile-mci,ou=profile,dc=int-evry,dc=fr
ObjectClass: top
ObjectClass: DUAConfigProfile
defaultServerList: 157.159.55.199
defaultSearchBase: dc=int-evry,dc=fr
authenticationMethod: simple
cn: profile-mci
credentialLevel: proxy
followReferrals: true
serviceSearchDescriptor: auto_master:nismapname=auto_master,dc=int-evry,dc=fr
objectclassMap: automount:automountMap=nisMap
objectclassMap: automount:automount=nisObject
attributeMap: automount:automountMapName=nisMapName
attributeMap: automount:automountInformation=nismapentry
attributeMap: automount:automountKey=cn
ajout d'un proxy-agent, qui sert de binddn plutot que de faire un accés anonyme
$ cat solaris-proxyagent.ldif
dn: cn=proxyagent,ou=profile,dc=int-evry,dc=fr
cn: proxyagent
sn: proxyagent
objectClass: top
objectClass: person
userPassword:: secretsecretsecretsecretsecret=
verification du bon fonctionnement du proxy-agent
[root@solaris9ldap /]
$ ldapsearch -b “dc=int-evry,dc=fr” -D “cn=proxyagent,ou=profile,dc=int-evry,dc=fr” -h 157.159.55.199 -p 389 cn=proxyagent
Bind Password:
cn=proxyagent,ou=profile,dc=int-evry,dc=fr
cn=proxyagent
sn=proxyagent
objectClass=top
objectClass=person
userPassword={CRYPT}secretsecret
Enfin, ajout de l'attribut nisdomain à la base de l'annuaire, cela est necéssaire pour la commande ldapclient init
$ cat solaris-add-nisdomain.ldif
dn: dc=int-evry,dc=fr
changetype: modify
add: objectclass
objectclass: nisDomainObject
-
add: nisdomain
nisdomain: int-evry.fr
$ ldapsearch -x objectclass=nisDomainObject -h localhost -LLL
dn: dc=int-evry,dc=fr
dc: int-evry
objectClass: top
objectClass: domain
objectClass: domainRelatedObject
objectClass: nisDomainObject
associatedDomain: int-evry.fr
nisDomain: int-evry.fr
11.2 Configuration du client
Maintenant que tout est préparé coté serveur, il suffit de lancer la commande suivante sur les clients solaris 9
$ ldapclient init -a profileName=profile-mci -a domainName=int-evry.fr -a proxyDn=cn=proxyagent,ou=profile,dc=int-evry,dc=fr 157.159.55.199
credentialLevel requires proxyPassword
Proxy Bind Password:
System successfully configured
cela récupere le profile depuis le serveur et configure en conséquence les fichiers systèmes
/etc/nsswitch.conf
/etc/pam.conf
/var/ldap/ldap_client_file
/var/ldap/ldap_client_cred
lance /usr/lib/ldap/ldap_cachemgr
…
verification
$ ssh procacci@solaris9ldap
procacci@solaris9ldap's password:
Last login: Thu Jul 17 13:31:58 2003 from corbeau.int-evr
Sun Microsystems Inc. SunOS 5.9 Generic May 2002
solaris9ldap:/mci/mci/procacci>
11.3 non traité
Ici il ne s'agissait que d'une experience, elle n'est pas vraiment mise en exploitation, le montage nfs automount se fait sur des fichiers auto_master/auto_home à plat sur la station, la configuration TLS n'est pas implémentée, l'optimisation des ACL sur le serveur non plus. Pour ces points je renvoie aux références ci-dessous.
11.4 Références
http://docs.sun.com/db/doc/806-4077/6jd6blbeq?a=view http://www.ypass.net/solaris8/openldap/ http://www.cse.sc.edu/~jqu/work/systemadmin/LDAP.html http://sapiens.wustl.edu/~sysmain/info/openldap/
12 Replication
12.1 Compte de replication
Nous utiliserons un compte pour la replication different du rootdn.
$ cat Replicator.ldif
dn: cn=replicator,ou=System,dc=int-evry,dc=fr
cn: replicator
sn: REPLICATOR SN
objectClass: person
userPassword: {crypt}fgtyp5LztXllw
$ ldapadd -f ./Replicator.ldif -x -D“cn=admin,dc=int-evry,dc=fr” -W -h corne
Enter LDAP Password:
adding new entry “cn=replicator,ou=System,dc=int-evry,dc=fr”
12.2 Configuration du maître
Les sections ACL et database du fichier de configuration slapd sont modifiés. attention dans la section replica avec une bindmethod=simple (ce serai different avec kerberos) le mot de passe qui suit dans credentials doit être en clair !.
$ cat /etc/openldap/slapd.conf
access to attr=userPassword
by self write
by anonymous auth
by dn=“cn=admin,dc=int-evry,dc=fr” write
by dn=“cn=replicator,ou=System,dc=int-evry,dc=fr” write
by * none
access to *
by self read
by dn=“cn=admin,dc=int-evry,dc=fr” write
by dn=“cn=replicator,ou=System,dc=int-evry,dc=fr” write
by * read
database ldbm
suffix “dc=int-evry, dc=fr”
rootdn “cn=admin, dc=int-evry, dc=fr”
rootpw {crypt}REYTjkmLCELfk
directory /var/lib/ldap/int
replica host=esclave.int-evry.fr
binddn=“cn=replicator,ou=System,dc=int-evry,dc=fr”
bindmethod=simple credentials=pass
replogfile /var/lib/ldap/replica/replogfile
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ eq
index cn,mail,surname,givenname eq,subinitial
12.3 Configuration de l'esclave
Sur l'esclave on modifie également les ACL pour donner tous les droits au compte de réplication. la section database est modifiée afin de prendre en compte le dn du compte de replica definit dans la section replica du maitre (binddn=) .
$ cat /etc/openldap/slapd.conf
#ACL
access to …
…
by dn=“cn=replicator,ou=System,dc=int-evry,dc=fr” write
…
database ldbm
suffix “dc=int-evry, dc=fr”
rootdn “cn=admin, dc=int-evry, dc=fr”
rootpw {crypt}REYTjkmLCELfk
directory /var/lib/ldap/int
updatedn “cn=replicator,ou=System,dc=int-evry,dc=fr”
updateref “ldap://maitre.int-evry.fr:389”
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ eq
index cn,mail,surname,givenname eq,subinitial
12.4 Mise en place
Apres avoir prédéfinis les fichiers de configuration ci-dessus, et crée le compte de réplication, il faut maintenant arrêter le serveur maître afin de récuperer la base ldap.
$ /etc/init.d/ldap stop
Arrêt de slapd : [ OK ]
On récupère les fichiers de la base ldap du maître sur l'esclave
$ cd /var/lib/ldap/int
$ ftp maitre
>cd /var/lib/ldap/int
>mget *.dbb # dans le cas d'un ldap utilisant db3 au lieu de gdbm !
>bye
$ chown ldap:ldap *.dbb
Enfin on relance ldap sur le maître et sur l'esclave.
#Maître
$ /etc/init.d/ldap start
Starting slapd: [ OK ]
Starting slurpd: [ OK ]
#Esclave
$ /etc/init.d/ldap start
Starting slapd: [ OK ]
12.5 Démonstration
12.5.1 Lancement d'une modification sur le maître.
#Maître
$ ldapmodify -f ./replace-host.ldif -x -W -D “cn=admin,dc=int-evry,dc=fr”
Enter LDAP Password:
modifying entry “uid=test,ou=People,dc=int-evry,dc=fr”
#log Maître
Jan 25 18:39:39 openldap slapd[5988]: daemon: conn=52 fd=24 connection from
IP=157.159.10.16:33986 (IP=157.159.10.16:34049) accepted.
Jan 25 18:39:39 openldap slapd[5995]: conn=52 op=0 BIND
dn=“CN=ADMIN,DC=INT-EVRY,DC=FR” method=128
Jan 25 18:39:39 openldap slapd[5995]: conn=52 op=0 RESULT tag=97 err=0 text=
Jan 25 18:39:39 openldap slapd[6003]: conn=52 op=1
MOD dn=“uid=test,ou=People,dc=int-evry,dc=fr”
Jan 25 18:39:40 openldap slapd[6003]: conn=52 op=1 RESULT tag=103 err=0 text=
Jan 25 18:39:40 openldap slapd[5995]: conn=52 op=2 UNBIND
Jan 25 18:39:40 openldap slapd[5995]: conn=-1 fd=24 closed
#log esclave
Jan 25 18:39:40 ur slapd[6369]: conn=1 op=5
MOD dn=“uid=test,ou=People,dc=int-evry,dc=fr”
Jan 25 18:39:41 ur slapd[6369]: conn=1 op=5 RESULT tag=103 err=0 text=
12.5.2 Fichiers de replication, explication
Explication: Merci à Vincent MATHIEU Vincent.Mathieu@univ-nancy2.fr
1
slurpd utilise comme répertoire de travail le sous-répertoire replica du répertoire précisé par l'option -t du lancement du démon.
2
slapd met les informations de modification dans le fichier indiqué par la directive replogfile du fichier de conf.
3
slurpd puise ses infos et vide ce fichier, qui sert ainsi de communicationentre les 2 processus. Ca permet un fonctionnement asynchrone, et l'arrêt-relance non synchronisé des 2 processus.
4
slurpd inscrit les infos de mises à jour dans le fichier slurp.replog de sonrépertoire de travail, avec un marqueur de temps (time). C'est un fichier qui s'agrandit indéfiniment.
5
slurpd tente de mettre à jour les réplicas. En cas d'erreur, il va créer un fichier de nom NomDuReplica.rej (reject). Il est possible ultérieurement de rejouer ce fichier des rejets.
6
Il met à jour à chaque traitement le fichier slurpd.status. Ce fichier contient une ligne par esclave. la ligne comprend un indicateur de temps identique au marqueur de temps du fichier slurpd.replog. C'est grâce à ce fichier qu'il sait pour chaque esclave où il en est des mises à jour.
A noter que le fichier des reject n'est mis à jour que lors de tentative de maj défectueuse d'un esclave LDAP (par exemple, incohérence dans les schémas, …); si l'esclave n'est pas dispo, ce n'est pas considéré comme une erreur, slurpd tentera une mise à jour plus tard pour cet esclave.
A noter également qu'il faut prévoir une moulinette qui nettoie de temps en temps le fichier slurpd.replog.
[root@openldap /var/lib/ldap/replica]
$ ls -al
total 16
drwxr-xr-x 2 root root 4096 Jan 25 17:29 .
drwx—— 7 ldap ldap 4096 Jan 25 17:08 ..
-rw-r–r– 1 ldap root 0 Jan 25 18:39 replogfile
-rw-r–r– 1 ldap root 0 Jan 25 18:39 replogfile.lock
-rw-r–r– 1 root root 3678 Jan 25 18:39 slurpd.replog
-rw-r–r– 1 root root 0 Jan 25 18:39 slurpd.replog.lock
-rw-r–r– 1 root root 30 Jan 25 18:39 slurpd.status
-rw-r–r– 1 root root 0 Jan 25 18:34 slurpd.status.lock
[root@openldap /var/lib/ldap/replica]
$ tail -14 slurpd.replog
replica: ur.int-evry.fr
time: 1011980380
dn: uid=test,ou=People,dc=int-evry,dc=fr
changetype: modify
replace: host
host: hostname0.int-evry.fr
-
replace: modifiersName
modifiersName: cn=admin, dc=int-evry, dc=fr
-
replace: modifyTimestamp
modifyTimestamp: 20020125173939Z
-
[root@openldap /var/lib/ldap/replica]
$ cat slurpd.status
ur.int-evry.fr:0:1011980380:0
12.6 Rejouer une réplication rejetée
Il se peut que la réplication ne se fasse pas, c'est le cas par exemple quand on modifie le schema sur le master pour ajouter de nouvelles objectclass/attribut et qu'on ne le fait pas sur le slave !.
12.6.1 Fichier de rejet
[root@corbeau /var/lib/ldap/replica]
-rw-r—– 1 root root 2990 Mar 13 19:42 corne.int-evry.fr:0.rej
[root@corbeau /var/lib/ldap/replica]
$ more corne.int-evry.fr:0.rej
ERROR: Undefined attribute type
replica: corne.int-evry.fr:0
time: 1015551248.0
dn: uid=doutrele,ou=People,dc=int-evry,dc=fr
changetype: modify
add: maildeliveryoption
maildeliveryoption: mailbox
-
replace: modifiersName
modifiersName: cn=admin, dc=int-evry, dc=fr
-
replace: modifyTimestamp
modifyTimestamp: 20020308013406Z
-
$ slurpd -r ./corne.int-evry.fr\:0.rej -o
Processing in one-shot mode:
9 total replication records in file,
9 replication records to process.
12.6.2 Problematique du timestamp
Ici un problème de timestamp lié à une difference de date entre le master et le slave ainsi qu'une application peut-etre trop tardive du fichier, refuse de repliquer .
[root@corbeau /var/lib/ldap/replica]
$ slurpd -r ./corne.int-evry.fr\:0.rej -o -d 65535
Config: opening config file “/etc/openldap/slapd.conf”
Config:….
…
begin replication thread for corne.int-evry.fr:0
Replica corne.int-evry.fr:0, skip repl record for uid=doutrele,ou=People,dc=int-evry,dc=fr (old)
…. 9 fois …
end replication thread for corne.int-evry.fr:0
slurpd: terminated.
12.6.3 Manipulations sur le timestamp
Le fichier slurpd.status maintien la date (en secondes depuis 1900 !) à laquelle à eu lieu la derniere replication pour le replica en question.
[root@openldap /var/lib/ldap/replica]
$ cat slurpd.status
ldap1.int-evry.fr:0:1099929945:0
ldap2.int-evry.fr:0:1099929945:0
Il est parfois interesent de convertir cette date en seconde en une date plus lisible ;
$ perl -e '($s,$m,$h,$dm,$mt,$y,$wday,$yday,$isdst) = localtime(1099929945);printf(“%02d:%02d:%02d-%02d/%02d/%04d\n”,$h, $m, $s, ,$dm , $mt+1, $y+1900);'
17:05:45-08/11/2004
Inversement, obtenir la date du momment en seconde depuis 1900 :
$ perl -e '$tm=time; print “$tm\n”;'
1099931104
12.6.4 Rejouer apres modification du timestamp
Pour rejouer un fichier de rejet, il faudra donc soit retirer ou modifier (antidater) l'entrée timestamp du fichier slurpd.status soit modifier les entrées timestamp du fichier de rejet afin quelles aient une date courante.
Exemple ici où l'on rejoue plus de 7500 modifications (2 par entrées ) apres antidater le slurpd.status et apres avoir arreter le slurpd daemon lancé par /etc/init/ldap ! afin d'eviter qu'il y ait une autre modification en parallele.
Replica ldap1.int-evry.fr:0, skip repl record for uid=test,ou=People,dc=int-evry,dc=fr (old)
[root@openldap /var/lib/ldap/replica]
$ /usr/sbin/slurpd -r /var/lib/ldap/replica/ldap1.int-evry.fr:0.rej -o -d 512
@(#) $OpenLDAP: slurpd 2.1.29 (Apr 14 2004 14:57:16) $
root@tweety.devel.redhat.com:/usr/src/build/387567-i386/BUILD/openldap-2.1.29/build-servers/servers/slurpd
Processing in one-shot mode:
13583 total replication records in file,
13583 replication records to process.
request 1 done
request 2 done
…
12.7 Problème de Replication
Attention à la propiété du répertoire de réplication, /var/lib/ldap/replica sur ma config Fedora Core 2 !. Par défaut ce répertoire appartient a root, hors slapd doit écrire son replogfile à cet endroit.
[root@openldap /var/lib/ldap/replica]
$ ls -al
total 16
drwxr-xr-x 2 ldap root 4096 Aug 11 14:23 .
drwx—— 5 ldap ldap 4096 Aug 11 14:08 ..
-rw-r–r– 1 ldap ldap 0 Aug 11 14:23 replogfile
-rw-r–r– 1 ldap ldap 0 Aug 11 14:23 replogfile.lock
-rw-r–r– 1 root root 505 Aug 11 14:23 slurpd.replog
-rw-r–r– 1 root root 0 Aug 11 14:23 slurpd.replog.lock
-rw-r–r– 1 root root 160 Aug 11 14:23 slurpd.status
-rw-r–r– 1 root root 0 Aug 11 14:23 slurpd.status.lock
12.8 Configuration PAM
L'une des utilisations d'un réplica, est de permettre aux clients de s'authentifier sur l'un ou l'autre des serveurs. Cela repond au probleme de panne, et permet aussi en exploitation normale de répartir la charge. En ce qui concerne PAM, il suffit de modifier le fichier de configuaration /etc/ldap.conf en conséquence:
$ cat /etc/ldap.conf | grep host
host openldap.int-evry.fr ur.int-evry.fr
il suffit donc lister les serveurs ldap (séparés par un espace) dans la directive host de /etc/ldap.conf.
Pour d'autres programmes comme les commandes shell openldap (ldapsearch, ldapmodify ..) ou automount par exemple, c'est /etc/openldap/ldap.conf qui sera lu !
$ grep HOST /etc/openldap/ldap.conf
HOST openldap.int-evry.fr ur.int-evry.fr
13 Réplication Partielle
13.1 Principes
Il peut être interessent d'avoir un replica contenant seulement une partie du DIT et/ou une partie des atrributs/objectclass du master. Dans cet exemple nous allons créer un replica dédié pages blanches, contenant uniquement la branche ou=people,dc=int-evry,dc=fr dépourvue des fonctionnalitées authentification système unix, donc dépourvue des objectclass PosixAccount et shadowAccount ainsi que les attributs associés (sauf ceux necessaires ``MUST
des autres objectclass; exp: uid !).
13.2 Initialisation du replica
13.3 Compte de replication partiel
Insertion du compte de replication partiel dans l'oberescence réduite à ou=people.
$ cat /usr/local/Migratemci/Ldif/replicator-partial.ldif
dn: ou=System,ou=people,dc=int-evry,dc=fr
ou: System
objectClass: top
objectClass: organizationalUnit
dn: cn=replicator,ou=System,ou=people,dc=int-evry,dc=fr
objectClass: person
sn: REPLICATOR SN
cn: replicator
userPassword:: e0NSWVBUfVg4aHUseU9UUjRlb1E=
$slapadd -f /etc/openldap/slapd.conf -l Ldif/replicator-partial.ldif
13.4 Extraction du subtree ou=people
Le replica partiel doit être initialialisé avec une base partielle !. On va donc extraire du master un ldif contenant uniquement l'arborescence desirée. (l'option -s de slapcat est un patch de la commande originale, je pense qu'elle devrait etre intégré dans les futures versions openldap, cf liste openldap-software ).
$ /usr/sbin/slapcat -b dc=int-evry,dc=fr -s ou=people,dc=int-evry,dc=fr \
-f /etc/openldap/slapd.conf > dump-ou=people.ldif
Puis on retire les attributs non desirables sur le replica pages blanches:
$ cat remove-posix-account.pl
#!/usr/bin/perl
open (F1,“<dump-ou=people.ldif”) || die “ pb $!”;
open (FOUT,“>dump-no-posix.ldif”);
while ($ligne1 = <F1>) {
if ($ligne1 =~ /Account|uidNumber|gidNumber|loginShell|homeDirectory|\
gecos|shadowLastChange/ )
{next;}
else {
print FOUT ( $ligne1 );}
}
$ ./remove-posix-account.pl
13.5 Initialisation du replica
Sur le replica on récupère le fichier ldif travaillés ci-dessus et on crée la base ldap:
sftp> get dump-no-posix.ldif
[root@ldaptux /var/lib/ldap/int-evry]
$ slapadd -f /etc/openldap/slapd_int-evry.conf -l ./dump-no-posix.ldif
$ chown ldap:ldap *
13.6 Configuration du master
database bdb
suffix “dc=int-evry, dc=fr”
rootdn “cn=root, dc=int-evry, dc=fr”
rootpw {crypt}rfG0trfN67nDn6
directory /var/lib/ldap/int
#cachesize 6000
#checkpoint 100000 360
#dbnosync
#readonly on
replica host=ldaptux.int-evry.fr:3006
#suffix limité a ou=people
suffix=“ou=people,dc=int-evry,dc=fr”
#on retire les objectclass/attributs indésirables
attr!=“posixAccount,shadowAccount,loginShell,homeDirectory,\
uidNumber,gidNumber,gecos”
binddn=“cn=replicator,ou=System,ou=people,dc=int-evry,dc=fr”
bindmethod=simple credentials=secret
replogfile /var/lib/ldap/replica/replogfile
13.7 Configuration du replica partiel
access to attr=userPassword
by self write
by anonymous auth
by dn=“cn=replicator,ou=System,ou=people,dc=int-evry,dc=fr” write
by * none
access to *
by self read
by dn=“uid=procacci,ou=people,dc=int-evry,dc=fr” write
by dn=“cn=replicator,ou=system,ou=people,dc=int-evry,dc=fr” write
by * none
schemacheck on
database bdb
suffix “ou=people,dc=int-evry,dc=fr”
rootdn “uid=procacci,ou=people,dc=int-evry,dc=fr
rootpw {crypt}ttG0lY6U7nDn6
directory /var/lib/ldap/int-evry
updatedn “cn=replicator,ou=system,ou=people,dc=int-evry,dc=fr”
updateref “ldap://corbeau.int-evry.fr:389”
#cachesize 100
#checkpoint 10 5
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ eq
index cn,mail,surname,givenname eq,subinitial
13.8 Demarrage et test
[root@ldaptux /var/lib/ldap/int-evry]
$ /etc/init.d/ldap_int-evry start
Modification des attributs telephoneNumber et loginShell sur le master slapd logs:
Master
Mar 7 18:12:36 corbeau slapd[4796]: conn=8 op=5 MOD dn=“uid=test, ou=People, \
dc=int-evry,dc=fr”
Mar 7 18:12:36 corbeau slapd[4796]: conn=8 op=5 MOD attr=telephoneNumber \
loginShell userPassword
Mar 7 18:12:36 corbeau slapd[4796]: conn=8 op=5 RESULT tag=103 err=0 text=
Mar 7 18:12:36 corbeau slapd[4806]: conn=8 op=6 SRCH base=“uid=test,ou=People,\
dc=int-evry,dc=fr” scope=0 filter=”(objectClass=*)“
Mar 7 18:12:36 corbeau slapd[4806]: conn=8 op=6 SEARCH RESULT tag=101 err=0 \
nentries=1 text=
replica
Mar 7 18:47:44 ldaptux slapd[22618]: conn=0 op=3 MOD dn=“uid=test,ou=People,\
dc=int-evry,dc=fr”
Mar 7 18:47:44 ldaptux slapd[22618]: conn=0 op=3 RESULT tag=103 err=0 text=
[root@corbeau /var/lib/ldap/replica]
tail slurpd.replog
replica: ldaptux.int-evry.fr:3006
time: 1047057156
dn: uid=test,ou=People,dc=int-evry,dc=fr
changetype: modify
replace: telephoneNumber
telephoneNumber: 4408
-
replace: entryCSN
entryCSN: 2003030717:12:36Z#0x0001#0#0000
-
replace: modifiersName
modifiersName: cn=root,dc=int-evry,dc=fr
-
replace: modifyTimestamp
modifyTimestamp: 20030307171236Z
-
Verification
$ ldapsearch -x uid=test -h corbeau -D “uid=test,ou=people,dc=int-evry,dc=fr” \
-W telephoneNumber loginShell -LLL
Enter LDAP Password:
dn: uid=test,ou=People,dc=int-evry,dc=fr
telephoneNumber: 4408
loginShell: /usr/local/bin/bash
$ ldapsearch -x uid=test -h ldaptux -p 3006 -b ou=people,dc=int-evry,dc=fr \
-D “uid=test,ou=people,dc=int-evry,dc=fr” -W telephoneNumber loginShell -LLL
Enter LDAP Password:
dn: uid=test,ou=People,dc=int-evry,dc=fr
telephoneNumber: 4408
Ok
14 Groups
Mise en place de groupes afin de déléguer l'administration des données de l'annuaire.
14.1 Création des groupes
Définition ldif de 2 groupes afin de gérer d'une part les attributs concernants les services géneraux, d'autre part les attributs relatifs aux Ressources Humaines.
$ cat group-servG.ldif
dn: cn=servG,ou=Groups,dc=int-evry,dc=fr
cn: administrateurs services generaux
objectclass: groupOfNames
objectclass: top
member: uid=test,ou=people,dc=int-evry,dc=fr
member: uid=riquet,ou=people,dc=int-evry,dc=fr
$ cat group-RH2.ldif
dn: cn=RH2,ou=Groups,dc=int-evry,dc=fr
cn: administrateurs RH2
objectclass: groupOfNames
objectclass: top
Member: uid=savoye,ou=People,dc=int-evry,dc=fr
Member: uid=herve,ou=People,dc=int-evry,dc=fr
$ ldapadd -x -D “cn=admin,dc=int-evry,dc=fr” -W -f ./group-servG.ldif
$ ldapadd -x -D “cn=admin,dc=int-evry,dc=fr” -W -f ./group-RH2.ldif
14.2 ACL
Définition dans le fichier slapd.conf d'ACL utilisants ces groupes. Ici on autorise le groupe servG à modifier le numero de téléphone, la pièce, le code postal et l'adresse postale, de même le groupe RH pourra modifier le type d'employé, le département … .
access to dn=“ou=people,dc=int-evry,dc=fr”
attrs=telephoneNumber,roomNumber,postalCode,postalAddress
by group=“cn=servG,ou=Groups,dc=int-evry,dc=fr” write
by dn=“cn=admin,dc=int-evry,dc=fr” write
by dn=“cn=replicator,ou=System,dc=int-evry,dc=fr” write
by * read
access to dn=“ou=people,dc=int-evry,dc=fr”
attrs=employeeType,departmentNumber,title,cn,givenName,sn
by group=“cn=RH2,ou=Groups,dc=int-evry,dc=fr” write
by dn=“cn=admin,dc=int-evry,dc=fr” write
by dn=“cn=replicator,ou=System,dc=int-evry,dc=fr” write
by * read
14.3 Exemple d'utilisation
Ici un employé des ressources humaines va s'authentifier sur le serveur ldap (bind individuel) pour modifier le titre d'une personne et ajouter l'attribut de département (détruit au préalable, cf # du fichier ldif) de cette personne.
$ cat modify-rh.ldif
dn: uid=procacci,ou=People,dc=int-evry,dc=fr
changetype: modify
replace: title
title: Ingenieur
#-
#delete: departmentNumber
-
add: departmentNumber
departmentNumber: MCI
#-
#changetype: modify
#replace: mailHost
#mailHost: bidon
$ ldapmodify -x -D “uid=herve,ou=people,dc=int-evry,dc=fr” -W -f ./modify-rh.ldif -h corbeau
Enter LDAP Password:
modifying entry “uid=procacci,ou=People,dc=int-evry,dc=fr”
$ldapsearch -x uid=procacci departmentNumber title
dn: uid=procacci,ou=People,dc=int-evry,dc=fr
title: Ingenieur
departmentNumber: MCI
Si on revient sur le fichier modify-rh.ldif ci dessus, en décommentant le remplacement du mailHost, attribut pour lequel le groupe RH n'a pas le droit d'écriture (cf ACL), le serveur répond ldap_modify: Insufficient access et annule entierement l'opération (pas de modification du title).
15 Sécurité SSL TLS
Je recommande de suivre http://www.openldap.org/faq/data/cache/185.html ce qui suis est une suite d'étapes pas à pas pour information/aide .
15.1 Ldaps, start TLS
Mettre le serveur openldap en écoute sur un port sécurisé; ldaps port 636 ou start TLS qui utilise a priori le port 389 (!?).
15.1.1 Certificat
Création d'un certificat 'selfsigned'. Ou bien signer avec une autorité de certification préexistante; voir: http://www.int-evry.fr/s2ia/user/procacci/Doc/openssl.html#htoc17
$ mkdir /var/myca
$ cd /var/myca/
[root@corbeau /var/myca]
$ /usr/share/ssl/misc/CA -newca
CA certificate filename (or enter to create)
Making CA certificate …
Generating a 1024 bit RSA private key
…………………………………………………..++++++
……………………………………………++++++
writing new private key to './demoCA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
phrase is too short, needs to be at least 4 chars
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
—–
Country Name (2 letter code) [GB]:FR
State or Province Name (full name) [Berkshire]:Essonne
Locality Name (eg, city) [Newbury]:Evry
Organization Name (eg, company) [My Company Ltd]:INT
Organizational Unit Name (eg, section) []:MCI
Common Name (eg, your name or your server's hostname) []:corbeau.int-evry.fr
Email Address []:root@corbeau.int-evry.fr
[root@corbeau /var/myca]
$ ls demoCA/
cacert.pem certs crl index.txt newcerts private serial
Création d'une requête de certificat et d'une clé privée pour le serveur
[root@corbeau /var/myca]
$ openssl req -new -nodes -keyout newreq.pem -out newreq.pem
Generating a 1024 bit RSA private key
……………++++++
………………………..++++++
writing new private key to 'newreq.pem'
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
—–
Country Name (2 letter code) [GB]:FR
State or Province Name (full name) [Berkshire]:Essonne
Locality Name (eg, city) [Newbury]:Evry
Organization Name (eg, company) [My Company Ltd]:INT-Evry
Organizational Unit Name (eg, section) []:MCI
Common Name (eg, your name or your server's hostname) []:corbeau.int-evry.fr
Email Address []:jehan@corbeau.int-evry.fr
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@corbeau /var/myca]
$ ls
demoCA newreq.pem
Utilisation du CA pour signer le cert request
[root@corbeau /var/myca]
$ /usr/share/ssl/misc/CA -sign
Using configuration from /usr/share/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: May 28 22:01:04 2003 GMT
Not After : May 27 22:01:04 2004 GMT
Subject:
countryName = FR
stateOrProvinceName = Essonne
localityName = Evry
organizationName = INT-Evry
organizationalUnitName = MCI
commonName = corbeau.int-evry.fr
emailAddress = jehan@corbeau.int-evry.fr
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
97:D2:DF:35:37:A1:45:20:C3:5C:DF:07:08:F3:B5:0A:2A:F6:0B:D4
X509v3 Authority Key Identifier:
keyid:6A:EA:69:1F:6C:23:07:02:05:42:D4:53:BB:60:F5:53:0A:78:71:DF
DirName:/C=FR/ST=Essonne/L=Evry/O=INT/OU=MCI/CN=corbeau.int-evry.fr/emailAddress=root@corbeau.int-evry.fr
serial:00
Certificate is to be certified until May 27 22:01:04 2004 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: md5WithRSAEncryption
Issuer: C=FR, ST=Essonne, L=Evry, O=INT, OU=MCI, CN=corbeau.int-evry.fr/emailAddress=root@corbeau.int-evry.fr
Validity
Not Before: May 28 22:01:04 2003 GMT
Not After : May 27 22:01:04 2004 GMT
Subject: C=FR, ST=Essonne, L=Evry, O=INT-Evry, OU=MCI, CN=corbeau.int-evry.fr/emailAddress=jehan@corbeau.int-evry.fr
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:c9:2d:b0:f8:ea:15:f4:4e:54:c0:f8:62:9b:8c:
4d:37:1c:1f:c4:c2:1a:b8:d2:a6:7d:b1:24:e6:d5:
60:77:05:82:3f:9e:3c:39:e0:6c:84:ae:19:db:33:
34:62:43:37:60:68:4a:77:39:ad:c1:00:47:5b:69:
63:8d:cb:10:c6:4b:a5:6a:eb:f9:c0:4b:3c:fc:2d:
55:95:d4:75:5c:65:34:a9:00:5c:75:77:14:2d:bf:
19:d0:87:bb:16:83:fe:c9:13:a6:14:5b:fd:7a:ee:
61:b0:f9:53:77:00:64:ff:2e:1f:11:d4:48:42:e9:
7c:5e:5a:47:79:58:22:50:e3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
97:D2:DF:35:37:A1:45:20:C3:5C:DF:07:08:F3:B5:0A:2A:F6:0B:D4
X509v3 Authority Key Identifier:
keyid:6A:EA:69:1F:6C:23:07:02:05:42:D4:53:BB:60:F5:53:0A:78:71:DF
DirName:/C=FR/ST=Essonne/L=Evry/O=INT/OU=MCI/CN=corbeau.int-evry.fr/emailAddress=root@corbeau.int-evry.fr
serial:00
Signature Algorithm: md5WithRSAEncryption
44:f6:95:f1:38:eb:61:3e:df:92:e4:2d:af:9c:a4:57:45:a9:
b1:24:6b:c4:e4:bf:ff:b6:41:c4:f3:b8:df:26:07:d3:c7:bc:
27:19:ca:74:7d:0b:22:c0:ef:05:cd:29:9c:ab:2d:13:b6:3d:
4f:11:4b:01:66:b7:c8:89:8d:0e:fe:ec:7a:ab:64:9c:af:8b:
c9:25:30:ca:63:23:64:d6:4b:b3:e0:a2:ee:ba:7c:bd:0b:a3:
56:5b:43:24:05:51:01:a9:b2:08:09:ad:6f:89:fe:95:f4:7c:
6c:30:12:18:6e:b7:39:bc:f0:3f:f4:9a:79:ec:de:8f:ee:26:
a7:bc
—–BEGIN CERTIFICATE—–
MIIDvzCCAyigAwIBAgIBATANBgkqhkiG9w0BAQQFADCBkTELMAkGA1UEBhMCRlIx
EDAOBgNVBAgTB0Vzc29ubmUxDTALBgNVBAcTBEV2cnkxDDAKBgNVBAoTA0lOVDEM
MAoGA1UECxMDTUNJMRwwGgYDVQQDExNjb3JiZWF1LmludC1ldnJ5LmZyMScwJQYJ
KoZIhvcNAQkBFhhyb290QGNvcmJlYXUuaW50LWV2cnkuZnIwHhcNMDMwNTI4MjIw
MTA0WhcNMDQwNTI3MjIwMTA0WjCBlzELMAkGA1UEBhMCRlIxEDAOBgNVBAgTB0Vz
c29ubmUxDTALBgNVBAcTBEV2cnkxETAPBgNVBAoTCElOVC1FdnJ5MQwwCgYDVQQL
EwNNQ0kxHDAaBgNVBAMTE2NvcmJlYXUuaW50LWV2cnkuZnIxKDAmBgkqhkiG9w0B
CQEWGWplaGFuQGNvcmJlYXUuaW50LWV2cnkuZnIwgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAMktsPjqFfROVMD4YpuMTTccH8TCGrjSpn2xJObVYHcFgj+ePDng
bISuGdszNGJDN2BoSnc5rcEAR1tpY43LEMZLpWrr+cBLPPwtVZXUdVxlNKkAXHV3
FC2/GdCHuxaD/skTphRb/XruYbD5U3cAZP8uHxHUSELpfF5aR3lYIlDjAgMBAAGj
ggEdMIIBGTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVy
YXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUl9LfNTehRSDDXN8HCPO1Cir2C9Qw
gb4GA1UdIwSBtjCBs4AUauppH2wjBwIFQtRTu2D1Uwp4cd+hgZekgZQwgZExCzAJ
BgNVBAYTAkZSMRAwDgYDVQQIEwdFc3Nvbm5lMQ0wCwYDVQQHEwRFdnJ5MQwwCgYD
VQQKEwNJTlQxDDAKBgNVBAsTA01DSTEcMBoGA1UEAxMTY29yYmVhdS5pbnQtZXZy
eS5mcjEnMCUGCSqGSIb3DQEJARYYcm9vdEBjb3JiZWF1LmludC1ldnJ5LmZyggEA
MA0GCSqGSIb3DQEBBAUAA4GBAET2lfE462E+35LkLa+cpFdFqbEka8Tkv/+2QcTz
uN8mB9PHvCcZynR9CyLA7wXNKZyrLRO2PU8RSwFmt8iJjQ7+7HqrZJyvi8klMMpj
I2TWS7Pgou66fL0Lo1ZbQyQFUQGpsggJrW+J/pX0fGwwEhhutzm88D/0mnns3o/u
Jqe8
—–END CERTIFICATE—–
Signed certificate is in newcert.pem
[root@corbeau /var/myca]
$ ls
demoCA newcert.pem newreq.pem
15.2 Configuration TLS de slapd et clients
Copie des fichiers dans l'arborescence serveur openldap et prise en compte des modes d'acces (slapd tourne sous le user ldap !)
[root@corbeau /var/myca]
$ cp demoCA/cacert.pem /etc/openldap/cacert.pem
$ cp newcert.pem /etc/openldap/servercrt.pem
$ cp newreq.pem /etc/openldap/serverkey.pem
$ chmod 600 /etc/openldap/serverkey.pem
$ chown ldap:ldap /etc/openldap/serverkey.pem
Edition du slapd.conf
$ grep TLS /etc/openldap/slapd.conf
TLSCACertificateFile /etc/openldap/cacert.pem
TLSCertificateFile /etc/openldap/servercrt.pem
TLSCertificateKeyFile /etc/openldap/serverkey.pem
copie du certificat de la CA (certificat d'autorité qui signe ) dans /etc pour les outils clients et configuration en conséquence des outils clients
[root@corbeau /var/myca]
$ cp demoCA/cacert.pem /etc
$ grep TLS /etc/openldap/ldap.conf
TLS_CACERT /etc/cacert.pem
15.3 Lancement de slapd avec TLS
$ /etc/init.d/ldap restart
Stopping slapd: [ OK ]
Starting slapd: [ OK ]
## cela lance:
## slapd -f /etc/openldap/slapd.conf -u ldap -h “ldap:/// ldaps:/”
15.4 Verification, avec nmap et lsof
$ nmap -p 636 calaz.int-evry.fr
Starting nmap 3.75 ( http://www.insecure.org/nmap/ ) at 2005-01-26 20:07 CET
Interesting ports on calaz.int-evry.fr (157.159.50.197):
PORT STATE SERVICE
636/tcp open ldapssl
$ lsof -i tcp:636,389
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
slapd 9259 ldap 6u IPv6 11523812 TCP *:ldap (LISTEN)
slapd 9259 ldap 7u IPv4 11523813 TCP *:ldap (LISTEN)
slapd 9259 ldap 8u IPv6 11523816 TCP *:ldaps (LISTEN)
slapd 9259 ldap 9u IPv4 11523817 TCP *:ldaps (LISTEN)
15.5 Exemple d'utilisation
Utiliser l'option ``-ZZ de ldapsearch pour forcer le start TLS.
$ ldapsearch -x uid=test -H ldap://corbeau.int-evry.fr/ -ZZ
15.5.1 Ecoutes réseau
Verifions que sans et avec le start TLS on ne voit pas passer la meme chose sur le réseau, respctivement échange en clair puis chiffré.
15.5.2 Echange en clair
$ ldapsearch -x uid=test -H ldap://calaz.int-evry.fr -D “cn=admin,dc=int-evry,dc=fr” -W cn -LLL
Enter LDAP Password:
#en parrallele on capture avec ethereal:
$ tethereal -i lo port 389
Capturing on lo
0.000000 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [SYN] Seq=0 Ack=0 Win=32767 Len=0 MSS=16396 TSV=1415942728 TSER=0 WS=2
0.021630 157.159.50.197 → 157.159.50.197 TCP ldap > 50545 [SYN, ACK] Seq=0 Ack=1 Win=32767 Len=0 MSS=16396 TSV=1415942728 TSER=1415942728 WS=2
0.021960 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [ACK] Seq=1 Ack=1 Win=32768 Len=0 TSV=1415942728 TSER=1415942728
0.020384 157.159.50.197 → 157.159.50.197 LDAP MsgId=1 Bind Request, DN=cn=admin,dc=int-evry,dc=fr
0.020419 157.159.50.197 → 157.159.50.197 TCP ldap > 50545 [ACK] Seq=1 Ack=48 Win=32768 Len=0 TSV=1415942749 TSER=1415942749
0.084645 157.159.50.197 → 157.159.50.197 LDAP MsgId=1 Bind Result
0.084682 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [ACK] Seq=48 Ack=15 Win=32768 Len=0 TSV=1415942813 TSER=1415942813
0.085745 157.159.50.197 → 157.159.50.197 LDAP MsgId=2 Search Request, Base DN=dc=int-evry,dc=fr
0.085761 157.159.50.197 → 157.159.50.197 TCP ldap > 50545 [ACK] Seq=15 Ack=108 Win=32768 Len=0 TSV=1415942814 TSER=1415942814
0.086809 157.159.50.197 → 157.159.50.197 LDAP MsgId=2 Search Entry
0.126120 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [ACK] Seq=108 Ack=90 Win=32768 Len=0 TSV=1415942855 TSER=1415942815
0.176524 157.159.50.197 → 157.159.50.197 LDAP MsgId=2 Search Result
0.176569 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [ACK] Seq=108 Ack=104 Win=32768 Len=0 TSV=1415942905 TSER=1415942905
0.177115 157.159.50.197 → 157.159.50.197 LDAP MsgId=3 Unbind Request
0.177157 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [FIN, ACK] Seq=115 Ack=104 Win=32768 Len=0 TSV=1415942906 TSER=1415942905
0.179402 157.159.50.197 → 157.159.50.197 TCP ldap > 50545 [FIN, ACK] Seq=104 Ack=116 Win=32768 Len=0 TSV=1415942908 TSER=1415942906
0.179427 157.159.50.197 → 157.159.50.197 TCP 50545 > ldap [ACK] Seq=116 Ack=105 Win=32768 Len=0 TSV=1415942908 TSER=1415942908
#retour au resultat ldapsearch:
dn: uid=test,ou=People,dc=int-evry,dc=fr
cn: compte de test mci
L'option follow TCP stream d'ethereal (version graphique) permet de voir clairement le contenue des échanges ldap sur le réseau. En plus du résultat de la requete, on voit ici le binddn suivit de son mot de passe !
.
0-…`(…..cn=admin,dc=int-evry,dc=fr..secret0….a.
……0:…c5..dc=int-evry,dc=fr
..
……………uid..test0…cn0I…dD.$uid=test,ou=People,dc=int-evry,dc=fr0.0…cn1…compte de test mci0….e.
……0….B.
15.5.3 Echange chiffré, start TLS
$ ldapsearch -x uid=test -H ldap://calaz.int-evry.fr -ZZ -D “cn=admin,dc=int-evry,dc=fr” -W cn -LLL
Enter LDAP Password:
#ecoute avec tethereal :
$ tethereal -i lo port 389
Capturing on lo
0.000000 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [SYN] Seq=0 Ack=0 Win=32767 Len=0 MSS=16396 TSV=1416303614 TSER=0 WS=2
0.002919 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [SYN, ACK] Seq=0 Ack=1 Win=32767 Len=0 MSS=16396 TSV=1416303614 TSER=1416303614 WS=2
0.003234 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [ACK] Seq=1 Ack=1 Win=32768 Len=0 TSV=1416303614 TSER=1416303614
0.004259 157.159.50.197 → 157.159.50.197 LDAP MsgId=1 Extended Request
0.004288 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=1 Ack=32 Win=32768 Len=0 TSV=1416303618 TSER=1416303618
0.037014 157.159.50.197 → 157.159.50.197 LDAP MsgId=1 Extended Response
0.037047 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [ACK] Seq=32 Ack=15 Win=32768 Len=0 TSV=1416303651 TSER=1416303651
0.130895 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
0.145397 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
0.150212 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [ACK] Seq=174 Ack=2797 Win=38332 Len=0 TSV=1416303764 TSER=1416303759
0.181431 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
0.220684 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=2797 Ack=500 Win=32768 Len=0 TSV=1416303835 TSER=1416303795
0.365409 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
0.405656 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [ACK] Seq=500 Ack=2856 Win=38332 Len=0 TSV=1416304020 TSER=1416303979
2.770622 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.770661 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=2856 Ack=622 Win=32768 Len=0 TSV=1416306385 TSER=1416306385
2.778834 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.778856 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [ACK] Seq=622 Ack=2946 Win=38332 Len=0 TSV=1416306393 TSER=1416306393
2.798611 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.838266 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=2946 Ack=760 Win=32768 Len=0 TSV=1416306453 TSER=1416306413
2.931956 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.940468 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.940918 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.940941 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=3174 Ack=834 Win=32768 Len=0 TSV=1416306555 TSER=1416306555
2.941010 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.941021 157.159.50.197 → 157.159.50.197 TCP ldap > 50547 [ACK] Seq=3174 Ack=871 Win=32768 Len=0 TSV=1416306555 TSER=1416306555
2.941056 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [FIN, ACK] Seq=871 Ack=3174 Win=38332 Len=0 TSV=1416306555 TSER=1416306555
2.966664 157.159.50.197 → 157.159.50.197 LDAP Invalid LDAP message (Can't parse sequence header: Wrong type for that item)
2.966715 157.159.50.197 → 157.159.50.197 TCP 50547 > ldap [RST] Seq=872 Ack=4045731940 Win=0 Len=0
# retoure au resultat de la requete ldapsearch
dn: uid=test,ou=People,dc=int-evry,dc=fr
cn: compte de test mci
Cette fois-ci, l'option de suivit du stream TCP d'ethereal n'affiche plus rien d'utile au niveau échange ldap, seul l'échange de certificat est visible.
0….w…1.3.6.1.4.1.1466.200370….x.
…
…..0?1”0 ..U….MCI Certificate Authority1.0
..U.
..INT1.0…U….FR0..
050126173836Z.
060126173836Z0..1.0…U….FR1.0…U….Essonne1
0…U….Evry1.0…U.
..GET-INT1
0…U….S2IA1.0…U….calaz.int-evry.fr1%0#..*.H..
…..root@calaz.int-evry.fr0..“0
..*.H..
……….0..
…
16 Meta annuaire
16.1 Principes
Le backend meta d'openldap permet de servir de point d'entré vers plusieurs annuaires de contexte (base DN/suffix) differents. Ainsi il est envisageable pour un groupe comprenant plusieurs entités de se servir de ce backend meta comme point d'entré unique aux differents arbres/annuaires de chacune de ses entités.
Il est egalement possible grace au rewrite engine de redéfinir (map) des attributs qui auraient une signification differente dans les entités du groupe → exemple; l'entité 1 a choisi pour contenir le nom de service d'une personne l'attribut normalisé departmentNumber, l'entité 2 l'attribut normilsé ourganizationalUnit et enfin l'entité 3 l'attribut ``maison
IntEPersUserEntite .
Dans la suite de ce chapitre nous allons monter une maquette sur le groupe fictif ``meta comprenant 3 sous-entités → get-telecom, enstb, int-evry . Le suffix dc=meta,dc=fr sera le point d'entré des 3 annuaires de chacune des entités du groupe. Voici le schema:
—————-dc=meta,dc=fr——————-
| | |
dc=get-telecom,dc=fr dc=int-evry,dc=fr dc=enstb,dc=fr
16.2 Montage et tests des entités du groupe
16.2.1 Construction des entités
Nous créons de toute pièce les annuires des entité get-telecom et enstb, pour l'entité int-evry nous utiliserons une copie de l'annuaire de production à l'INT.
$ slapadd -f /usr/local/openldap-2.2.20-1/etc/openldap/slapd-meta-get.conf -b dc=enstb,dc=fr -l arbre-enstb_meta.ldif
$ slapadd -f /usr/local/openldap-2.2.20-1/etc/openldap/slapd-meta-get.conf -b dc=get-telecom,dc=fr -l arbre-get-telecom_meta.ldif
Pour information, voici le contenu ldif de ces 2 annuaires:
$ cat arbre-enstb_meta.ldif
dn: dc=enstb,dc=fr
dc: enstb
objectClass: top
objectClass: domain
dn: ou=People,dc=enstb,dc=fr
ou: People
objectClass: top
objectClass: organizationalUnit
dn: sn=brouty,ou=People,dc=enstb,dc=fr
cn: Andre Brouty
sn: Brouty
objectClass: top
objectClass: person
objectClass: inetOrgPerson
mail: Andre.Brouty@enstb.fr
givenName: Andre
$ cat arbre-get-telecom_meta.ldif
dn: dc=get-telecom,dc=fr
dc: get-telecom
objectClass: top
objectClass: domain
objectClass: domainRelatedObject
associatedDomain: get-telecom.fr
dn: ou=People,dc=get-telecom,dc=fr
ou: People
objectClass: top
objectClass: organizationalUnit
dn: sn=lautraite,ou=People,dc=get-telecom,dc=fr
cn: Isabelle Lautraite
sn: lautraite
objectClass: top
objectClass: person
objectClass: inetOrgPerson
mail: Isabelle.Lautraite@get-telecom.fr
givenName: Isabelle
16.2.2 Lancement des entités
Lancement d'un serveur propre aux deux entités
Acces systeme
Donner l'acces systeme à l'utilisateur ldap:
$ chown ldap /usr/local/openldap-2.2.20-1/etc/openldap/slapd-meta-get.conf
[root@calaz /usr/local/openldap-2.2.20-1/var/lib/ldap]
$ chown -R ldap:ldap ./get/ ./enstb/
lancement slapd
$ /usr/local/openldap-2.2.20-1/sbin/slapd -u ldap -h “ldap://:9000/” -l local6 -f /usr/local/openldap-2.2.20-1/etc/openldap/slapd-meta-get.conf
Test de requete simple directement sur les annuaires d'entite
$ ldapsearch -x “cn=*” -h localhost -p 9000 -b “dc=get-telecom,dc=fr” -LLL cn
dn: sn=lautraite,ou=People,dc=get-telecom,dc=fr
cn: Isabelle Lautraite
$ ldapsearch -x “cn=*” -h localhost -p 9000 -b “dc=enstb,dc=fr” -LLL cn
dn: sn=brouty,ou=People,dc=enstb,dc=fr
cn: Andre Brouty
16.3 Base meta
16.4 Configuration meta de 1er niveau
Voici un fichier de configuration slapd-meta-get.conf gérant à la fois la ``metabase
et les deux annuaires des entités enstb et get-telecom (pour l'entité int-evry une autre instance de slapd de production est utilisée dans cette maquette).
defaultsearchbase dc=meta,dc=fr
#database meta
database meta
suffix “dc=meta,dc=fr”
uri “ldap://localhost:9000/dc=meta,dc=fr”
suffixmassage “dc=meta,dc=fr” “dc=enstb,dc=fr”
uri “ldap://localhost:9000/dc=meta,dc=fr”
suffixmassage “dc=meta,dc=fr” “dc=get-telecom,dc=fr”
uri “ldap://localhost/dc=meta,dc=fr”
suffixmassage “dc=meta,dc=fr” “dc=int-evry,dc=fr”
lastmod off
#database ENSTB
database bdb
suffix “dc=enstb, dc=fr”
rootdn “cn=admin, dc=enstb, dc=fr”
rootpw {crypt}jpG0l9N67nDn6
directory /usr/local/openldap-2.2.20-1/var/lib/ldap/enstb
# validation de checkpoint dans les log tous les 200K ou toutes les Heure
checkpoint 200 3600
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ,mailHost eq
index cn,mail,surname,givenname eq,subinitial
#
# Nombre d'entree conserver dans le cache
cachesize 3000
#database get-telecom
database bdb
suffix “dc=get-telecom, dc=fr”
rootdn “cn=admin, dc=get-telecom, dc=fr”
rootpw {crypt}jpG0l9N67nDn6
directory /usr/local/openldap-2.2.20-1/var/lib/ldap/get
#readonly on
# validation de checkpoint dans les log tous les 200K ou toutes les Heure
checkpoint 200 3600
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ,mailHost eq
index cn,mail,surname,givenname eq,subinitial
#
# Nombre d'entree conserver dans le cache
cachesize 3000
16.4.1 Exemple de recherche sur la base meta
Une recherche sur la base meta parcours bien les differents annuaires/arbres.
$ ldapsearch -x “cn=*laut*” -h localhost -p 9000 -b “dc=meta,dc=fr” -LLL cn
dn: sn=lautraite,ou=People,dc=meta,dc=fr
cn: Isabelle Lautraite
dn: uid=vaillaut,ou=People,dc=meta,dc=fr
cn: Julien VAILLAUT
La personne cn: Julien VAILLAUT viens de l'entité int-evry et cn: Isabelle Lautraite de l'entité get-telecom, verification:
$ ldapsearch -x “cn=*laut*” -h localhost -b “dc=int-evry,dc=fr” -LLL cn
dn: uid=vaillaut,ou=People,dc=int-evry,dc=fr
cn: Julien VAILLAUT
$ ldapsearch -x “cn=*laut*” -h localhost -p 9000 -b “dc=get-telecom,dc=fr” -LLL cn
dn: sn=lautraite,ou=People,dc=get-telecom,dc=fr
cn: Isabelle Lautraite
16.4.2 Traces dans les log
On voit bien dans les log de slapd que la recherche initiale sur SRCH base=“dc=meta,dc=fr” est aiguillée vers SRCH base=“dc=get-telecom,dc=fr” et SRCH base=“dc=enstb,dc=fr” , ainsi que vers SRCH base=“dc=int-evry,dc=fr” qui tourne sous une autre instance de slapd donc un autre fichier de log non visible ci-dessous !
Jan 19 23:56:21 calaz slapd[29470]: conn=15 fd=12 ACCEPT from IP=127.0.0.1:40761 (IP=0.0.0.0:9000)
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=0 BIND dn=”“ method=128
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=0 RESULT tag=97 err=0 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=1 SRCH base=“dc=meta,dc=fr” scope=2 deref=0 filter=”(cn=*laut*)“
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=1 SRCH attr=cn
Jan 19 23:56:21 calaz slapd[29470]: conn=16 fd=14 ACCEPT from IP=127.0.0.1:40762 (IP=0.0.0.0:9000)
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=0 BIND dn=”“ method=128
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=0 RESULT tag=97 err=0 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=17 fd=16 ACCEPT from IP=127.0.0.1:40763 (IP=0.0.0.0:9000)
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=0 BIND dn=”“ method=128
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=0 RESULT tag=97 err=0 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=1 SRCH base=“dc=get-telecom,dc=fr” scope=2 deref=0 filter=”(cn=*laut*)“
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=1 SRCH attr=cn
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=1 SRCH base=“dc=enstb,dc=fr” scope=2 deref=0 filter=”(cn=*laut*)“
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=1 SRCH attr=cn
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=1 SEARCH RESULT tag=101 err=0 nentries=0 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=1 SEARCH RESULT tag=101 err=0 nentries=2 text=
Jan 19 23:56:21 calaz slapd[29470]: conn=15 op=2 UNBIND
Jan 19 23:56:21 calaz slapd[29470]: conn=15 fd=12 closed
Jan 19 23:56:21 calaz slapd[29470]: conn=16 op=2 UNBIND
Jan 19 23:56:21 calaz slapd[29470]: conn=16 fd=14 closed
Jan 19 23:56:21 calaz slapd[29470]: conn=17 op=2 UNBIND
Jan 19 23:56:21 calaz slapd[29470]: conn=17 fd=16 closed
16.5 Base Meta de 2eme niveau
On peux egalement faire apparaitre chacune des entités du groupe apres le suffix meta, cela rend les entités plus visibles !
16.5.1 Configuration meta
database meta
suffix “dc=meta,dc=fr”
uri “ldap://localhost:9000/dc=enstb,dc=meta,dc=fr”
suffixmassage “dc=enstb,dc=meta,dc=fr” “dc=enstb,dc=fr”
uri “ldap://localhost:9000/dc=get-telecom,dc=meta,dc=fr”
suffixmassage “dc=get-telecom,dc=meta,dc=fr” “dc=get-telecom,dc=fr”
uri “ldap://localhost/dc=int-evry,dc=meta,dc=fr”
suffixmassage “dc=int-evry,dc=meta,dc=fr” “dc=int-evry,dc=fr”
lastmod off
16.5.2 Recherche sur le groupe
Cette fois ci le résultat d'une recherche sur le groupe fait bien apparaitre l'entité d'appartenance de la personne dans le dn:
$ldapsearch -x “cn=*laut*” -h localhost -p 9000 -b “dc=meta,dc=fr” -LLL cn
dn: sn=lautraite,ou=People,dc=get-telecom,dc=meta,dc=fr
cn: Isabelle Lautraite
dn: uid=vaillaut,ou=People,dc=int-evry,dc=meta,dc=fr
cn: Julien VAILLAUT
16.5.3 Recherche meta spécifique à une entité
$ ldapsearch -x “cn=*laut*” -h localhost -p 9000 -b “dc=get-telecom,dc=meta,dc=fr” -LLL cn
dn: sn=lautraite,ou=People,dc=get-telecom,dc=meta,dc=fr
cn: Isabelle Lautraite
16.5.4 Log d'accès de la recherche spécifique
La base meta renvoi une requete uniquement sur la base de l'entité get-telecom:
Jan 20 22:37:07 calaz slapd[7780]: conn=10 fd=12 ACCEPT from IP=127.0.0.1:42122 (IP=0.0.0.0:9000)
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=0 BIND dn=”“ method=128
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=0 RESULT tag=97 err=0 text=
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=1 SRCH base=“dc=get-telecom,dc=meta,dc=fr” scope=2 deref=0 filter=”(cn=*laut*)“
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=1 SRCH attr=cn
Jan 20 22:37:07 calaz slapd[7780]: conn=11 fd=14 ACCEPT from IP=127.0.0.1:42123 (IP=0.0.0.0:9000)
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=0 BIND dn=”“ method=128
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=0 RESULT tag=97 err=0 text=
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=1 SRCH base=“dc=get-telecom,dc=fr” scope=2 deref=0 filter=”(cn=*laut*)“
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=1 SRCH attr=cn
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Jan 20 22:37:07 calaz slapd[7780]: conn=10 op=2 UNBIND
Jan 20 22:37:07 calaz slapd[7780]: conn=10 fd=12 closed
Jan 20 22:37:07 calaz slapd[7780]: conn=11 op=2 UNBIND
Jan 20 22:37:07 calaz slapd[7780]: conn=11 fd=14 closed
16.6 Equivalance d'attributs
Comme évoqué dans les principes en début de chapitre, il est possible de rendre équivalent (map) des attributs distincts entre entités.
16.6.1 Modification de la maquette
Modifions une entrée dans l'entité get-telecom afin d'y ajouter l'attribut departmentNumber
$ ldapmodify -x -D “cn=admin,dc=get-telecom,dc=fr” -W -f ./add-dept-meta.ldif -p 9000 -h localhost
Enter LDAP Password:
modifying entry “sn=lautraite,ou=People,dc=get-telecom,dc=fr”
$ cat add-dept-meta.ldif
dn: sn=lautraite,ou=People,dc=get-telecom,dc=fr
changetype: modify
add: departmentNumber
departmentNumber: SAG
Verification:
$ ldapsearch -x “cn=*laut*” -h localhost -p 9000 -b “dc=get-telecom,dc=meta,dc=fr” -LLL cn departmentNumber
dn: sn=lautraite,ou=People,dc=get-telecom,dc=meta,dc=fr
cn: Isabelle Lautraite
departmentNumber: SAG
Modification équivalente sur l'entité enstb , cette entité ayant choisi l'attribut ``ou pour contenir l'information de service d'appartenance de la personne
$ ldapmodify -x -D “cn=admin,dc=enstb,dc=fr” -W -f ./add-dept-enstb.ldif -p 9000 -h localhost
Enter LDAP Password:
modifying entry “sn=brouty,ou=People,dc=enstb,dc=fr”
$ cat add-dept-enstb.ldif
dn: sn=brouty,ou=People,dc=enstb,dc=fr
changetype: modify
add: ou
ou: SAG
Verification:
$ ldapsearch -x “cn=*brout*” -h localhost -p 9000 -b “dc=enstb,dc=meta,dc=fr” -LLL cn ou
dn: sn=brouty,ou=People,dc=enstb,dc=meta,dc=fr
cn: Andre Brouty
ou: SAG
16.6.2 Modification de la configuration du serveur
Nous pouvons maintenant configurer le meta annuaire afin qu'une recherche sur le groupe rende homogene l'attribut d'appartenance au service. Ici nous traduiront l'attribut departementNumber vers ou lors d'une recherche sur l'entite enstb.
database meta
suffix “dc=meta,dc=fr”
uri “ldap://localhost:9000/dc=enstb,dc=meta,dc=fr”
suffixmassage “dc=enstb,dc=meta,dc=fr” “dc=enstb,dc=fr”
map attribute departmentNumber ou
Test
$ ldapsearch -x “departmentNumber=SAG” -h localhost -p 9000 -b “dc=meta,dc=fr” -LLL cn departmentNumber ou
dn: sn=brouty,ou=People,dc=enstb,dc=meta,dc=fr
cn: Andre Brouty
departmentNumber: SAG
dn: sn=lautraite,ou=People,dc=get-telecom,dc=meta,dc=fr
cn: Isabelle Lautraite
departmentNumber: SAG
L'attribut ou=SAG pour l'annuaire de l'entité enstb a bien été traduit en departmentNumber=SAG .
16.6.3 Equivalence d'attribut par entité
Il est possible de définir une équivalence (map) d'attribut par entité. Ici nous conservons le ``map
depatmentNumber vers ou pour l'entité enstb et ajoutons le ``map depatmentNumber vers IntEPersUserEntite (attribut ``maison
).
Configuration de la database meta
#database meta
database meta
suffix “dc=meta,dc=fr”
uri “ldap://localhost:9000/dc=enstb,dc=meta,dc=fr”
suffixmassage “dc=enstb,dc=meta,dc=fr” “dc=enstb,dc=fr”
map attribute departmentNumber ou
uri “ldap://localhost:9000/dc=get-telecom,dc=meta,dc=fr”
suffixmassage “dc=get-telecom,dc=meta,dc=fr” “dc=get-telecom,dc=fr”
uri “ldap://localhost/dc=int-evry,dc=meta,dc=fr”
suffixmassage “dc=int-evry,dc=meta,dc=fr” “dc=int-evry,dc=fr”
map attribute departmentNumber IntEPersUserEntite
lastmod off
Verification des differents attributs de ``services sur l'entité int-evry:
$ ldapsearch -x “IntEPersUserEntite=SAG” -h localhost -b “dc=int-evry,dc=fr” -LLL cn departmentNumber ou IntEPersUserEntite -D “cn=admin,dc=int-evry,dc=fr” -W
Enter LDAP Password:
dn: uid=procacci,ou=People,dc=int-evry,dc=fr
cn: Jehan PROCACCIA
departmentNumber: S2IA
IntEPersUserEntite: SAG
ou: MCI
Rechecrhe sur la meta base sur l'attribut d'equivalence departmentNumber:
$ /usr/local/openldap-2.2.20-1/bin/ldapsearch -x “departmentNumber=SAG” -h localhost -p 9000 -b “dc=meta,dc=fr” -LLL cn departmentNumber
dn: sn=brouty,ou=People,dc=enstb,dc=meta,dc=fr
cn: Andre Brouty
departmentNumber: SAG
dn: sn=lautraite,ou=People,dc=get-telecom,dc=meta,dc=fr
cn: Isabelle Lautraite
departmentNumber: SAG
dn: uid=procacci,ou=People,dc=int-evry,dc=meta,dc=fr
cn: Jehan PROCACCIA
departmentNumber: SAG
Log
Ils font apparaitre une indisponibilité d'index sur l'attribut ``mappé
, ce qui pourrait avoir des consequences en terme de performance !.
Jan 21 10:15:57 calaz slapd[11956]: conn=6 fd=12 ACCEPT from IP=127.0.0.1:42322 (IP=0.0.0.0:9000)
Jan 21 10:15:57 calaz slapd[11956]: conn=6 op=0 BIND dn=”“ method=128
Jan 21 10:15:57 calaz slapd[11956]: conn=6 op=0 RESULT tag=97 err=0 text=
Jan 21 10:15:57 calaz slapd[11956]: conn=6 op=1 SRCH base=“dc=meta,dc=fr” scope=2 deref=0 filter=”(departmentNumber=sag)“
Jan 21 10:15:57 calaz slapd[11956]: conn=6 op=1 SRCH attr=cn departmentNumber
Jan 21 10:15:57 calaz slapd[11956]: conn=7 fd=14 ACCEPT from IP=127.0.0.1:42323 (IP=0.0.0.0:9000)
Jan 21 10:15:57 calaz slapd[11956]: conn=7 op=0 BIND dn=”“ method=128
Jan 21 10:15:57 calaz slapd[11956]: conn=7 op=0 RESULT tag=97 err=0 text=
Jan 21 10:15:57 calaz slapd[11956]: conn=8 fd=16 ACCEPT from IP=127.0.0.1:42324 (IP=0.0.0.0:9000)
Jan 21 10:15:57 calaz slapd[11956]: conn=8 op=0 BIND dn=”“ method=128
Jan 21 10:15:57 calaz slapd[11956]: conn=8 op=0 RESULT tag=97 err=0 text=
Jan 21 10:15:57 calaz slapd[11956]: conn=7 op=1 SRCH base=“dc=enstb,dc=fr” scope=2 deref=0 filter=”(ou=sag)“
Jan 21 10:15:57 calaz slapd[11956]: conn=7 op=1 SRCH attr=cn ou
Jan 21 10:15:57 calaz slapd[11956]: ⇐ bdb_equality_candidates: (ou) index_param failed (18)
Jan 21 10:15:57 calaz slapd[11956]: conn=7 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Jan 21 10:15:57 calaz slapd[11956]: conn=8 op=1 SRCH base=“dc=get-telecom,dc=fr” scope=2 deref=0 filter=”(departmentNumber=sag)“
Jan 21 10:15:57 calaz slapd[11956]: conn=8 op=1 SRCH attr=cn departmentNumber
Jan 21 10:15:57 calaz slapd[11956]: ⇐ bdb_equality_candidates: (departmentNumber) index_param failed (18)
Jan 21 10:15:57 calaz slapd[11956]: conn=8 op=1 SEARCH RESULT tag=101 err=0 nentries=1 text=
Jan 21 10:15:58 calaz slapd[11956]: conn=6 op=1 SEARCH RESULT tag=101 err=0 nentries=3 text=
Jan 21 10:15:58 calaz slapd[11956]: conn=6 op=2 UNBIND
Jan 21 10:15:58 calaz slapd[11956]: conn=6 fd=12 closed
Jan 21 10:15:58 calaz slapd[11956]: conn=7 op=2 UNBIND
Jan 21 10:15:58 calaz slapd[11956]: conn=7 fd=14 closed
Jan 21 10:15:58 calaz slapd[11956]: conn=8 op=2 UNBIND
Jan 21 10:15:58 calaz slapd[11956]: conn=8 fd=16 closed
16.7 Avertissements
16.7.1 ACL
Ici les attributs recherchés ont été ouverts en read by * !. Il doit y avoir moyen d'affiner ceci avec les directives binddn bindpw du backend meta .
16.7.2 Performances
Ces tests ont été réalisés sur des bases ldap comprenants pour les entités get-telecom et enstb une seule entrée ! (2800 pour int-evry), de plus les instances de slapd sont locales au PC de test → les resultats ont été instantanés, il faudrait verifier ce que cela donne avec des annuaires distants et plus consequents .
17 Migration vers Supann (NEW)
Presentation de supann: http://www.cru.fr/ldap/supann/
17.1 Objectif
L'objectif est ici de convertir un annuaire existant vers supann. Il s'agit donc d'y ajouter les objectclass de supannPersonn et de eduPerson telles qu'elles sont présentées dans : http://www.cru.fr/ldap/supann/recomm/SUPANN-V10.pdf
Dans un premier temps, j'ai essayé de remplir le maximum d'attributs optionnels en plus des attributs obligatoires .
17.2 Méthode
Il en existe plusieurs, on pourrai simplement faire un dump ldif de l'annuaire et utiliser un script quelconque pour ajouter à froid les attributs et objectclass, puis recharger le ldif completement.
J'ai choisis l'option de modification à chaud (d'abord sur un annuaire de test !) en utilisant la librairie Perl Net::LDAP → recherche des objects (uid de personnes) , et modification un à un.
17.3 Script d'insertion
voici le script : ./add-supann-eduperson-attr.plou en txt pour le voir dans le navigateur: ./add-supann-eduperson-attr.txt
Ce script est spécifique à l'INT, mais doit pouvoir facilement s'adapter .
Il essais de recuperer le maximum d'information deja existantes dans la base ldap de production (exemple employeeType pour alimenter eduPersonAffiliation) et en recupere d'autres depuis une extraction de base externe (supannCivilite récupéré d'une base SQL des etudiants).
Il gére aussi l'utilisation multiple, je veux dire par là qu'il peux repasser sur un annuaire deja supann en ne faisant que modifier les attributs déja presents sans ajouter à nouveau les objectclass supannPersonn et eduPerson (cf flag dans les commentaires en ligne du script).
17.4 Execution
Relativement rapide, 1mn pour 2000 entrées via le reseau .
[jehan@calaz ~/Procacci/Progs-jp/Perl/Ldap]
$ time ./add-supann-eduperson-attr.pl
…
flag=0 et civ=M
DN,uid=procacci,ou=People,dc=int-evry,dc=fr
…
real 1m11.769s
user 0m30.374s
sys 0m0.532s
17.5 Résultat
Voici un exemple d'entré d'une étudiante:
[root@esup /var/lib/ldap/int]
$ ldapsearch -x uid=sadoo_li
…
supannListeRouge: FALSE
supannEtuId: 17555
supannOrganisme: INT EVRY 0911781S
supannCivilite: Mlle
supannAffectation: EM
supannCodeINE: 17555
supannParrainDN: uid=sadoo_li,ou=People,dc=int-evry,dc=fr
eduPersonAffiliation: student
eduPersonPrimaryAffiliation: student
eduPersonNickname: Linda
eduPersonOrgDN: o=GET-INT,dc=int-evry,dc=fr
eduPersonOrgUnitDN: sn=EM,ou=departements,ou=informations,dc=int-evry,dc=fr
eduPersonPrimaryOrgUnitDN: sn=EM,ou=departements,ou=informations,dc=int-evry,d
c=fr
eduPersonPrincipalName: Linda.Sadoo@int-evry.fr
eduPersonScopedAffiliation: student@EM
18 Trucs et astuces
18.1 Index
Remarque sur l'indexation à posteriori d'un annuaire.
ajouter une indexation après avoir “populé” la base: il faut detruire les fichier d'index existant, puis lancer slapindex. Il est recommendé d'arreter le serveur ldap pendant cette opération
slapd.conf
#ajout des index sur sn,mail en pres et sub
index cn,sn,mail pres,eq,sub
#ou dans l'exemple ci-dessus, suite a des pb d'index, reconstruction totale:
index objectClass,uid,uidNumber,gidNumber,IntEPersInetServ eq
index cn,mail,surname,givenname eq,subinitial
$ /etc/init.d/ldap stop
Arrêt de slapd :
[root@ur /var/lib/ldap/int]
$ ls -al
total 25128
drwxr-xr-x 2 ldap ldap 4096 aoû 1 17:07 .
drwx—— 3 ldap ldap 4096 jan 25 2002 ..
-rw-r–r– 1 ldap ldap 1617920 aoû 1 17:56 cn.dbb
-rw-r–r– 1 ldap ldap 827392 aoû 1 15:39 dn2id.dbb
-rw-r–r– 1 ldap ldap 49152 aoû 1 17:56 gidNumber.dbb
-rw-r–r– 1 ldap ldap 536576 aoû 1 17:56 givenName.dbb
-rw-r–r– 1 ldap ldap 19894272 aoû 1 17:56 id2entry.dbb
-rw-r–r– 1 ldap ldap 20480 aoû 1 17:56 IntEPersInetServ.dbb
-rw-r–r– 1 ldap ldap 1306624 aoû 1 17:56 mail.dbb
-rw-r–r– 1 ldap ldap 8192 aoû 1 15:39 nextid.dbb
-rw——- 1 ldap ldap 253952 aoû 1 17:56 objectClass.dbb
-rw-r–r– 1 ldap ldap 876544 aoû 1 17:56 sn.dbb
-rw-r–r– 1 ldap ldap 139264 aoû 1 17:56 uid.dbb
-rw-r–r– 1 ldap ldap 135168 aoû 1 17:56 uidNumber.dbb
[root@ur /var/lib/ldap/int]
$ rm cn.dbb gidNumber.dbb givenName.dbb IntEPersInetServ.dbb mail.dbb \
objectClass.dbbsn.dbb uid.dbb uidNumber.dbb
[root@ur /var/lib/ldap/int]
$ ls -ltra
total 20280
drwx—— 3 ldap ldap 4096 jan 25 2002 ..
-rw-r–r– 1 ldap ldap 8192 aoû 1 15:39 nextid.dbb
-rw-r–r– 1 ldap ldap 827392 aoû 1 15:39 dn2id.dbb
-rw-r–r– 1 ldap ldap 19894272 aoû 1 17:56 id2entry.dbb
drwxr-xr-x 2 ldap ldap 4096 aoû 1 18:02 .
#On garde id2entry qui est la base elle meme, ainsi que nextid et dn2id.
$ slapindex -f /etc/openldap/slapd.conf
# redonner les droits au compte ldap sur ces fichiers
[root@ur /var/lib/ldap/int]
$ chown ldap:ldap *
#et c'est reparti
$ /etc/init.d/ldap start
Démarrage de slapd: [ OK ]
18.2 Récuperer le champs userPassword
Via les commandes shell ; ldapsearch, avec un bind administrateur ou l'utilisateur du compte concerné. Le champs userPassword est retourné encodé en base 64, il faut donc le decoder .
$ldapsearch -x -D “uid=test,ou=people,dc=int-evry,dc=fr” \
-W “uid=test” -LLL userPassword
Enter LDAP Password:
dn: uid=test,ou=People,dc=int-evry,dc=fr
userPassword:: e2NyeXB0fTgybmhJTTcuUGtFODY=
ajouter de le décodage
$ldapsearch -x -D “uid=test,ou=people,dc=int-evry,dc=fr” \
-W “uid=test” -LLL userPassword | grep userPassword | \
cut –delimiter=” “ -f2 | openssl base64 -d ; echo
Enter LDAP Password:
{crypt}82nhIM7.PkE86
verification de la concordance de la chaine cryptée et du password en clair
$python -c “import crypt; print crypt.crypt('motdepas','82nhIM7.PkE86')”
82nhIM7.PkE86
18.3 Acces au schema par ldap
Attention, suivant les ACL, il faut faire ces recherches avec un bind administrateur -D ``cn=admin,dc=int-evry,dc=fr -W .
get RootDSE without SASL
$ ldapsearch -x -H ldap://corbeau:389 -b
-s base -LLL + -D “cn=admin,dc=int-evry,dc=fr” -W
Enter LDAP Password:
dn:
structuralObjectClass: OpenLDAProotDSE
namingContexts: dc=int-evry,dc=fr
monitorContext: cn=Monitor
supportedControl: 2.16.840.1.113730.3.4.2
supportedControl: 1.3.6.1.4.1.4203.1.10.2
supportedControl: 1.2.826.0.1.334810.2.3
supportedExtension: 1.3.6.1.4.1.4203.1.11.3
supportedExtension: 1.3.6.1.4.1.4203.1.11.1
supportedExtension: 1.3.6.1.4.1.1466.20037
supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
supportedFeatures: 1.3.6.1.4.1.4203.1.5.2
supportedFeatures: 1.3.6.1.4.1.4203.1.5.3
supportedFeatures: 1.3.6.1.4.1.4203.1.5.4
supportedFeatures: 1.3.6.1.4.1.4203.1.5.5
supportedLDAPVersion: 2
supportedLDAPVersion: 3
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
subschemaSubentry: cn=Subschema
get supported attributes from subschema entry
$ldapsearch -x -H ldap://corne:389 -b 'cn=Subschema' -s base -LLL \
objectclass=subschema attributeTypes
dn: cn=Subschema
attributeTypes: ( 2.5.18.1 NAME 'createTimestamp' EQUALITY generalizedTimeMatc
h ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
attributeTypes: ( 2.5.18.2 NAME 'modifyTimestamp' EQUALITY generalizedTimeMatc
h ORDERING generalizedTimeOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
SINGLE-VALUE NO-USER-MODIFICATION USAGE directoryOperation )
attributeTypes: ( 2.5.18.3 NAME 'creatorsName' EQUALITY distinguishedNameMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE NO-USER-MODIFICATION USAGE
directoryOperation )
…
attributeTypes: ( 1.3.6.1.4.1.7391.2.2.1.1.2.8 NAME 'vacationaddress' DESC 'Ad
resse de vacation' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1
.15 )
get supported objectclasses from subschema entry
$ldapsearch -x -H ldap://corne:389 -b 'cn=Subschema' -s base -LLL \
objectclass=subschema objectClasses
objectClasses: ( 2.5.20.1 NAME 'subschema' DESC 'RFC2252: controlling subschem
a' AUXILIARY MAY ( dITStructureRules $ nameForms $ ditContentRules $ objectCl
asses $ attributeTypes $ matchingRules $ matchingRuleUse ) )
objectClasses: ( 2.5.6.0 NAME 'top' ABSTRACT MUST objectClass )
…
objectClasses: ( 1.3.6.1.4.1.7391.2.2.2.1 NAME 'Vacation' DESC 'Users vacation
status information' STRUCTURAL MUST ( vacationActive $ maildeliveryoption $
uid ) MAY ( vacationInfo $ vacationStart $ vacationEnd $ vacationaddress $ ma
ilforwardingaddress ) )
18.4 Erreurs stupides !
Après avoir perdu du temps sur cette erreur, j'en note la raison.
fichier ldif contenant:
objectclass: groupOfNames
ajout par ldapadd retourne:
ldap_add: Invalid syntax
additional info: objectclass: value #0 invalid per syntax
Ici j'avais laissé trainer un espace derrière groupOfNames dans le fichier ldif, ce qui donne ce genre d'erreur !.
18.5 Sauvegarde en ligne des données PosixAccount
Pour restaurer ou avoir une copie sous un format “traditionnel” des comptes posix :
getent passwd >passwd.back
getent shadow >shadow.back
Références
[1]
Administrator's Guide du site openldap, http://www.openldap.org/doc/admin/
[2]
Archives de la liste de discussion openldap, http://www.openldap.org/lists/openldap-software/
[3]
Pam ldap, http://www.padl.com/OSS/pam_ldap.html
[4]
Open-IT project, http://kodama.open-it.org/metadot/index.pl
[5]
Ldap au CRU, http://www.cru.fr/ldap/
[6]
Ldap schema repository, http://ldap.akbkhome.com/index.php
[7]
openldap latest release notes http://www.openldap.org/software/release/
[8]
Fedora Directory Server Project http://directory.fedora.redhat.com/wiki/Main_Page
[9]
Red Hat Directory Server http://www.redhat.com/software/rha/directory/
[10]
Red Hat Opens Netscape Directory http://linux.slashdot.org/article.pl?sid=05/05/26/0044247&tid=110&tid=95
Ce document a été traduit de LATEX par HEVEA.