Journal LDAP, un peu de technique.

Posté par  (site web personnel) . Licence CC By‑SA.
42
21
juin
2013

Sommaire

Dans mon journal d'hier, je parlais de LDAP d'un point de vue utilités. Je propose ici de se plonger un peu plus dans le côté technique.

Comme référence, j'utilise l'installation et la configuration du paquet slapd sous debian, nul doute que cela marchera à d'autres endroits sur d'autres OS. Installez donc slapd, et ldap-tools.

Une histoire de schéma.

Avant de se plonger dans une partie configuration du serveur LDAP proprement dit, nous allons revenir sur ces histoires de schéma LDAP. Chez moi, les schémas par défaut se trouvent dans /etc/ldap/schema. Ils ne sont pas « préchargés » automatiquement, la configuration prise en compte se trouve dans /etc/ldap/slapd.d, mais ils permettent de comprendre un peu ce qu'il se passe.

Des attributs…

Bon, ce titre fait un peu cliffhanger de derrière les fagots… Passons. Une base LDAP sert à stocker des objets, inscrits dans des nœuds, ayant parent et enfants. Les propriétés d'un objet dépendent de celui-ci. Ici, avant de nous intéresser à l'objet proprement dit, on va se pencher sur les attributs. (on peut ce référer à cette page web pour plus d'informations)

Dans l'ancien format des bases LDAP, pour les schémas, les attributs se représentaient de la façon suivante :

attributetype ( 1.3.6.1.1.1.1.2 NAME 'gecos'
    DESC 'The GECOS field; the common name'
    EQUALITY caseIgnoreIA5Match
    SUBSTR caseIgnoreIA5SubstringsMatch
    SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

Vous croiserez cet attribut dans /etc/ldap/schema/nis.schema.

  • attributetype signifie qu'on déclare un attribut, tout ce qui suit se trouve entre parenthèses.
  • La suite de numéros bizarres est un OID, un identifiant unique, qui permet de représenter votre attribut. Une des spécificités de LDAP est de proposer de le voir comme un arbre mondial, la racine de votre base serait donc virtuellement un des enfants d'un arbre LDAP imaginaire qui serait la propriété des gourous de LDAP. L'identifiant en question permettrait de dire "cet attribut est l'attribut numéro 2 du schéma nis".
  • NAME 'nom' définit le nom de l'attribut, on s'y réfère ainsi par la suite. Il est préférable pour la lisibilité de se limiter aux caractères ASCII.
  • DESC 'description' est une description de l'attribut. Dans la mesure du possible, on se limite aux caractères ASCII.
  • EQUALITY compMethod définit une méthode de comparaison pour l'égalité, c'est une contrainte implicite pour dire que notre attribut est un entier, ou une chaîne de caractère ou autre chose…
  • SUBSTR compMethod propose la même chose que EQUALITY, mais pour un sous-ensemble de l'attribut (chercher "coucou" dans la phrase "coucou, comment vas-tu ?" par exemple).
  • SYNTAX PLEIN.DE.CHIFFRES définit une contrainte sur la variable. La suite de chiffre est un OID qui pointe vers un type d'attribut précis. Par exemple, si vous utilisez SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{123}, vous définissez une chaîne de caractère quasi-ASCII de longueur maximale 123 caractères. Si vous essayez de définir un attribut avec cette syntaxe et de balancer un "é" dedans, LDAP vous inondera de son amour et de sa croyance en vos capacités de leader religieux.
  • SINGLE-VALUE signifie que l'attribut est monovalué. Autrement dit, un objet ne peut avoir deux gecos. Il n'en a au plus qu'un.

Référez-vous au lien que je vous ai fourni pour plus d'informations.

Pourquoi vous parler de l'ancienne syntaxe si elle n'est justement plus d'actualité ? Parce que la nouvelle syntaxe correspond aux schémas définis directement dans la base LDAP de configuration, qu'elle diffère peu de l'ancienne, et que lorsqu'on crée sa base LDAP, et qu'on la configure pour la première fois, créer un schéma dans un fichier puis le faire incorporer dans la base via la commande slaptest est bien plus agréable et facile.

La nouvelle syntaxe est une syntaxe compatible avec ldif, voici le même attribut dans cette syntaxe.

olcAttributeTypes: ( 1.3.6.1.1.1.1.2 NAME 'gecos' DESC 'The GECOS field; the common name' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )

C'est très proche de l'ancienne syntaxe, mais compatible avec ldif. Regardez nis.ldif en comparaison avec nis.schema.

…et des objets

Une fois qu'on a nos attributs, on souhaite créer des objets. Toujours dans nis, regardez en bas du fichier.

objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount'
    DESC 'Abstraction of an account with POSIX attributes'
    SUP top AUXILIARY
    MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory )
    MAY ( userPassword $ loginShell $ gecos $ description ) )

