Troisième partie de la série de tuto sur OpenLDAP.
Dans la première partie, nous avons installé et configuré OpenLDAP. Ensuite, nous avons installé différents Overlays.
Nous allons maintenant remplir l’annuaire.
Article révisé en octobre 2022
I – Les OUs
Nous avions créé un répertoire /root/ldap/conf pour y mettre la configuration. Créons un répertoire pour y mettre les fichiers ldif contenant les données.
# cd /root/ldap # mkdir data # cd data
Pour rappel, les OUs sont des conteneurs qui permettent de ranger les données dans l’annuaire, de les hiérarchiser.
Il ne faut pas les confondre avec les groupes, dont nous verrons l’usage un peu plus tard.
Créez un fichier OU.ldif et remplissez le de la sorte :
dn: ou=people,dc=debugo,dc=fr ou: people objectClass: organizationalUnit dn: ou=group,dc=debugo,dc=fr ou: group objectClass: organizationalUnit dn: ou=system,dc=debugo,dc=fr ou: system objectClass: organizationalUnit dn: ou=debugo,ou=people,dc=debugo,dc=fr ou: debugo objectClass: organizationalUnit dn: ou=client,ou=people,dc=debugo,dc=fr ou: client objectClass: organizationalUnit dn: ou=sysgroup,ou=group,dc=debugo,dc=fr ou: sysgroup objectClass: organizationalUnit dn: ou=workgroup,ou=group,dc=debugo,dc=fr ou: workgroup objectClass: organizationalUnit
Les OUs que j’utilise me sont propres. Surement en aurez vous besoin d’autres, etc.. A vous de modifier.
On injecte :
# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f OU.ldif
II – Les utilisateurs
On va créer notre premier utilisateur.
Fichier user_niko.ldif :
dn: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson uid: niko sn: niko givenName: Nicolas cn: Nicolas displayName: Nicolas userPassword: password mail: mail@spam.com title: Admin initials: N
On met un mdp « temporaire », on le modifiera pas la suite et ca évite de laisser trainer une info sensible dans un fichier.
On injecte :
# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f user_niko.ldif
Profitons pour faire une explication sur ces lignes :
objectclass: person objectclass: organizationalPerson objectclass: inetOrgPerson
Notre utilisateur héritera des attributs de ces trois classes. Mais qu’est ce donc ?
Voyons un peu les schémas :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config"
Beaucoup d’infos, pour s’en sortir affichons les dn des schémas :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" dn
Ce qui nous affiche :
dn: cn=schema,cn=config dn: cn={0}core,cn=schema,cn=config dn: cn={1}cosine,cn=schema,cn=config dn: cn={2}nis,cn=schema,cn=config dn: cn={3}inetorgperson,cn=schema,cn=config dn: cn={4}ppolicy,cn=schema,cn=config
Concentrons nous sur le schéma core :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core"
La vous devez voir deux grands types de données : les olcObjectClasses et les olcAttributeTypes:
Les AttributeTypes sont les attributs que peuvent avoir les entrées de l’annuaire. Les ObjectClasses sont les regroupement de ces attributs.
Regardons les différents ObjectClasses qui composent notre schéma core :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core" olcObjectClasses
En cherchant dedans, on va trouver nos objectclasses person et organizationalPerson :
olcObjectClasses: {4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP top STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) ) olcObjectClasses: {5}( 2.5.6.7 NAME 'organizationalPerson' DESC 'RFC2256: an o rganizational person' SUP person STRUCTURAL MAY ( title $ x121Address $ regis teredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ fac simileTelephoneNumber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )
Ce qu’il faut comprendre :
L’ObjectClasses person hérite de top.
Must spécifie les AttributeTypes obligatoires : sn et cn.
May définie les AttributeTypes facultatives
Les AttributeTypes sont définis sur un modèle similaire, par exemple :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=schema,cn=config" "cn={0}core" olcAttributeTypes
J’en prend un au hasard :
olcAttributeTypes: {6}( 2.5.4.9 NAME ( 'street' 'streetAddress' ) DESC 'RFC225 6: street address of this object' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreS ubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
On trouve le nom de l’attribut, une description et son type (SYNTAX suivi d’un OID, je reviendrais sur ce point dans le chapitre consacré à la création d’un schéma).
L’objet que l’on créé hérite des attributs des classes person, organizationalPerson et inetOrgPerson.
Voila donc pour les explications sur les ObjectClasses et les AttributeTypes:
Au passage, on va vérifier quelques points.
Regardons comment est stocké le mdp dans la base :
# ldapsearch -xLLL -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "uid=niko"
On voit une ligne :
userPassword:: e1NTSEF9TklxSkd5YVFBdVcwMkpOVmplcjArOGYwRmNNMjNBVXg=
Il s’agit d’un codage en base64. Pour le décoder :
# echo e1NTSEF9TklxSkd5YVFBdVcwMkpOVmplcjArOGYwRmNNMjNBVXg= | base64 -d
Et la on le résultat suivant :
{SSHA}NIqJGyaQAuW02JNVjer0+8f0FcM23AUx
Le mot de passe est bien crypté comme configuré avec l’overlay ppolicy.
Et pour tester la connexion avec ce compte :
# ldapsearch -xLLLH ldap://localhost -D uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr -W -b "dc=debugo,dc=fr" "uid=niko"
Et si vous tapez le bon mot de passe, cela vous affiche votre propre fiche.
NB : Nous changerons le mdp dans la partie IV.
III – Les groupes
A noter, il existe deux types de groupes : les posixgroup et les groupofnames.
Les posixgroup sont similaires au groupes Unix, et les groupofnames ressemblent plus à des groupes AD.
Pour faire simple, l’avantage des groupofnames est qu’avec un filtre sur un utilisateur, on peut connaitre ses groupes (avec l’overlay memberof). Chose impossible avec les posixgroups.
Par contre, il est impératif d’avoir au moins un utilisateur dans un groupe de type groupofnames. Vous pouvez être tenté de vous mettre par défaut, mais le jour ou vous aller modifier votre schéma, vous allez devoir supprimer les utilisateurs, et un groupe sans utilisateur garde l’uid du dernier membre à l’avoir quitté et si vous refaite un compte avec le même uid, impossible de vous remettre dedans sans supprimer le groupe. Bref, perso, je met l’admin par défaut, comme ça pas de risques. De plus notre overlay refint configuré au préalable est raccord avec cela.
On créé un fichier group.ldif :
dn: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr cn: cloud description: Cloud objectClass: groupOfNames member: cn=admin,dc=debugo,dc=fr dn: cn=debugo,ou=workgroup,ou=group,dc=debugo,dc=fr cn: debugo description: Debugo objectClass: groupOfNames member: cn=admin,dc=debugo,dc=fr
J’ai mis dedans les groupes dont j’ai besoin, à vous de faire en fonction, etc…
# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f group.ldif
Au passage, on peut tester notre overlay memberof :
# ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "cn=admin" memberof
Doit nous retourner quelque chose qui ressemble à :
dn: cn=admin,dc=debugo,dc=fr memberOf: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr memberOf: cn=wiki,ou=sysgroup,ou=group,dc=debugo,dc=fr memberOf: cn=debugo,ou=workgroup,ou=group,dc=debugo,dc=fr
A la question, si je veux rajouter un utilisateur dans un groupe, comment faire ?
Je vous répond qu’avec OpenLdap, tout passe par des fichiers ldif, du coup, créez un fichier addusertogroup.ldif pour y mettre :
dn: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr changetype: modify add: member member: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr
Puis on injecte :
# ldapmodify -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f addusertogroup.ldif
Et la, si on requête cela :
ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "dc=debugo,dc=fr" "uid=niko" memberof
On doit avoir ceci :
dn: uid=niko,ou=debugo,ou=people,dc=debugo,dc=fr memberOf: cn=cloud,ou=sysgroup,ou=group,dc=debugo,dc=fr
Nous verrons plus en détail les ajouts, modifications, suppressions dans la partie suivante.
IV – Comptes Système et ACL
Par défaut, l’accès à l’annuaire est assez ouvert :
# ldapsearch -xLLL
On voit ce que l’accès anonyme nous affiche…
On va devoir filtrer un peu.
Tout d’abord, nous allons créer deux compte systèmes. Un viewer (qui aura des droits de lecture uniquement, utilisé par les applications pour se connecter à l’annuaire et vérifier des droits, au lieu de passe par le bind anonyme) et un Writer (qui lui aura des droits d’écriture…)
Créez le fichier viewer.ldif :
dn: cn=viewer,ou=system,dc=debugo,dc=fr objectClass: simpleSecurityObject objectClass: organizationalRole cn: viewer description: LDAP viewer userPassword: passview
Créez le fichier writer.ldif :
dn: cn=writer,ou=system,dc=debugo,dc=fr objectClass: simpleSecurityObject objectClass: organizationalRole cn: writer description: LDAP Writer userPassword: passwrite
Injectez :
# ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f viewer.ldif # ldapadd -cxWD cn=admin,dc=debugo,dc=fr -y /root/pwdldap -f writer.ldif
Voyons les ACLs par défaut :
# ldapsearch -x -H ldap://localhost -D cn=admin,dc=debugo,dc=fr -y /root/pwdldap -b "cn=config" "olcDatabase={1}mdb" olcaccess
Modifions les pour empêcher les connexions anonymes.
Créez un fichier acl.ldif :
dn: olcDatabase={1}mdb,cn=config changetype: modify replace: olcAccess olcAccess: to attrs=userPassword by self write by anonymous auth by dn="cn=writer,ou=system,dc=debugo,dc=fr" write by dn="cn=viewer,ou=system,dc=debugo,dc=fr" read by dn="cn=admin,dc=debugo,dc=fr" write by * none olcAccess: to dn.base="dc=debugo,dc=fr" by users read olcAccess: to * by self write by dn="cn=admin,dc=debugo,dc=fr" write by * read by anonymous none
J’expliquerais plus précisément le fonctionnement des ACLs dans un autre article. Nous modifions la deuxieme ACL qui par défaut donne accès en lecture à tout le monde. La, nous réduisons la lecture aux utilisateurs authentifiés.
On injecte :
ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f acl.ldif
On test de manière anonyme :
# ldapsearch -xLLL
Ça ne passe plus.
On teste avec notre compte viewer :
# ldapsearch -xLLL -H ldap://localhost -D cn=viewer,ou=system,dc=debugo,dc=fr -w passview -b "dc=debugo,dc=fr" "uid=niko"
Bingo !
Dans la prochaine partie, nous allons voir comment modifier les entrées de l’annuaire.
Merci, tout fonctionne bien, effectivement c’est assez obscur comme fonctionnement.
J’ai un élément qui ne répond pas : l’overlay memberof
la commande ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=tiko,dc=lan -y /root/pwdldap -b « dc=tiko,dc=lan » « uid=vhugo » memberof
n’indique pas comme toi la ligne memberOf
Je termine l ‘ensemble avant de revenir dessus
As tu bien ajouté ton user dans des groupes ?
Oui par exemple
ldapsearch -xLLLH ldap://localhost -D cn=admin,dc=tiko,dc=lan -y /root/pwdldap -b « dc=tiko,dc=lan »
permet de voir tout
dont cet extrait
dn: cn=cloud,ou=sysgroup,ou=group,dc=tiko,dc=lan
cn: cloud
description: Cloud
objectClass: groupOfNames
member: cn=admin,dc=tiko,dc=lan
member: uid=vhugo,ou=tiko,ou=people,dc=tiko,dc=lan
L’overlay a bien été configuré (les deux étapes…) ?