19 mars 2024

Tuto Openldap, partie III : Peuplement

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.

 

 

 

4 réflexions sur « Tuto Openldap, partie III : Peuplement »

  1. 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

      1. 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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *