Dernière modification 16 juillet 2022
Si on rentre dans les détails, le protocole
LDAP est du type client serveur, le serveur contient la base de
données, et le client consulte la base de données, le protocole fournit
les bases pour cette communication entre la client et le serveur
(normalisée par l'IETF par la RFC2251), et les commandes nécessaires au
client pour rechercher, créer, modifier ou effacer des données. LDAP est
bien entendu sécurisé pour le transfert et l'accès aux des données, avec
des outils de cryptage comme SSL et d'authentification.
Par ailleurs LDAP fournit des outils pour que les serveurs LDAP
puissent communiquer entre eux, on a ainsi la possibilité de créer des
serveurs miroirs qui pourront se synchroniser, ou de relier simplement les
serveurs entre eux, les serveurs redirigeant automatiquement les requêtes
qui ne les concernent pas.
Les exemples d'applications de LDAP
sont nombreux:
- bases de données d'employés,
- bases de données de produits,
- bases de données pour certaines applications, exemple :
* toutes les infos contenant
les utilisateurs de votre réseau (mot de passe, shell, homedirectory, ...)
peuvent être dans la base, on a ainsi beaucoup plus de possibilités qu'un
simple fichier /etc/passwd, l'authentification peut donc utiliser
LDAP plutôt que passwd ou shadow ou encore NIS.
Vos utilisateurs pourront ainsi changer leur mot de passe et certains de
leurs attributs à partir d'une interface web.
* les préférences
d'applications ou d'environnement (netscape, environnement
graphique KDE, ...) sont sauvegardés dans la base, ainsi l'utilisateur
peut passer d'une machine à une autre et retrouver ses préférences.
Cette page est une introduction à LDAP elle ne couvre pas certains aspects comme les liens avec d'autres bases (duplication, miroir, ...), la sécurité (access control, SSL, ...). Elle n'a seulement pour but de mettre en place un serveur LDAP simplement configuré pour que vous puissiez faire vos "premières armes" dans le domaine. Pour plus d'info reportez vous à l'excellente page de Laurent Mirtain .
Pour utiliser une base LDAP à partir de script PHP, voir ma page Apache .
Le principe est donc le même qu'en C++, on retrouve une structure arborescente, avec à la racine la classe top, toutes les autres classes d'objet dérivent de cette classe générique, chaque classe hérite des propriétés d'une classe père et possède des attributs supplémentaires par rapport à ce dernier.
objectclass ( 2.5.6.6 NAME 'person'
DESC 'RFC2256: a person'
SUP top STRUCTURAL
MUST ( sn $ cn )
MAY ( userPassword $
telephoneNumber $ seeAlso $ description ) )
MUST correspond au attributs obligatoires et MAY à ceux
facultatifs
objectClass est le nom de la classe qui descend elle même de la
classe top
sn correspond à surname (nom)
cn correspond à common name (prénom nom)
Je vous laisse deviner la signification des autres attributs.
On voit qu'il est nécessaire de fournir les attributs sn (surname) et cn (common name), sont facultatifs le mot de passe (userPassword), le numéro de téléphone (telephoneNumber ), les liens (seeAlso) et la description.
Les attributs sont définis dans le même fichier, la syntaxe est la suivante pour telephoneNumber par exemple :
attributetype ( 2.5.4.20 NAME 'telephoneNumber'
DESC 'RFC2256: Telephone
Number'
EQUALITY
telephoneNumberMatch
SUBSTR
telephoneNumberSubstringsMatch
SYNTAX
1.3.6.1.4.1.1466.115.121.1.50{32} )
Je vous présenterai la syntaxe plus tard, on peut dans un premier temps se limiter aux attributs disponibles. Pour créer une classe d'objet breizhPerson dérivant de person, disposant de l'attribut obligatoire title en plus et des arguments facultatifs ou (groupe de travail) et l (localisation). On tapera dans le fichier core.schema juste après la définition de la classe person
objectclass ( 2.5.6.6.2 NAME 'breizhPerson' SUP person STRUCTURAL
MUST ( title )
MAY ( ou $ l ) )
# $OpenLDAP: pkg/ldap/servers/slapd/slapd.conf,v 1.8.8.6 2001/04/20
23:32:43 kurt Exp $
#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
# Modified by Christian Zoffoli <czoffoli@linux-mandrake.com>
# Version 0.2
include /usr/share/openldap/schema/core.schema
include /usr/share/openldap/schema/cosine.schema
include /usr/share/openldap/schema/corba.schema
include
/usr/share/openldap/schema/inetorgperson.schema
include /usr/share/openldap/schema/java.schema
include /usr/share/openldap/schema/krb5-kdc.schema
include /usr/share/openldap/schema/kerberosobject.schema
include /usr/share/openldap/schema/misc.schema
include /usr/share/openldap/schema/nis.schema
include /usr/share/openldap/schema/openldap.schema
include /usr/share/openldap/schema/autofs.schema
include /usr/share/openldap/schema/samba.schema
include /usr/share/openldap/schema/kolab.schema
include /usr/share/openldap/schema/evolutionperson.schema
include /usr/share/openldap/schema/calendar.schema
include /usr/share/openldap/schema/sudo.schema
include /usr/share/openldap/schema/dnszone.schema
include /usr/share/openldap/schema/dhcp.schema
include /etc/openldap/schema/local.schema
# Define global ACLs to disable default read access and provide default
# behaviour for samba/pam use
include /etc/openldap/slapd.access.conf
# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral ldap://root.openldap.org
pidfile /run/ldap/slapd.pid
argsfile /run/ldap/slapd.args
modulepath /usr/lib64/openldap
# database backend modules available:
moduleload back_mdb.la
# To allow TLS-enabled connections, create /etc/ssl/openldap/ldap.pem
# and uncomment the following lines.
#TLSRandFile
/dev/random
#TLSCipherSuite
HIGH:MEDIUM:+SSLv2
TLSCertificateFile
/etc/pki/tls/certs/ldap.pem
TLSCertificateKeyFile /etc/pki/tls/private/ldap.pem
#TLSCACertificatePath /etc/ssl/openldap/
#TLSCACertificateFile /etc/ssl/cacert.pem
TLSCACertificateFile /etc/pki/tls/certs/ldap.pem
#TLSVerifyClient never # ([never]|allow|try|demand)
# logging
#loglevel 256
#######################################################################
# database definitions
#######################################################################
database mdb
suffix "dc=kervao,dc=fr"
rootdn "cn=Manager,dc=kervao,dc=fr"
# Cleartext passwords, especially for the rootdn, should
# be avoided. See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
rootpw secret
# The database directory MUST exist prior to running slapd AND
# should only be accessable by the slapd/tools. Mode 700 recommended,
répertoire où se trouve la base de donnée
directory /var/lib/ldap
# Tuning settings, please see the man page for slapd-bdb for more
information
# as well as the DB_CONFIG file in the database directory
# commented entries are at their defaults
# In-memory cache size in entries
#cachesize 1000
# Checkpoint the bdb database after 256kb of writes or 5 minutes have
passed
# since the last checkpoint
checkpoint 256 5
# Indices to maintain
index objectClass
eq
# persion-type searches
index cn,mail,surname,givenname
eq,subinitial
# nss_ldap exact searches:
index
uidNumber,gidNumber,memberuid,member,uniqueMember eq
# username completion via nss_ldap needs uid indexed sub:
index
uid
eq,subinitial
# samba:
index sambaSID,sambaDomainName,displayName
eq
# autofs:
#index
nisMapName
eq
# bind sdb_ldap:
#index
zoneName,relativeDomainName
eq
# sudo
#index
sudoUser
eq
# syncprov
#index
entryCSN,entryUUID
eq
# Replicas running syncrepl as non-rootdn need unrestricted size/time
limits:
limits group="cn=Replicator,ou=Group,dc=example,dc=com"
size=unlimited
time=unlimited
# Basic ACL (deprecated in favour of ACLs in
/etc/openldap/slapd.access.conf)
access to attrs=userPassword
by self write
by anonymous auth
by
dn="cn=Manager,dc=kervao,dc=fr" write
by * none
#
access to *
by
dn="cn=Manager,dc=kervao,dc=fr" write
by * read
La base LDAP a été créée par défaut sous /var/lib/ldap
Le fichier ldap.conf peut être vide dans un premier temps voire inexistant.
Le mot de passe de l'administrateur est secret en clair, si ça ne vous convient pas et que vous voulez le crypter, il faudra taper
slappasswd
on saisit son mot de passe
New password:
Re-enter new password:
et voilà le résultat
{SSHA}vNCYRQthN6u3OqcTAJ4lt/9vIhjsFmI
A la place de
rootpw secret
Dans slapd.conf, vous mettrez donc:
rootpw {SSHA}vNCYRQthN6u3OqcTAJ4lt/9vIhjsFmI
After=syslog.target
[Service]
Type=forking
PIDFile=/run/ldap/slapd.pid
Environment="SLAPDURLLIST=ldap:/// ldapi:///" "LDAP_USER=ldap"
"LDAP_GROUP=ldap" "SLAPDSYSLOGLOCALUSER=local4" "SLAPDSYSLOGLEVEL=0"
EnvironmentFile=/etc/sysconfig/slapd
ExecStartPre=/usr/share/openldap/scripts/ldap-config check
ExecStart=/usr/sbin/slapd -u ${LDAP_USER} -g ${LDAP_GROUP} -h
${SLAPDURLLIST} -l ${SLAPDSYSLOGLOCALUSER} -s ${SLAPDSYSLOGLEVEL}
[Install]
WantedBy=multi-user.target
maintenant pour que le service soit lancé à chaque boot de la machine il
faudra taper
systemctl enable slapd.service
voilà le résultat
Created symlink from /etc/systemd/system/multi-user.target.wants/slapd.service to /usr/lib/systemd/system/slapd.service.
pour le lancer il suffit maintenant de taper
systemctl start slapd.service
et pour connaître son état
systemctl status slapd.service
voilà le résultat
● slapd.service - OpenLDAP
Server Daemon
Loaded: loaded
(/usr/lib/systemd/system/slapd.service; disabled; vendor preset:
disabled)
Active: active (running) since Sat 2022-07-16
11:24:49 CEST; 2h 13min ago
Process: 3267
ExecStartPre=/usr/share/openldap/scripts/ldap-config check (code=exited,
status=0/SUCCESS)
Process: 3302 ExecStart=/usr/sbin/slapd -u
${LDAP_USER} -g ${LDAP_GROUP} -h ${SLAPDURLLIST} -l
${SLAPDSYSLOGLOCALUSER} -s ${SLAPDSYSLOGLEVEL} (code=exited,
status=0/SUCCESS)
Main PID: 3303 (slapd)
Tasks: 3 (limit: 9283)
Memory: 3.1M
CPU: 57ms
CGroup: /system.slice/slapd.service
└─3303 /usr/sbin/slapd -u ldap -g ldap -h ldap:/// ldapi:/// -l local4
-s 0
juil. 16 11:24:48 serveur-slapd.kervao.fr systemd[1]: Starting OpenLDAP
Server Daemon...
juil. 16 11:24:48 serveur-slapd.kervao.fr su[3274]: (to ldap) root on
none
juil. 16 11:24:49 serveur-slapd.kervao.fr su[3274]:
pam_unix(su:session): session opened for user ldap by (uid=0)
juil. 16 11:24:49 serveur-slapd.kervao.fr su[3274]:
pam_unix(su:session): session closed for user ldap
juil. 16 11:24:49 serveur-slapd.kervao.fr ldap-config[3267]:
Vérification de la configuration file /etc/openldap/slapd.conf :
[ OK ]
juil. 16 11:24:49 serveur-slapd.kervao.fr systemd[1]: Started OpenLDAP
Server Daemon.
ça nous évitera une erreur du genre
slapd[5803]: main: TLS init def
ctx failed: -1
maintenant
on va modifier le fichier
/etc/openldap/slapd.conf
on rajoute les
lignes suivantes
TLSCACertificateFile /etc/pki/CA/cacert.pem
TLSCertificateFile /etc/pki/CA/private/cakey.pem
TLSCertificateKeyFile /etc/pki/CA/cacert.pem
/etc/pki/tls/certs/
). Il doit avoir les droits 644
chmod 644 ldapcrt.pem
On édite le fichier
/etc/openldap/ldapd.conf
et on modifie ainsi
# SSL/TSL configuration. With CA-signed certs, TLS_REQCERT
should be
# "demand", with the CA certificate accessible
#TLS_REQCERT ([demand],never,allow,try)
# We ship with allow by default as some LDAP clients (e.g.
evolution) have
# no interactive SSL configuration
TLS_REQCERT allow
# CA Certificate locations
# Use the default self-signed cert generated by
openldap-server postinstall
# by default
TLS_CACERT
/etc/pki/tls/certs/ldap.pem
La syntaxe du format LDIF est la suivante:
dn: description du distinguished name
objetclass: classe d'objet d'origine
...
objetclass: classe d'objet dérivée
type attribut: valeur
...
On va par exemple utiliser la classe breizPerson définie plus
haut pour décrire une nouvelle personne Veronique Hoarau qu'on va
rajouter dans l'annuaire. Elle appartient au service (organizationalUnit)
staff, ce même service appartenant à l'organisation kervao.fr
Soit le fichier entree.ldif
dn: dc=kervao, dc=fr
objectClass: dcObject
objectClass: organization
dc: kervao
o: kervao.fr
dn: ou=staff, dc=kervao, dc=fr
objectclass: organizationalUnit
ou: staff
dn: cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
objectclass: person
objectclass: breizhPerson
cn: Veronique Hoarau
sn: Hoarau
title: madame
dc=fr
|
dc=kervao
|
------------------------------------------------------------------------------------------------------------
|
|
|
|
ou=staff
ou=informatique
ou=production
ou=achat
|
------------------------------------------------------------------
|
|-b 'dc=kervao, dc=fr' '(objectclass=*)'
cn=Veronique
Hoarau
cn=Olivier
Hoarau
Au niveau de la définition de la personne:
objetclass: person définit la classe père de la classe breizPerson,
objetclass: breizPerson classe décrivant la personne,
cn et sn sont des attributs à renseigner obligatoirement,
title est un attribut obligatoire
On rajoutera l'enregistrement en utilisant la syntaxe suivante (en tant que simple utilisateur):
ldapadd -x -D "description du dn de l'administrateur" -W -f nom-du-fichier-ldif
Exemple concret:
ldapadd -x -D "cn=Manager, dc=kervao, dc=fr" -W -f
entree.ldif
Enter LDAP Password: secret
adding new entry "dc=kervao, dc=fr"
adding new entry "ou=staff, dc=kervao, dc=fr"
adding new entry "cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr"
Pour rajouter par la suite un autre enregistement dans le groupe staff, il sera plus nécessaire de rajouter la définition du groupe et de l'organisation. Soit le fichier entree.ldif
dn: cn=Olivier Hoarau, ou=staff, dc=kervao, dc=fr
objectclass: person
objectclass: breizhPerson
cn: Olivier Hoarau
sn: Hoarau
title: monsieur
On tape ensuite la commande:
ldapadd -x -D "cn=Manager, dc=kervao, dc=fr" -W -f entree.ldif
Enter LDAP Password:
adding new entry "cn=Olivier Hoarau, ou=staff, dc=kervao, dc=fr"
ldapsearch -x -b 'dc=kervao, dc=fr' '(objectclass=*)'
Voilà le résultat
# extended LDIF
#
# LDAPv3
# base <dc=kervao, dc=fr> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# kervao.fr
dn: dc=kervao,dc=fr
objectClass: dcObject
objectClass: organization
dc: kervao
o: kervao.fr
# staff, kervao.fr
dn: ou=staff,dc=kervao,dc=fr
objectClass: organizationalUnit
ou: staff
# Veronique Hoarau, staff, kervao.fr
dn: cn=Veronique Hoarau,ou=staff,dc=kervao,dc=fr
objectClass: person
objectClass: breizhPerson
cn: Veronique Hoarau
sn: Hoarau
title: madame
# Olivier Hoarau, staff, kervao.fr
dn: cn=Olivier Hoarau,ou=staff,dc=kervao,dc=fr
objectClass: person
objectClass: breizhPerson
cn: Olivier Hoarau
sn: Hoarau
title: monsieur
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 4
dn: cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
add: l
title: bureau36
On tape ensuite
ldapmodify -x -D "cn=Manager, dc=kervao, dc=fr" -W -f modif.ldif
Enter LDAP Password:secret
modifying entry "cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr"
dn: cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
changetype: modify
replace: title
title: mademoiselle
On tape ensuite
ldapmodify -x -D "cn=Manager, dc=kervao, dc=fr" -W -f modif.ldif
Enter LDAP Password:secret
modifying entry "cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr"
dn: cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
delete: l
On tape ensuite
ldapmodify -x -D "cn=Manager, dc=kervao, dc=fr" -W -f modif.ldif
Enter LDAP Password:secret
modifying entry cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
dn: cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
changetype: delete
On tape ensuite:
ldapmodify -x -D "cn=Manager, dc=kervao, dc=fr" -W -f modif.ldif
Enter LDAP Password:secret
deleting entry cn=Veronique Hoarau, ou=staff, dc=kervao, dc=fr
ATTENTION Vous ne pouvez pas supprimer un attribut obligatoire comme title pour la classe breizhPerson.
Le principe est d'exporter une base sur le serveur A pour la réimporter sur le serveur B. Pour exporter une base sur le serveur A on tapera
slapcat > base.ldif
Maintenant on revient sur le serveur B sur lequel on aura récupéré le fichier base.ldif, on stoppera tout d'abord slapd en tapant
systemctl stop slapd
puis pour importer
slapadd -l base.ldif
voilà le résultat
62d2baf8 /etc/openldap/slapd.conf: line 185: rootdn is always granted
unlimited privileges.
62d2baf8 /etc/openldap/slapd.conf: line 189: rootdn is always granted
unlimited privileges.
_#################### 100.00% eta none
elapsed
none fast!
Closing DB...
Attention si la base contient déjà des éléments préexistants en doublon, ça fera une erreur dans ce genre
62d2b3b7 /etc/openldap/slapd.conf: line 185: rootdn is always granted
unlimited privileges.
62d2b3b7 /etc/openldap/slapd.conf: line 189: rootdn is always granted
unlimited privileges.
_#
8.38% eta 27s
elapsed
02s spd 155.6 /s 62d2b3b9 mdb_id2entry_put: mdb_put failed:
MDB_KEYEXIST: Key/data pair already exists(-30799) "dc=kervao,dc=fr"
62d2b3b9 => mdb_tool_entry_put: id2entry_add failed: err=-30799
62d2b3b9 => mdb_tool_entry_put: txn_aborted! MDB_KEYEXIST: Key/data
pair already exists (-30799)
slapadd: could not add entry dn="dc=kervao,dc=fr" (line=1): txn_aborted!
MDB_KEYEXIST: Key/data pair already exists (-30799)
.#
8.38% eta 27s
elapsed
02s spd 0.0 /s
Closing DB..
Dans ce cas il faudra faire le ménage dans la base de donnée en la supprimant tout simplement
rm -f /var/lib/ldap/*
on relance slapd pour créer une base minimale
systemctl start slapd
puis on le recoupe pour taper
slapadd -l base.ldif
on relance ensuite slapd
systemctl start slapd
Il suffit de rajouter l'option -Z pour passer en connexion chiffrée, avec le mode debug en plus (-d 1), on doit obtenir ce genre de message
TLS trace: SSL_connect:before SSL initialization
TLS trace: SSL_connect:SSLv3/TLS write client hello
TLS trace: SSL_connect:SSLv3/TLS write client hello
TLS trace: SSL_connect:SSLv3/TLS read server hello
TLS trace: SSL_connect:TLSv1.3 read encrypted extensions
TLS certificate verification: depth: 0, err: 0, subject:
/CN=serveur-slapd.kervao.fr/OU=default ldap cert for
serveur-slapd.kervao.fr/emailAddress=root@serveur-slapd.kervao.fr,
issuer: /CN=serveur-slapd.kervao.fr/OU=default ldap cert for
serveur-slapd.kervao.fr/emailAddress=root@serveur-slapd.kervao.fr
TLS trace: SSL_connect:SSLv3/TLS read server certificate
TLS trace: SSL_connect:TLSv1.3 read server certificate verify
TLS trace: SSL_connect:SSLv3/TLS read finished
TLS trace: SSL_connect:SSLv3/TLS write change cipher spec
TLS trace: SSL_connect:SSLv3/TLS write finished
ldap_sasl_bind
ldap_send_initial_request
ldap_send_server_request
(...)
TLS trace: SSL_connect:SSL negotiation finished successfully
TLS trace: SSL_connect:SSL negotiation finished successfully
TLS trace: SSL_connect:SSLv3/TLS read server session ticket
TLS trace: SSL_connect:SSL negotiation finished successfully
TLS trace: SSL_connect:SSL negotiation finished successfully
TLS trace: SSL_connect:SSLv3/TLS read server session ticket
(...)
ldap_free_connection 1 1
ldap_send_unbind
ber_flush2: 7 bytes to sd 3
TLS trace: SSL3 alert write:warning:close notify
ldap_free_connection: actually freed
il y a une erreur avec le certificat qui est auto signé mais comme on a mis TLS_REQCERT allow dans le fichier ldap.conf ce n'est pas bloquant. Côté serveur cela donne cela
juil. 16 14:26:32
serveur-slapd.kervao.fr slapd[5289]: conn=1001 fd=11 ACCEPT from
IP=127.0.0.1:37634 (IP=0.0.0.0:389)
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=0
EXT oid=1.3.6.1.4.1.1466.20037
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=0
STARTTLS
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=0
RESULT oid= err=0 text=
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 fd=11
TLS established tls_ssf=256 ssf=256
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=1
BIND dn="" method=128
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=1
RESULT tag=97 err=0 text=
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=2
SRCH base="dc=kervao,dc=fr" scope=2 deref=0 filter="(objectClass=*)"
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=2
SEARCH RESULT tag=101 err=0 nentries=4 text=
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 op=3
UNBIND
juil. 16 14:26:32 serveur-slapd.kervao.fr slapd[5289]: conn=1001 fd=11
closed
[Retour page d'accueil FUNIX] |