Logo Khaganat
Traductions de cette page?:

Ceci est une ancienne révision du document !


Openldap

C'est LE backend de référence. Ça fait le café, d'après les chamanes des profondeurs les plus lointaines de la Crypte.

Ne suivez pas ce qui suit trop aveuglément, je me rends compte que j'ai rien compris à certains morceaux, qui sont datés, et donc que ça risque d'être crasseux.

Installation

Pour l'installer :

sudo apt install slapd ldap-utils

La configuration par défaut s'appuie sur le FQDN de la machine. Avant de tout bidouiller, vérifions…

sudo slapcat | grep dn:

Le résultat devrait être “dn: dc=example,dc=org” (ou autre domaine). Si c'est ce que vous voulez, parfait. Sinon, dpkg-reconfigure slapd, répondre “non” à “Omit OpenLDAP server configuration?” et ensuite adapter le reste. À la fin, à la question “Do you want the database to be removed when slapd is purged?”, répondre “Oui”.

On peut admirer la base de son annuaire avec la commande suivante :

ldapsearch -x -LLL -H ldap://localhost -b "dc=example,dc=org"

Dans mon cas, avec l'installation par défaut et un “domaine” appelé ldap.local :

# ldapsearch -x -LLL -H ldap://localhost -b "dc=ldap,dc=local"
dn: dc=ldap,dc=local
objectClass: top
objectClass: dcObject
objectClass: organization
o: ldap.local
dc: ldap

Concernant la structure et la configuration d'Openldap, cela reste assez difficile à lire au début mais c'est assez “logique” pour s'apprendre au fil des manipulations.

Un petit coup de tree /etc/ldap/ permet de voir qu'on a deux types de fichiers : .schema et .ldif. Et des noms de dossiers étranges, qui utilisent en fait la syntaxe de ldap. L'une des parties qu'on va bidouiller est ici :

└── slapd.d
    ├── cn=config
    │   ├── cn=module{0}.ldif
    │   ├── cn=schema
    │   │   ├── cn={0}core.ldif
    │   │   ├── cn={1}cosine.ldif
    │   │   ├── cn={2}nis.ldif
    │   │   └── cn={3}inetorgperson.ldif
    │   ├── cn=schema.ldif
    │   ├── olcDatabase={0}config.ldif
    │   ├── olcDatabase={-1}frontend.ldif
    │   └── olcDatabase={1}mdb.ldif
    └── cn=config.ldif

Ce qui est dans le dossier cn=config concerne… la configuration. Autrefois il y avait un fichier “/etc/ldap/sldap.conf”, si je comprend bien ce n'est plus trop d'actualité. Mais on n'édite pas directement les ldif ici, il faut passer par l'utilitaire ldapmodify.

Dans la suite du document, nous allons donc écrire nos documents “ldif”, puis les injecter dans l'annuaire avec cette commande “ldapmodify”. Il est conseillé de bosser dans un répertoire dédié (par exemple /root/ldap/conf/) histoire de tout nettoyer à la fin avec un petit “rm -R”. Ou de garder trace des bidouilles effectuées.

En fait, LDAP étant un vieux dinosaure utilisé très largement, l'usage de “/etc/ldap/sldap.conf” reste possible. C'est cependant déconseillé et considéré comme une pratique obsolète depuis la version 2.3. L'usage du fichier de configuration “sldap.conf” demande un redémarrage du service à chaque modification, alors que la modification de la configuration dans l'arbre ldap lui-même (via ces fichiers ldif dans “cn=config” est immédiatement pris en compte.

Cela semble anodin lors des tests, mais un gros annuaire peut mettre beaucoup de temps à redémarrer… Alors autant prendre l'habitude des bonnes pratiques, même si la syntaxe pique les yeux.

Avoir des logs plus bavards

Pour avoir des logs plus complets, il va falloir l'activer. On commence par copier le truc actuel, qu'on va bidouiller avant de réinjecter :

# ldapsearch -Y external -H ldapi:/// -b cn=config "(objectClass=olcGlobal)" olcLogLevel -LLL > log.ldif

Ce fichier “log.ldif” est assez court par défaut, il contient deux lignes :

  • dn: cn=config : ça veut dire que c'est de la configuration (ne pas bidouiller ce nom !)
  • olcLogLevel: none : “olcLogLevel” c'est le niveau de log, forcément “none” c'est pas bavard… Au choix :
    • -1 : enable all debugging
    • 0 : no debugging
    • 1 : trace function calls
    • 2 : debug packet handling
    • 4 : heavy trace debugging
    • 8 : connection management
    • 16 : print out packets sent and received
    • 32 : search filter processing
    • 64 : configuration file processing
    • 128 : access control list processing
    • 256 : stats log connections/operations/results
    • 512 : stats log entries sent
    • 1024 : print communication with shell backends
    • 2048 : print entry parsing debugging

On va faire ceci :

log.ldif
dn: cn=config
changetype: modify
replace: olcLogLevel
olcLogLevel: 256

On injecte avec la commande suivante :

# ldapmodify -Y EXTERNAL -H ldapi:/// -f log.ldif

On peut vérifier le résultat avec ça :

# ldapsearch -Y external -H ldapi:/// -b cn=config "(objectClass=olcGlobal)" olcLogLevel

Ou simplement en faisant une requête avec slapd (par exemple ldapsearch -Y external -H ldapi:/// -b dc=ldap,dc=local ) et en admirant le résultat avec tail -f /var/log/syslog.

On retrouve les logs propres à slapd aussi dans journalctl :

journalctl -eu slapd.service

J'ai des trucs dans /var/log/syslog parce que je demande à systemd de m'écrire ce genre de log.

Il y a moyen de paramétrer pour que ce soit dans un fichier de log propre à slapd. Les infos sont par défaut envoyés à “local4”1). Yep, y'a d'autres logiciels qui loguent de façon plus clair, mais visiblement local4 n'est pas trop utilisé par ailleurs et de toute façon sur le serveur avec openldap on ne devrait pas avoir trop d'autres services. On va donc dire à rsyslog d'envoyer le flux de local4 dans un fichier de log séparé via /etc/rsyslog.d/ldap.conf.

/etc/rsyslog.d/ldap.conf
local4.*    /var/log/ldap.log

Puis on redémarre rsyslog :

sudo systemctl restart rsyslog

Overlays

Les overlays sont des fonctionnalités supplémentaires qui se rajoutent. (Source)

La doc complète est sur https://www.openldap.org/doc/admin26/overlays.html ; je ne documente ici que ce qui nous est utile.

La configuration demande plusieurs fichiers : un pour l'activation (utile juste une fois), l'autre pour la configuration (donc pouvant changer avec le temps).

Généralement (mais pas toujours) nous avons un module à activer qui va fournir une fonctionnalité de base, puis l'overlay lui-même qui indique comment utiliser les fonctionnalités du module ou ajoute des fonctionnalités à LDAP. Les modules (extensions en .so et .la) sont des bibliothèques compilées pour Openldap. Ils sont généralement dans /usr/lib/ldap/

Certains overlay sont assez essentiels :

  • memberOf : liste les groupes dont une utilisatrice est membre
  • refint : cohérence de l'annuaire lors de suppression d'entrées, pour éviter les membres fantômes et les groupes vides par erreur.
  • auditlog : journalisation des modifications. Loguer, c'est bien ! Celui-ci ne logue que les opérations affectant les données (add, delete, modify, modrdn). Ça suffit pour voir quand quelqu'un change son mot de passe.
    • accesslog : journalise tous les accès read et write (donc aussi search, compare, bind,write), et les connexions (échouées ou réussis). Cela peut être utile mais ça va impacter fortement les performances. Donc… pas tout de suite.
  • unique : s'assurer que certaines données sont uniques (UID par exemple, ou pseudo, ou mail).
  • ppolicy : politique de mots de passe (complexité, expiration, verrouillage)
  • constraint : ajoute des contraintes sur les attributs, pour éviter de rentrer n'importe quoi (et donc de mettre en pseudo un truc qui va faire cracher les cms). Cela peut être des contraintes du type “une membre doit renseigner un mail” ou “si Untelle est membre de sysadmin, alors elle doit avoir renseigner aussi son téléphone”
  • valsort : ordonne les résultats. Par exemple renseigner certains groupes (genre les assos) avant d'autres (genre les sous-groupes d'assos).

