Principes généraux
Les ACL dans OpenLDAP peuvent se trouver à 2 niveaux, database ou backEnd, sachant qu'il est assez courant d'avoir un backend par database (ou vice-versa).
Les ACL sont donc généralement positionnées dans la configuration de la database.
Syntaxe
La syntaxe globale est :
olcAccess: to [ressource] by [à qui] [type d'accès autorisé] by [à qui] [type d'accès autorisé] by [à qui] [type d'accès autorisé]
Un exemple de base, qui limite l'accès à l'attribut userPassword :
olcAccess: to attrs=userPassword by self write by group.exact="cn=ADMIN,ou=groups,dc=example,dc=com" write by anonymous auth by * none
Dans l'exemple, on autorise l'utilisateur à écrire (modifier) son propre mot de passe, ainsi qu'au groupe ADMIN.
Pour les utilisateurs anonymes, seule l'authentification est possible.
Pour les autres, l'accès est refusé.
On peut également gérer les accès sur un objet de l'arborescence :
olcAccess: to dn.subtree="ou=applications,dc=example,dc=com" by group.exact="cn=APPADMIN,ou=groups,dc=example,dc=com" write by users read by * none
Ici, on donne accès en écriture au groupe APPADMIN sur toute l'arborescence de la branche "ou=applications" (via le dn.subtree).
Les utilisateurs authentifiés peuvent lire l'arborescence. Les accès non authentifiés ne sont pas autorisés. Il faut noter que par défaut, la règle "by * none" est ajoutée, interdisant les accès anonymes.
Par défaut, s'il n'y a pas de correspondance (directive d'accès ou [who]), l'accès est refusé.
Ressource protégées
Une ACL peut protéger / cibler une ressource, en se basant sur le DN, un filtre LDAP, un attribut ou une combinaison. Les types de ressources protégées sont :
- * : toutes les entrées
- dn:[scope] : un objet ou un périmètre (exact, subtree, children)
- filter: filtre LDAP
- attrs: attribut(s)
Pour les DN, on peut cibler un élément particulier (dn.exact, dn.base, dn.one, dn.children, dn.subtree) :
- dn.exact ou dn.base : accès restreint au DN de l'objet ciblé lui-même
- dn.one : accès restreint aux entrées présentes exactement sous le DN (mais pas l'objet lui-même, ni les niveaux inférieurs)
- dn.subtree : accès à toute l'arborescence sous le DN, y compris le DN
- dn.children : accès à toute l'arborescence sous le DN, excepté le DN
Pour les attributs, on peut avoir un seul ou plusieurs attributs, dans ce cas ils sont séparés par des virgules. Par exemple :
access to attrs=homePhone,fax,mobile,telephoneNumber,mail by users read by * none
Si on veut permettre la recherche et la lecture de certains attributs, il faut ajouter entry dans la liste des attributs. Par exemple :
olcAccess: to dn.subtree="ou=people,dc=example,dc=com" attrs=entry,cn,uid,userstatus,employeenumber,ou by dn.exact="cn=AppRead,ou=access,dc=example,dc=com" read by * none
Dans le cas des attributs, il est également possible de restreindre l'accès à une valeur.
A noter une particularité intéressante pour OpenLDAP : la possibilité d'adresse tous les attributs d'une classe d'objet, en utilisant la syntaxe attrs=@ObjectClass. Par exemple, la règle suivante donnera accès en lecture à tous les attributs de la classe d'objet inetOrgPerson :
olcAccess: to dn.subtree="ou=people,dc=example,dc=com" attrs=@inetorgperson by dn.exact="cn=AppRead,ou=access,dc=example,dc=com" read by * none
Une règle rarement mise en oeuvre utilise un filtre LDAP. On peut par exemple restreindre des accès en fonction d'un filtre sur un attribut. Prenons l'exemple d'entrées avec un attribut portant le code Pays :
access to filter="(co=fr)" by group.exact="cn=ADMIN-FR,ou=groups,dc=example,dc=com" write by users read by * none
A qui donner accès
On trouve plusieurs sélecteurs :
- * : tout le monde
- anonymous : les utilisateurs non connectés
- users : les utilisateurs conenctés (via un BIND)
- self : porte sur l'utilisateur lui-même
- dn.[specifier] : un DN (peut être un DN exact, subtree ou children)
- group.[specifier] : un groupe LDAP
Type d'accès à donner
Les ACL permettent de gérer plusieurs niveaux de droits, du plus faible au plus élevé :
- (0) none : pas d'accès
- (d) disclose : permet de savoir si l'entrée ou l'attribut existe
- (x) auth : requis pour l'authentification
- (c) compare : comparaison de valeur d'attribut
- (s) search : recherche sur un attribut
- (r) read : lecture / affichage d'un attribut
- (w) write : modification / écriture d'un attribut
Chaque niveau de droit implique tous les droits inférieurs.
Par exemple, le droit "read" donne également les droits search, compare, auth et disclose.
Il est possible d'utiliser le verbe (plus parlant) ou une combinaison des codes de droits. Par exemple :
access to dn.subtree=ou=people,dc=example,dc=com by group.exact="cn=ADMIN-FR,ou=groups,dc=example,dc=com" write by users=cd by * none
Dans l'exemple, les utilisateurs authentifiés auront les droits compare et disclose.
Ordre d'évaluation
Le placement des ACI dans la configuration est importante, car l'évaluation des directives de droits d'accès se fait dans l'ordre d'apparition.
Si une directive est plus spécifique d'une autre, en terme d'entrées sélectionnées, elle doit apparaître en premier dans la configuration.
De la même manière, si un sélecteur "who" est plus spécifique il doit également être positionné en premier. Par exemple, si on met :
by users read by group.exact="cn=ADMIN,ou=groups,dc=example,dc=com" write
la première règle sera toujours appliquée pour les utilisateurs, même s'ils font partie du groupe ADMIN. Du coup, seuls les accès en lecture seront autorisés.
Break et Continue
Comme vu précédemment, le mode de fonctionnement des ACL est particulier : par défaut, dès qu'une ACL correspond à l'objet et au compte, la validation s'arrête. Dans certains cas simples, ceci est satisfaisant, mais parfois il faut pouvoir traiter plusieurs cas à l'intérieur d'une même ACL, ou traiter différentes ACL.
C'est notamment le cas si on doit restreindre les droits sur des attributs, dans une même branche.
Dans ce cas, on peut utiliser des directives telles que break et continue :
- break : permet d'outrepasser la règle en cours d'analyse, et de continuer l'analyse des autres règles
- continue : permet de continuer au sein d'une même ACL
- stop : arrête l'analyse des règles (c'est le comportement par défaut)
Voyons quelques exemples plus parlants.
olcAccess: to attr=employeeNumber,employeeType,departmentNumber by users=cd by dn="uid=matt,ou=Users,dc=example,dc=com" +read olcAccess: to attr=employeeNumber by users +write
Si je me connecte en tant que uid=matt,ou=users,dc=example,dc=com et que j'essaie de modifier mon attribut employeeNumber, je ne serai pas autorisé. En effet, la première règle autorise uniquement le compare + disclose à tous les utilisateurs. La règle va être évaluée et va correspondre, l'analyse s'arrête alors.
Si on ajouter les directives break / continue :
olcAccess: to attr=employeeNumber, employeeType, departmentNumber by users=cd continue by dn="uid=matt,ou=Users,dc=example,dc=com" +read break olcAccess: to attr=employeeNumber by users +write stop
La première règle est évaluée, et elle correspond. Mais avec la directive continue, l'annuaire examine la seconde clause de l'ACI. En tant que uid=matt, j'ai donc la possibilité de lire les attributs. La directive break va aussi stipuler que les autres ACI doivent être évaluées. La deuxième ACI donne droit à l'écriture. La permission finale est donc cdrw = compare/disclose/read/write.
Vérification des ACL
Afin de vérifier le bon fonctionnement des ACL, on peut utiliser les outils LDAP tels que ldapsearch ou ldapmodify. Dans ce cas, je préconise de modifier le niveau de logs en acl trace
dn: cn=config changetype:modify add: olcLogLevel # ou replace si on a déjà positionné un olcLogLevel olcLogLevel: acl trace
Conversion des ACI Sun DSEE vers OpenLDAP
Il y a plusieurs différences par rapport aux ACI dans l'annuaire Sun.
Au niveau du placement, les ACI sont positionnées dans l'annuaire Sun DSEE au niveau où elles s'appliquent. Dans un export LDIF on peut donc avoir des ACI dans tout le fichier. Si dans l'ACI, il n'y a pas de (target) définie explicitement, alors l'ACI s'applique sur l'objet et son arborescence.
Sun DSEE gère également des types d'accès supplémentaires : import, export, all. Il n'y a pas par contre de droit "auth".
Dans les ACI Sun DSEE, il est possible de mettre des commentaires pour nommer l'ACI. Ceci n'est pas possible avec les ACL OpenLDAP.
Les ACI étant placées dans l'arborescence, il est recommandé de les protéger avec une ACI. Ceci n'est pas nécessaire avec OpenLDAP, puisque les ACI sont au niveau de la configuration, séparée des données.
Par défaut, l'annuaire de Sun autorise la lecture (read / compare / search) en anonyme sur toute l'arborescence.
Merci
C'est le genre d'article vraiment utile, car mis à part la doc officielle en anglais on a pas grand chose.
Merci et bonne année !