Il arrive des cas où l'utilisation des attributs "simples", qu'ils soient mono ou multi-valués, n'est pas satisfaisante par rapport aux besoins des utilisateurs.
Prenons le cas suivant : on veut gérer des délégations pour X types de profils et chacun avec des rôles spécifiques.
Soit :
Si on utilise un attribut de type chaîne de caractères, on peut s'en sortir avec des concaténations et des caractères de séparation. Par exemple :
type|identifiant du type|role1-role2-role3
Dans ce cas on doit déjà gérer 2 types de séparateurs :le "|" pour les différents éléments, et le "-" pour les rôles.
Dans notre exemple, ça donnerait :
Par contre pour les recherches, ça devient plus compliqué, sauf à pré-calculer un filtre, en jouant avec les séparateurs.
Depuis la version 5.5 (au moins), Forgerock permet d'utiliser une syntaxe Json dans les attributs, ce qui permet de gérer des données structurées à l'intérieur d'un attribut.
L'ajout d'un attribut de type JSON se fait de manière traditionnelle, en utilisant une syntaxe spécifique (1.3.6.1.4.1.36733.2.1.3.1).
On ajoute ensuite les attributs dans le schéma :
attributeTypes: ( 1.3.6.1.4.1.18472.2.101 NAME 'delegations' SYNTAX 1.3.6.1.4.1.36733.2.1.3.1 EQUALITY caseIgnoreJsonQueryMatch X-ORIGIN 'Mes tests json' )
attributeTypes: ( 1.3.6.1.4.1.18472.2.102 NAME 'jsonId' SYNTAX 1.3.6.1.4.1.36733.2.1.3.1 EQUALITY caseIgnoreJsonIdMatch SINGLE-VALUE X-ORIGIN 'Mes tests json' )
On doit également préciser le type de règle d'égalité qui sera utilisée. Il en existe 4 pré-définies :
Quelques exemples pour illustrer les cas. En supposant que j'ai 2 entrées dans l'annuaire LDAP, avec :
Selon les cas :
Lorsqu'on indexe un attribut JSON, le comportement par défaut de Forgerock DS est de maintenir des clés pour chaque champ JSON. De ce fait, si l'attribut JSON contient de nombreux champs différents (et qui ne font pas l'objet de recherches) on peut choisir de n'indexer que ces champs. Dans ce cas, il faudra définir soi-même une règle (de type json-equality-matching-rule).
Si on utilise une règle de comparaison basée sur l'ID uniquement, c'est ce champ qui sera indexé, et pas les autres.
La syntaxe du filtre de recherche est la même que celle utilisée pour les API REST Forgerock (communément appelées CREST = Common REST).
Quelques exemples de filtres, sur la base de nos attributs delegations et jsonId déclarés précédemment :
delegations: {"type":"societe","attributions":[{"id":"societe1","roles":["role-soc1","role-soc2","role-soc3"]},{"id":"societe2","roles":["role-soc4"]}]}
delegations: {"type":"utilisateur","attributions":[{"id":"user1","roles":["role-usr1","role-usr2"]},{"id":"user2","roles":["role-usr4"]}]}
delegations: {"type":"org","attributions":[{"id":"org1","roles":["role-org1","role-org2","role-org4"]}] }
jsonId: {"_id":"json","type":"user","value":"user123"}
jsonId: {"_id":"Json","type":"User","value":"USER123"}
jsonId: {"_id":"json","type":"user","value":"user345"}
jsonId: {"_id":"Json","type":"User","value":"USER345"}
Limitations sur les filtres de recherche
Il n'est pas possible de faire une recherche dans un tableau qui contient plusieurs objets (attributions dans notre exemple).
(delegations=id eq "user2")
ne ramène rien (on n'y accède pas directement, il faudrait passer par attributions->id).
Par contre, si on a une structure dont l'un des attributs est un tableau, qui ne contient que des valeurs, cela fonctionne.
Si on a des attributs comme ceci :
delegations: {"type":"utilisateur","id":"user1","roles":["role-usr1","role-usr2"]}
delegations: {"type":"utilisateur","id":"user2","roles":["role-usr4","role-usr2"]}
delegations: {"type":"societe","id":"societe1","roles":["role-soc1","role-soc2","role-soc3"]}
delegations: {"type":"societe","id":"societe2","roles":["role-soc4"]}
delegations: {"type":"org","id":"org2","roles":["role-org1","role-org2","role-org4"]}
On peut bien faire des recherches de type :
ldapsearch -b ou=people,dc=example,dc=com '(delegations=id eq "user2")'
Si on veut éviter des collisions entre les différents types, on peut combiner plusieurs recherches. Si elles portent sur plusieurs éléments de l'attribut json, il faut utiliser le filtre adéquat. Par exemple :
(delegations=id eq "2" and type eq "societe")
La recherche dans un tableau fonctionne également. On peut ainsi rechercher tout les objets LDAP qui ont un role "role-usr4" :
(delegations=roles eq "role-usr4")
Idem pour les objets avec un type "societe" et un rôle "role-soc1" :
(delegations=type eq "societe" and roles eq "role-soc1")