Ceux où je ne sais pas encore quand ce sera utile (mais ça le sera très certainement à un moment)

  • collect : je n'en suis pas absolument sûre mais vu ce que je prévois comme architecture, ça devrait être utile. Cela permet d'aggréger les données, et donc quand on demande par exemple des infos sur “pseudo” on aie aussi plus facilement des données annexes sans multiplier les requêtes (par exemple, tous les groupes dont le pseudo fait partie ?)
  • syncprov : pour répliquer les infos entre serveurs OpenLDAP (et oui, vu le côté critique de la bestiole, on va redonder).
  • translucent : proxy stockant localement certains attributs. Cas d'usage : si un des serveurs a un usage intensif de LDAP, il y aura un ldap sur le serveur en question, avec un cache local, qui se synchronisera avec le reste “quand y'a le temps”. On est sur des questions de latence, bref on verra quand ça commencera à ramer ! Potentiellement le serveur de jeu.

J'ai compris ça avec la doc et quelques exemples piochés sur le web et autant dire que je ne suis pas sûre de moi. Donc lisez aussi la doc, et corrigez si j'ai mal traduit/compris.

MemberOf

Cela permet de lister plus facilement de quels groupes une utilisatrice est membre.

Créer les documents suivants :

memberof_act.ldif
dn: cn=module,cn=config
cn:module
objectclass: olcModuleList
objectclass: top
olcmoduleload: memberof.la
olcmodulepath: /usr/lib/ldap
memberof_conf.ldif
dn: olcOverlay=memberof,olcDatabase={1}mdb,cn=config
changetype: add
objectClass: olcMemberOf
objectClass: olcOverlayConfig
objectClass: olcConfig
objectClass: top
olcOverlay: memberof
olcMemberOfDangling: ignore
olcMemberOfRefInt: TRUE
olcMemberOfGroupOC: groupOfNames
olcMemberOfMemberAD: member
olcMemberOfMemberOfAD: memberOf

Puis on injecte ces fichiers :

root
ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_act.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f memberof_conf.ldif

Pour vérifier la configuration, au choix, une de ces commandes dans le terminal :

ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"
tree /etc/ldap/slapd.d/
ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcmemberOf"

Pour chercher tous les groupes dont Truc est membre :

ldapsearch -xLLL  "(uid=truc)" memberof

Cohérence de l'annuaire lors de suppression d'entrées (refint)

Cela évitera d'avoir des membres fantômes qui ne sont plus liés à rien. Si une utilisatrice est supprimée, alors elle le sera aussi des groupes dans lesquels elle était. Si un groupe se retrouve vide, l'admin y est automatiquement ajouté (ce qui évitera des erreurs).

Créer les fichiers suivants :

refint_act.ldif
dn: cn=module,cn=config
cn: module
objectclass: olcModuleList
objectclass: top
olcmoduleload: refint.la
olcmodulepath: /usr/lib/ldap
refint_conf.ldif
dn: olcOverlay=refint,olcDatabase={1}mdb,cn=config
objectClass: olcConfig
objectClass: olcOverlayConfig
objectClass: olcRefintConfig
objectClass: top
olcOverlay: refint
olcRefintAttribute: memberof member manager owner
olcRefintNothing: cn=admin,dc=ldap,dc=local

Injection

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f refint_act.ldif
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f refint_conf.ldif

Vérification, et vérification de la configuration :

ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"
ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcRefintConfig"

Enregistrer les modifications de l'annuaire (auditlog)

Ce qui pourra être utile pour savoir ce qui s'est passé.

On commence par créer le dossier où cela s'écrira (automatique suivant comment on a configuré ses logs par ailleurs…) :

mkdir -m 755 -p /var/log/openldap
touch /var/log/openldap/auditlog.log
chmod 755 /var/log/openldap/auditlog.log
chown -R openldap:openldap /var/log/openldap

Puis on crée les fichiers :

auditlog_act.ldif
dn: cn=module,cn=config
cn: module
objectclass: olcModuleList
objectclass: top
olcModuleLoad: auditlog.la
olcmodulepath: /usr/lib/ldap
auditlog_conf.ldif
dn: olcOverlay=auditlog,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcAuditLogConfig
olcOverlay: auditlog
olcAuditlogFile: /var/log/openldap/auditlog.log