Et en nouvelle syntaxe :

olcObjectClasses: ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction of an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) )

  • objectclass signifie qu'on déclare un objet.
  • L'OID est également unique, comme pour les attributs
  • NAME définit toujours un nom, si possible avec des caractères ASCII exclusivement
  • DESC décrit l'objet
  • SUP définit un objet parent (celui qu'on définit hérite de ses propriétés)
  • La déclaration AUXILIARY est plus compliquée. Ici, on peut écrire STRUCTURAL, AUXILIARY ou ABSTRACT. Lorsqu'on crée un nœud et lui donne des informations, parmi les attributs objectClass, qui vont définir quels autres attributs un objet peut avoir, il doit y avoir un (et un seul) objectClass pointant vers un élément STRUCTURAL, et autant que l'on souhaite vers des éléments AUXILIARY, ou ABSTRACT. Un élément ne peut hériter que d'un élément du même type, ou d'un ABSTRACT. Donc un élément AUXILIARY ne peut pas hériter d'un STRUCTURAL, et réciproquement. Les éléments STRUCTURAL représentent des objets concrets. Ici, posixAccount est AUXILIARY : un objet ne pourra pas être juste un posixAccount.
  • MUST ( attributs séparés par des $ ) indique la liste des attributs qu'un objet doit posséder en au moins un exemplaire.
  • MAY ( attributs séparés par des $ ) indique les attributs supplémentaires qu'un objet peut posséder.

Voilà pour les schémas, une fois ceci compris, imaginons qu'en plus des éléments dans nis, on ait défini un schéma personnel avec cet objectClass :

olcObjectClasses: ( 1.2.3.1.2.3.1.2.3.10 NAME 'userAccount' DESC 'Implementation of a user account' SUP top STRUCTURAL MUST ( fname $ name ) MAY ( mail $ town ) )

Avec mail, town, name et fname des attributs définissant email, ville, nom et prénom.

Un compte d'utilisateur pourrait alors être l'objet avec les attributs :

dn: uid=peb,ou=users,dc=localdomain
objectClass: userAccount
objectClass: posixAccount
cn: PEB
fname: PE
gidNumber: 100
homeDirectory: /home/peb
loginShell: /bin/zsh
mail: peb@yopmail.com
name: B
uid: peb
uidNumber: 2573
userPassword: {SSHA}Sdduv35Y4x/49FeFmrroxXXlrpgff

La syntaxe ici est celle de LDIF. On y reviendra, mais vous savez désormais à quoi ressemblent les objets dans une base LDAP.

Configuration de slapd.

Ça va vous sembler extrême, mais la première chose à faire après avoir installé slapd est cette série de commandes.

# /etc/init.d/slapd stop
# rm -rf /etc/ldap/slapd.d/*
# rm -rf /var/lib/ldap/[^D]*

On va démarrer avec un environnement propre, et faire une configuration nous-même. Il est possible que la configuration initiale vous ait convenu, mais l'objectif est de comprendre ce qu'il se passe.

Écriture d'un fichier slapd.conf

Je vous propose ici de construire notre fichier /etc/ldap/slapd.conf, je vais partir sur un exemple simple, mais n'hésitez pas à l'aide de la documentation à rendre le votre plus complet, et adapté à vos envies.

#######################################################################
# Directives globales:

# Définition des schémas et objectClasses
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
include         /etc/ldap/schema/dyngroup.schema
include         /etc/ldap/schema/perso.schema

Ici, on commence par inclure les schémas prééexistants qui peuvent servir, et notre schéma personnel.

# Emplacement du pidfile
pidfile         /var/run/slapd/slapd.pid

# Arguments passés au serveur
argsfile        /var/run/slapd/slapd.args

# Niveau de journalisation
loglevel        0

Ensuite, quelques configurations basiques, pour les besoins du logiciel. loglevel 0 signifie qu'on le loggue rien dans syslog. Regardez loglevel dans la manpage de slapd.conf pour plus d'infos. Un bon niveau de logging quand on fait du débug est 255, mais attention, c'est extrêmement verbeux, et un serveur limité en ressources se fait souvent overloader par ce niveau de logging. (testé et désapprouvé sur un domu)

# Stockage des modules
modulepath      /usr/lib/ldap
moduleload      back_bdb

On définit ici le répertoire des modules, et on charge back_bdb, qui fournit le type de base LDAP "Berkley DB", que j'aime bien.

# Limitation du nombre de réponses
sizelimit       1000000000

Limite du nombre d'objets que la base peut simultanément retourner.

# Méthode pour crypter les mots de passe
password-hash   {SSHA}

###############################################################
# Directives de configuration pour le backend bdb
backend         bdb

Ici, on précise type de backend pour lequel les options à venir s'appliquent. Comme il n'y a pas d'autre option, je ne suis pas convaincu que ça soit utile.

#######################################################################
# Configuration de la base de données principale
database        bdb

Ici, on déclare une nouvelle base de données, de type Berkley DB, tout ce qui suivra jusqu'à une autre déclaration générale concerne cette base. Certaines directives sont spécifiques au backend, comme on peut le voir ici.

# Racine
suffix          "dc=localdomain"

Nom du nœud racine.

# Répertoire de stockage de la base de données
directory       "/var/lib/ldap"

(Backend-dependant) Il peut être plus adapté lorsqu'on souhaite créer plusieurs bases de données de les mettre dans des répertoires distincts, il faut pour cela que le backend le permette.

# Options d'indexation pour la base de données
index           entryUUID,entryCSN eq
index           objectClass,uid,uidNumber eq
index           cn,sn eq,approx,sub
index           mail,town eq
index           name,fname eq,approx,sub

(Backend-dependant) Les index ont à peu près les mêmes utilités que pour une base SQL par exemple : diminuer le temps de processing pendant les recherches. Les index sont créés à l'ajout d'un objet dans la base ldap, ou à la modification des attributs sur lesquels ils sont placés.

# Sauvegarde des timestamps de modifications des objets
lastmod         on

# LDAP a besoin de la déclaration du rootdn
rootdn "cn=admin,dc=localdomain"
rootpw "{SSHA}HASH"

Ici, on définit l'administrateur de la base, avec pour mot de passe un hash. Pour générer un ssha à partir d'un mot de passe, utilisez la commande slappasswd, et collez sa sortie à la place de "{SSHA}HASH".

# L'attribut userPassword doit pouvoir être écrit uniquement par
# soi-même, l'admin, les replicas. Dovecot peut le lire, et on peut
# s'authentifier avec anonymement

access to attrs=userPassword
       by dn.regex="cn=dovecot,dc=localdomain" read
       by anonymous auth
       by self write
       by * none

# Permettre l'accès à la base pour des trucs comme 
# "supportedSASLMechanisms", pour éviter des problèmes
# possibles si les méthodes SASL ne sont pas connues.
access to dn.base="" by * read

# Pour postfix
access to dn.regex="^uid=[0-9]+,ou=users,dc=localdomain$$" attrs=mail,alias,uid,mail,entry,objectClass
       by dn.regex="cn=postfix,dc=localdomain" read
       by * break

# Pour dovecot
access to dn.regex="^uid=[0-9]+,ou=users,dc=localdomain$$" attrs=uid,homeDirectory,uidNumber,gidNumber,userPassword,objectClass,entry
       by dn.regex="cn=dovecot,dc=localdomain" read
       by * break

# Informations accessibles à tous
access to dn.regex="^uid=[0-9]+,ou=users,dc=localdomain$$" attrs=uid,homeDirectory,uidNumber,gidNumber,gecos,objectClass,entry
       by anonymous read
       by * break

access to dn="ou=users,dc=localdomain"
       by anonymous search
       by * break

access to dn.subtree="ou=Group,dc=linkki,dc=crans,dc=org"
       by anonymous read
       by * break

# L'admin et readonly peuvent tout lire 
# can read everything.
access to *
       by dn.regex="cn=admin,dc=localdomain" write
       by sockname.regex="ldapi" read
       by dn.regex="cn=readonly,dc=localdomain" read
       by self read
       by * none

Ici, on configure les acl. Ils ne sont pas dépendants du backend, comme c'est un des points les plus techniques de LDAP, j'en reparlerai dans un journal séparé, après avoir pu faire mon lot de tests.

Vous noterez que ça parle de dovecot et postfix, l'idée est de montrer un cas où on va créer des utilisateurs administratifs de LDAP pour dovecot et postfix à des fins d'interfaçage.

Voilà, la configuration est finie, votre fichier slapd.conf est prêt.

Il ne reste qu'à exécuter la commande

# sudo -u openldap slaptest -f /etc/ldap/slapd.conf -F /etc/ldap/slapd.d

Il est possible que slaptest vous sorte une erreur, due au fait que id2entry.bdb n'existe pas, c'est normal, puisqu'on avait fait le ménage, mais la configuration est bien faite. Faites

# /etc/init.d/slapd start

Votre base LDAP tourne (et id2entry a été créé), mais… est vide.

Peupler une base LDAP

On y est, on va ici apprendre à ajouter des données, donc à créer des petits fichiers au format LDIF, puis à utiliser ldapadd, voire ldapmodify. Une fois cela fait, on arrêtera ici pour cette initiation. Un journal parlera des ACL, et un autre de la modification à chaud du schéma, des configs, et la réplication.

Premiers objets.

Il faut créer le nœud racine, et nous allons en plus créer deux nœuds, ou=groups, et ou=users. Lorsqu'on souhaite ajouter des objets, la syntaxe ldif est très simple, il suffit de donner l'ensemble des informations concernant les divers objets, séparés par des lignes vides. Avant chaque :, on a le nom d'attribut, et après, une espace puis la valeur de l'attribut.

dn: dc=localdomain
objectClass: top
objectClass: dcObject
objectClass: organization
dc: localdomain
o: localdomain

dn: ou=users,dc=localdomain
objectClass: top
objectClass: organizationalUnit
ou: users

dn: ou=groups,dc=localdomain
objectClass: top
objectClass: organizationalUnit
ou: groups

On enregistre ces lignes dans un fichier /tmp/begin.ldif, puis on effectue la commande

$ ldapadd -H ldap://127.0.0.1 -D "cn=admin,dc=localdomain" -W -f /tmp/begin.ldif

  • -H permet d'indiquer l'hôte à contacter.
  • -D permet de préciser l'utilisateur avec lequel on effectue l'opération
  • -W signifie qu'on entre le mot de passe de l'utilisateur en command line
  • -f permet de préciser un fichier (sinon, on utilise l'entrée standard)

Tapez le mot de passe de votre admin ("Plop", chez moi), et le tour est joué.

Ajout d'objets plus concrets, modifications.

Vous devriez, via ldapadd, et un fichier, pouvoir créer un utilisateur voisin de celui que j'avais proposé ci-dessus.

dn: uid=peb,ou=users,dc=localdomain
objectClass: userAccount
objectClass: posixAccount
cn: PEB
fname: PEB
gidNumber: 100
homeDirectory: /ghome/peb
loginShell: /sbin/zsh
mail: peb@yopmail.com
name: B
uid: peb
uidNumber: 2573
userPassword: {SSHA}Sdduv35Y4x/49FeFmrroxXXlrpgff

Malheureusement, comme vous l'avez sûrement constaté, je suis très mauvais pour copier/coller, et des erreurs de scénario se sont glissées dans l'utilisateur. Apprenons maintenant à les corriger.

La syntaxe change quelque peu, puisqu'on va devoir utiliser ldapmodify : il faut préciser le dn de l'objet à modifier, puis le type de changement à lui apporter. Pour une zoologie des types de changements, se rendre ici. Ensuite, il faut préciser les attributs que l'on modifie. On sépare les modifications par des lignes contenant juste un tiret d'union.

dn: uid=peb,ou=users,dc=localdomain
changetype: modify
replace: prenom
prenom: PE
-
delete: homeDirectory
homeDirectory: /ghome/peb
-
add: homeDirectory
homeDirectory: /home/peb
-
delete: loginShell
-
add: loginShell
loginShell: /bin/zsh

  • add ajoute un ou plusieurs attributs de même type.
  • delete en efface un ou plusieurs s'ils sont spécifiés (cf homeDirectory), tous si on se contente d'annoncer un delete: loginShell, par exemple.
  • Pour remplacer un attribut par un autre, on peut l'effacer, et en ajouter un nouveau, ou alors utiliser replace, qui remplace tous les attributs par la même valeur.

Les trois méthodes possibles pour faire des corrections ont été utilisées ci-dessus. On sauvegarde ce LDIF dans /tmp/modif.ldif, et on appelle alors la commande

$ ldapmodify -H ldap://127.0.0.1 -D "cn=admin,dc=localdomain" -W -f /tmp/modif.ldif

On donne le mot de passe, et le tour est joué.

Pour effacer des entrées, on peut utiliser ldapdelete, ou ldapmodify avec le changetype delete.

De la doc, encore de la doc.

  • Zytrax, toujours aussi complet
  • OpenLdap, toujours gérants du projet openldap
  • Google, et vos amis.

Bonne lecture. :o)

  • # Très bonne doc

    Posté par  . Évalué à 2.

    Merci pour la grande explication et le partage. ;)

    Merci aux personnes qui mon aidé a trouvé des solutions pour essayer d’écrire sans faute d’orthographe.

  • # configuration par cn=config

    Posté par  . Évalué à 8. Dernière modification le 21 juin 2013 à 08:35.

    Il est plus que conseillé maintenant de faire la configuration directement par le protocole ldap lui-même. L'arbre cn=config contient justement toute la configuration.

    L'avantage majeur est que c'est dynamique : pas besoin de redémarrer le serveur après une modification. L'inconvénient est que pour le débutant, il faut savoir utiliser les outils client ldapadd/ldapmodify. Go go Zytrax pour plus de précision.

    Mais si on en est à se poser la question de refaire la configuration par défaut, je pense que cela vaut le coup.

    Bonne doc pour commencer sinon !

    • [^] # Re: configuration par cn=config

      Posté par  (site web personnel) . Évalué à 2.

      La config chez moi est poussé par un serveur central via cfengine. Le tout est versionné. Parfois, il est préférable de rester en mode fichier car cela permet de garder des traces et un historique clair de toute modification.

      Ensuite, il y a l'aspect sécurité ou le mode fichier me semble plus sur.

      • [^] # Re: configuration par cn=config

        Posté par  . Évalué à 4.

        Je tourne avec Puppet, et j'ai fait la conf openldap par le backend cn=config. Et la recette puppet décrivant mon infrastructure ldap est versionnée, on a ainsi le meilleur des 2 mondes.

      • [^] # Re: configuration par cn=config

        Posté par  (site web personnel) . Évalué à 3.

        Il me semble que la config reste sous la forme de fichiers textes (probablement format ldif), stockés dans un sous-répertoire de /etc. En cas de raté lors de la config - du genre qui fait qu'on ne peut plus se connecter au LDAP… ça permet de rattraper le coup.

        Python 3 - Apprendre à programmer dans l'écosystème Python → https://www.dunod.com/EAN/9782100809141

      • [^] # Re: configuration par cn=config

        Posté par  . Évalué à 3.

        Ensuite, il y a l'aspect sécurité ou le mode fichier me semble plus sur.

        Je ne vois pas pourquoi. Une explication ?

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

        • [^] # Re: configuration par cn=config

          Posté par  (site web personnel) . Évalué à 1.

          Il y a un niveau d'indirection de moins : tu peux directement modifier la configuration, sans avoir besoin que la base fonctionne pour le faire proprement.

          Si ta base est pétée, changer la config via cn=config devient plus difficile, et somme toute, tu confies toujours les modifications à une commande, au lieu de les faire toi-même.

          Bien entendu, c'est plus psychologique que réel, mais je comprends assez bien ce qu'il veut dire.

          • [^] # Re: configuration par cn=config

            Posté par  . Évalué à 5.

            Je ne comprends pas, on peut aussi modifier les fichiers ldiff à la main si jamais ça ne démarre plus.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

            • [^] # Re: configuration par cn=config

              Posté par  (site web personnel) . Évalué à 2.

              La syntaxe est quand même un chouia plus compliqué et un chouia moins lisible :)

              • [^] # Re: configuration par cn=config

                Posté par  . Évalué à 5.

                Ça je suis bien d'accord, c'est le fait de dire que les fichiers sont plus sécurisés qui me semble bizarre.

                « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: configuration par cn=config

      Posté par  (site web personnel) . Évalué à 1.

      Oui, je l'ai précisé dans le journal, mais je pense qu'il faut commencer en douceur, quand on débute. Pour avoir dû apprendre sur le tas à modifier la configuration, j'ai conscience des problèmes psychologiques que ça peut poser à quelqu'un de non initié. :)

    • [^] # Re: configuration par cn=config

      Posté par  (site web personnel) . Évalué à 2.

      Un autre avantage, c'est que tu peux utiliser les acls et la réplication sur cn=config. Donc d'une part,les serveurs se mettent à jour en même temps ( ou plus ou moins ), et ensuite, tu peux filer une interface d'admin à d'autres équipes/presta et leur permettre de faire leur truc sans te déranger ( genre du tuning de leur arbre ).

      Perso, je préfère aussi puppet, mais bon.

      • [^] # Re: configuration par cn=config

        Posté par  (site web personnel) . Évalué à 2.

        Perso, je préfère aussi puppet, mais bon.

        Je dis cfengine car c'est pour moi le nom générique pour ce genre d'outil. Après l'un ou l'autre, chacun comme il veut.

        • [^] # Re: configuration par cn=config

          Posté par  (site web personnel) . Évalué à 2.

          C'était plus puppet/cfengine/etc que la config via la base de données elle même, pas puppet vs cfengine.

          Tout comme j'en chie pour avoir un module propre qui configure mysql, j'aurais du mal à faire un module openldap pour faire la même chose avec cn=config

          • [^] # Re: configuration par cn=config

            Posté par  . Évalué à 2.

            Je suis en train d'écrire un module puppet pour configurer openldap par cn=config. C'est long, mais pour le coup c'est assez intéressant pour découvrir les entrailles d'openldap. À suivre :-)

  • # OID

    Posté par  (site web personnel) . Évalué à 3.

    Les OID sont les mêmes que ceux utilisé dans SNMP. On peut les obtenir gratuitement auprès de l'IANA, le registre est là http://www.iana.org/assignments/enterprise-numbers et si vous commencez à utiliser du LDAP, je conseille vivement de commander le votre http://pen.iana.org/pen/PenApplication.page on veut très rapidement faire un schéma auxiliaire pour rajouter deux, trois infos à un objet. Et rien de plus frustrant que d'attendre une semaine quant on arrive au jour J de l'écriture de son premier schéma.

    "It was a bright cold day in April, and the clocks were striking thirteen" - Georges Orwell

    • [^] # Re: OID

      Posté par  . Évalué à 3. Dernière modification le 21 juin 2013 à 12:27.

      LDAP est sympa, et sa conception résiste au temps qui passe.
      Je trouve très frustrant ce système d'OID. C'est illisible et on ne peut résoudre les problèmes qu'en utilisant grep, ça gâche tout.

      PS: 404 sur ton premier lien.

      • [^] # Re: OID

        Posté par  (site web personnel) . Évalué à 3.

        J'ai jamais eu de problèmes avec les OID personnellement et je trouve mais très sympa comme système. Après c'est des goûts et des couleurs, mais je crois que dans LDAP, les OID avec leur structure hiérarchique ont vraiment un sens.

        PS: 404 sur ton premier lien.

        Chez moi ça marche … j'ai cliqué et je suis arrivé sur le site.

        "It was a bright cold day in April, and the clocks were striking thirteen" - Georges Orwell

        • [^] # Re: OID

          Posté par  . Évalué à 4.

          Chez moi ça marche … j'ai cliqué et je suis arrivé sur le site.

          Ça fait aussi un 404 chez moi.

          « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

        • [^] # Re: OID

          Posté par  . Évalué à 3.

          Ça a un côté antique. Je pense que ça mériterait une glue entre leur aspect numérique et un espace de nom.
          Rien n'est aussi compréhensible pour un humain que du texte :)

          • [^] # Re: OID

            Posté par  . Évalué à 10.

            Rien n'est aussi compréhensible pour un humain que du texte :)

            Toi, tu ne lis pas les postes de kadalka.

            « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

          • [^] # Re: OID

            Posté par  (site web personnel) . Évalué à 3.

            Ça a un côté antique. Je pense que ça mériterait une glue entre leur aspect numérique et un espace de nom.

            Les noms de domaine inversé c'est tellement mieux (OK : je sors)…

          • [^] # Re: OID

            Posté par  (site web personnel) . Évalué à 2.

            C'est le cas : iso.org.dod.internet.private.enterprise (1.3.6.1.4.1). Et quand tu écris un schéma :

            objectidentifier XXX 1.3.6.1.4.1.31204.100.4.1
            
            attributeType ( XXX:1.1 NAME 'YYY'
                    DESC 'Bip bop heu ... loula'
                EQUALITY caseIgnoreMatch
                SUBSTR caseIgnoreSubstringsMatch
                SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) 
            
            

            "It was a bright cold day in April, and the clocks were striking thirteen" - Georges Orwell

            • [^] # Re: OID

              Posté par  . Évalué à 3.

              Est-ce qu'il y a un système de gestion de dépendances permettant de savoir quels schémas parmi ceux connus permettront de fournir tel OID ou telle classe ?

              • [^] # Re: OID

                Posté par  (site web personnel) . Évalué à 4.

                Il y a pléthore de schémas qui sont des standards IETF. Après je n'ai pas connaissance d'un outils qui fait de la gestion de dépendance, mais ton serveur LDAP, si tu lui demandes, va te retourner la liste de tout ce qu'il connaît, les mécanismes qu'il utilise, les versions de protocole, … Tout est disponible via le protocole LDAP auprès de ton serveur.

                Donc si vraiment il y avait un besoin, un outil aurait été écrit pour faire ça. Peut-être il existe. Mais dans tous les cas, c'est pas un problème. J'ai un bout de code qui fait un peu ça en PHP http://www.lamaisondebarbie.ch/cgi-bin/repo/tchetch/artifact/bfc333896dc354559df061970ff4f05e9daa1c6e (plus ou moins).

                "It was a bright cold day in April, and the clocks were striking thirteen" - Georges Orwell

              • [^] # Re: OID

                Posté par  (site web personnel) . Évalué à 1.

                Le mieux est de lire les schémas qui préexistent, ça prend certes un peu de temps, mais une fois que c'est fait, ça aide grandement à ne pas créer des données redondantes.

                J'espère avoir répondu à ta question. :)

  • # Droits

    Posté par  (site web personnel) . Évalué à 2.

    Très sympa ce journal, mais c'est loin d'être terminé. Parce qu'après avoir un schéma et l'avoir peuplé, il faut régler les droits d'accès. Je me suis arraché les cheveux quelques heures dessus avant de bien comprendre le mécanisme (et encore je devais juste modifier des droits existants).

    Il existe deux catégories de gens : ceux qui divisent les gens en deux catégories et les autres.

    • [^] # Re: Droits

      Posté par  (site web personnel) . Évalué à 3.

      Je me cite :

      Ici, on configure les acl. Ils ne sont pas dépendants du backend, comme c'est un des points les plus techniques de LDAP, j'en reparlerai dans un journal séparé, après avoir pu faire mon lot de tests.

      Il m'a fallu une bonne heure et demie pour maîtriser la plupart des ACL, et une heure rien que pour la partie sets. Je préfère faire un journal entier, avec des exemples à la pelle.

      J'en profite pour préciser que je ferai sans doute un journal sur la réplication et la modification à chaud des configurations, un sur la partie SSL, et un dernier sur la notion de binding, et les utilisations pratiques des bases LDAP.

      En espérant que j'aie rien oublié.

  • # Pinaillage

    Posté par  (site web personnel) . Évalué à 1.

    Pour le niveau de journalisation, mieux vaut utiliser des valeurs textuelles que numériques, c'est plus lisible. Et contrairement à ce que le commentaire laisse supposer, le choix n'est pas entre 0 (rien) et 255 (trop), il y a tout un éventail de possibilité. Loglevel stats, par exemple, est largement supportable par n'importe quel annuaire, et permet d'identifier les problèmes après qu'ils soient signalés.

    Pour les ACLs, mieux vaut éviter d'entrelacer les déclaration par objet (sur quoi porte une règle) et par sujet (sur qui elle porte), pour éviter les erreurs. Par exemple, il est plus lisible de commencer par:

     # l'admin peut tout écrire
     access to dn.subtree="dc=localdomain"
           by dn.exact="cn=admin,dc=localdomain" write
           by * break
    
     # readonly peut tout lire
     access to dn.subtree="dc=localdomain"
           by dn.exact="cn=admin,dc=localdomain" read
           by * break
    

    Plutôt que de gérer ces cas par des clauses supplémentaires dans la règle par défaut qui vient tout à la fin.

    Par ailleurs, l'utilisateur déclaré par les directives rootdn et rootpw dans les fichiers de configuration ignore totalement les ACLs, il n'y a aucune nécessité d'en prévoir pour lui. Ou alors, de ne pas utiliser ces directives (rootdn n'est nécessaire que sur un esclave) pour plus de contrôle.

    Enfin, je suis très sceptique sur la nécessité pour une application d'avoir accès en lecture à l'attribut userPassword. Les seuls cas que je connaisse concernent radius ou kerberos, dans des configuration particulières, dans lesquelles l'annuaire est utilisé comme solution de stockage de mots de passe, avec des syntaxes spécifiques, et jamais en réutilisant l'attribut mot de passe de l'annuaire lui-même. Toutes les autres applications se contentent d'une opération bind sur l'annuaire, avec l'identificant de l'utilisateur, pour laquelle seul la permission by anonymous auth est nécessaire.

    • [^] # Re: Pinaillage

      Posté par  (site web personnel) . Évalué à 1.

      Pour le niveau de journalisation, mieux vaut utiliser des valeurs textuelles que numériques, c'est plus lisible. Et contrairement à ce que le commentaire laisse supposer, le choix n'est pas entre 0 (rien) et 255 (trop), il y a tout un éventail de possibilité. Loglevel stats, par exemple, est largement supportable par n'importe quel annuaire, et permet d'identifier les problèmes après qu'ils soient signalés.

      Je ne vois pas ce qui te permet d'affirmer que je situe le logging de 0 à 255, c'est faux, et je précise que les informations sont dans la manpage de slapd.conf.

      Pour les ACLs, mieux vaut éviter d'entrelacer les déclaration par objet (sur quoi porte une règle) et par sujet (sur qui elle porte), pour éviter les erreurs. Par exemple, il est plus lisible de commencer par:

      # l'admin peut tout écrire
      access to dn.subtree="dc=localdomain"
      by dn.exact="cn=admin,dc=localdomain" write
      by * break

      # readonly peut tout lire
      access to dn.subtree="dc=localdomain"
      by dn.exact="cn=admin,dc=localdomain" read
      by * break

      Plutôt que de gérer ces cas par des clauses supplémentaires dans la règle par défaut qui vient tout à la fin.

      Bof, à l'usage, quelle que soit la forme des ACL, elle ne m'a jamais posé de problème, et sont difficilement sujetes à erreurs.

      Cela étant, c'est toujours un bon conseil pour qui commence…

      Par ailleurs, l'utilisateur déclaré par les directives rootdn et rootpw dans les fichiers de configuration ignore totalement les ACLs, il n'y a aucune nécessité d'en prévoir pour lui. Ou alors, de ne pas utiliser ces directives (rootdn n'est nécessaire que sur un esclave) pour plus de contrôle.

      Là dessus, je ne répondrai pas directement, c'est une question d'idéologie, je préfère, dans la mesure du faisable, que les ACL rappellent explicitement les droits du superutilisateur plutôt que de laisser cette information tacitement admise. C'est plus intelligible.

      Enfin, je suis très sceptique sur la nécessité pour une application d'avoir accès en lecture à l'attribut userPassword. Les seuls cas que je connaisse concernent radius ou kerberos, dans des configuration particulières, dans lesquelles l'annuaire est utilisé comme solution de stockage de mots de passe, avec des syntaxes spécifiques, et jamais en réutilisant l'attribut mot de passe de l'annuaire lui-même. Toutes les autres applications se contentent d'une opération bind sur l'annuaire, avec l'identificant de l'utilisateur, pour laquelle seul la permission by anonymous auth est nécessaire.

      Cette permission n'existe que depuis récemment, mon exemple décrit un ACL qui remonte à 2006 je crois. Par ailleurs, je crois que dovecot ne sa(va)it pas se binder directement en tant que l'utilisateur pour vérifier son mot de passe, je n'exclus pas de ne pas être à jour sur la question, mais du coup, l'acl dovecot semble utile…

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.