Les ACL dans OpenLDAP

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.

Catégorie
Permalien

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 !