Injection :

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f auditlog_act.ldif
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f auditlog_conf.ldif

Vérification :

ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"
ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcAuditLogConfig"

Unicité des attributs (unique)

C'est par exemple pour que les UID attribués à chacune soit bien uniques. Ou qu'une adresse mail ne soit liée qu'à une seule personne. Éviter les doublons sur les attributs évitera des erreurs, voir des exploits, et améliore les recherches.

Créer les fichiers suivants :

unique_act.ldif
dn: cn=module,cn=config
cn: module
objectclass: olcModuleList
objectclass: top
olcModuleLoad: unique.la
olcmodulepath: /usr/lib/ldap

Attention ici, remplacez dc=ldap,dc=local par votre DC. Notez aussi qu'on va forcer l'unicité uniquement sur quelques attributs :

  • L'uid, qui doit absolument être unique… utilisé dans la base elle-même, c'est du “texte”
  • L'uidNumber, qui est forcément un nombre, sert entre autre quand il y a une utilisatrice linux liée (identifiant numérique utilisé par le système)
  • le mail (utilisé pour récupérer son mot de passe, mais à voir avec la possibilité d'avoir plusieurs “pseudo” pour une seule personne… Pour le moment, on reste en “unique”.
  • La portée (?sub) précise que cela s'applique aux sous-arbres.
unique_conf.ldif
dn: olcOverlay=unique,olcDatabase={1}mdb,cn=config
objectClass: olcOverlayConfig
objectClass: olcUniqueConfig
olcOverlay: unique
olcUniqueUri: ldap:///ou=people,dc=ldap,dc=local?uid?sub
olcUniqueUri: ldap:///ou=people,dc=ldap,dc=local?mail?sub
olcUniqueUri: ldap:///ou=people,dc=ldap,dc=local?uidNumber?sub

Injection :

ldapadd -Q -Y EXTERNAL -H ldapi:/// -f unique_act.ldif
ldapadd -Q -Y EXTERNAL -H ldapi:/// -f unique_conf.ldif

Vérification :

ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcModuleList"
ldapsearch -QLLLY EXTERNAL -H ldapi:/// -b "cn=config" "Objectclass=olcUniqueConfig"

Policy

Je suis Debuguo MAIS je ne sais pas encore quels contraintes vont être amenées par Oauth et compagnie, et je ne suis pas encore certaine que ces paramètres sont “bons”. Mais après réflexion, ça me semble quand même mieux que rien pour mes tests.

Par ailleurs ma méthode est un peu différente, puisque j'active le module de ppolicy.

La “policy” est donc la politique de mots de passe, y compris : les utilisatrices peuvent-elles changer leurs mots de passe ? Combien d'essais de connexion avant de bloquer ? Etc. Je ne sais pas trop où on définit le type de hash (je vais chercher).

On commence par charger le module ppolicy. Et du coup on vérifie avant tout s'il existe (sinon, voir le tuto de Debuguo, mais chez moi “ça marchait pas”) :

find /usr/lib/ldap -name "*ppolicy*"

Type de retour attendu :

/usr/lib/ldap/ppolicy.so
/usr/lib/ldap/ppolicy.la

Pour charger le module, on crée le fichier ldif suivant :

ppolicy_module.ldif
dn: cn=module{0},cn=config
changetype: modify
add: olcModuleLoad
olcModuleLoad: ppolicy

Et appliquer :

ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f ppolicy_module.ldif

Pour vérifier la liste des modules (ppolicy doit apparaitre dedans) :

ldapsearch -Q -Y EXTERNAL -H ldapi:/// -b cn=config | grep olcModuleLoad

Plus de doc

1)
Cherchez de la doc sur “facility”, le petit nom de ces canaux ; c'est sur les facility de local0 à local7 que les applications sont censées envoyer leurs infos
CC Attribution-Share Alike 4.0 International Driven by DokuWiki
fr/openldap.1758402119.txt.gz · Dernière modification : de zatalyz

Licences Mentions légales Accueil du site Contact Inclusion