json https://www.vincentliefooghe.net/index.php/ fr Utilisation d'attributs Json dans Forgerock DS https://www.vincentliefooghe.net/index.php/content/utilisation-dattributs-json-dans-forgerock-ds <span class="field field--name-title field--type-string field--label-hidden">Utilisation d&#039;attributs Json dans Forgerock DS</span> <div class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item"><h2>Problématique</h2> <p>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.</p> <p>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.</p> <p>Soit :</p> <ul><li>délégation pour une société S1, avec les rôles RS1, RS2, RS3</li> <li>délégation pour une société S2, avec les rôles RS1, RS3</li> <li>délégation pour un utilisateur U1, avec les rôles RU1, RU2</li> </ul><p>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 :</p> <pre> <code>type|identifiant du type|role1-role2-role3 </code></pre><p>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.</p> <p>Dans notre exemple, ça donnerait :</p> <ul><li>societe|S1|RS1-RS2-RS3</li> <li>societe|S2|RS1-RS3</li> <li>utilisateur|U1|RU1-RU2</li> </ul><p>Par contre pour les recherches, ça devient plus compliqué, sauf à pré-calculer un filtre, en jouant avec les séparateurs.</p> <h2>Attribut Json</h2> <p>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.</p> <h3>Déclaration dans le schéma</h3> <p>L'ajout d'un attribut de type JSON se fait de manière <em>traditionnelle</em>, en utilisant une syntaxe spécifique (<em>1.3.6.1.4.1.36733.2.1.3.1</em>).</p> <p>On ajoute ensuite les attributs dans le schéma :</p> <pre> <code>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' ) </code></pre><p>On doit également préciser le type de règle d'égalité qui sera utilisée. Il en existe 4 pré-définies :</p> <ul><li>caseIgnoreJsonQueryMatch : 2 objets sont identiques si tous leurs champs sont les mêmes, à la casse près</li> <li>caseExactJsonQueryMatch : 2 objets sont identiques si tous leurs champs sont les mêmes, avec la même casse de caractères</li> <li>caseIgnoreJsonIdMatch : 2 objets sont identiques si leur champ "_id" est identique, quelle que soit la casse de caractères</li> <li>caseExactJsonIdMatch : 2 objets sont identiques si leur champ "_id" est identique, avec la même casse de caractères.</li> </ul><p>Quelques exemples pour illustrer les cas. En supposant que j'ai 2 entrées dans l'annuaire LDAP, avec :</p> <ol><li>{"_id":"json","type":"user","value":"user123"}</li> <li>{"_id":"Json","type":"User","value":"USER123"}</li> <li>{"_id":"json","type":"user","value":"user345"}</li> <li>{"_id":"Json","type":"User","value":"USER345"}</li> </ol><p>Selon les cas :</p> <ul><li>avec la règle <strong>caseIgnoreJsonQueryMatch</strong>, les objets 1 et 2, et les objets 3 et 4 sont identiques</li> <li>avec la règle <strong>caseExactJsonQueryMatch</strong>, il n'y a pas de correspondance</li> <li>avec la règle <strong>caseIgnoreJsonIdMatch</strong>, les 4 objets sont identiques (ils ont le même _id)</li> <li>avec la règle <strong>caseExactJsonIdMatch</strong>, les objets 1 et 3 sont considérés identiques, ainsi que 2 et 4</li> </ul><h3>Indexation</h3> <p>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 <em>json-equality-matching-rule</em>).</p> <p>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.</p> <h3>Recherche</h3> <p>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).</p> <p>Quelques exemples de filtres, sur la base de nos attributs <em>delegations</em> et <em>jsonId</em> déclarés précédemment :</p> <pre> <code>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"} </code></pre><ul><li>(delegations=*) : va renvoyer toutes les entrées qui ont un attribut <em>delegations</em></li> <li>(jsonid=_id eq 'json') va renvoyer les entrées qui ont la valeur 'json' dans le champ "_id" de l'attribut</li> <li>(delegations=type eq 'utilisateur' or type eq 'societe') : va renvoyer les objets ayant l'une ou l'autre valeur dans le champ type</li> </ul><p><strong>Limitations sur les filtres de recherche</strong></p> <p>Il n'est pas possible de faire une recherche dans un tableau qui contient plusieurs objets (attributions dans notre exemple).</p> <pre> <code>(delegations=id eq "user2") </code></pre><p>ne ramène rien (on n'y accède pas directement, il faudrait passer par attributions-&gt;id).</p> <p>Par contre, si on a une structure dont l'un des attributs est un tableau, qui ne contient que des valeurs, cela fonctionne.</p> <p>Si on a des attributs comme ceci :</p> <pre> <code>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"]} </code></pre><p>On peut bien faire des recherches de type :</p> <pre> <code>ldapsearch -b ou=people,dc=example,dc=com '(delegations=id eq "user2")' </code></pre><p>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 <em>json</em>, il faut utiliser le filtre adéquat. Par exemple :</p> <pre> <code>(delegations=id eq "2" and type eq "societe") </code></pre><p>La recherche dans un tableau fonctionne également. On peut ainsi rechercher tout les objets LDAP qui ont un role "role-usr4" :</p> <pre> <code>(delegations=roles eq "role-usr4") </code></pre><p>Idem pour les objets avec un type "societe" et un rôle "role-soc1" :</p> <pre> <code>(delegations=type eq "societe" and roles eq "role-soc1") </code></pre></div> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/index.php/users/vincentl" typeof="schema:Person" property="schema:name" datatype="">vincentl</span></span> <span class="field field--name-created field--type-created field--label-hidden">ven 04/03/2022 - 14:55</span> <div class="field field--name-field-categorie field--type-entity-reference field--label-above"> <div class="field__label">Catégorie</div> <div class="field__item"><a href="/index.php/cat%C3%A9gorie/iam" hreflang="fr">IAM</a></div> </div> <div class="field field--name-field-tags field--type-entity-reference field--label-above"> <div class="field__label">Tag</div> <div class="field__items"> <div class="field__item"><a href="/index.php/tags/forgerock" hreflang="fr">forgerock</a></div> <div class="field__item"><a href="/index.php/tags/opendj" hreflang="fr">opendj</a></div> <div class="field__item"><a href="/index.php/tags/ds" hreflang="fr">ds</a></div> <div class="field__item"><a href="/index.php/tags/json" hreflang="fr">json</a></div> </div> </div> <section class="field field--name-comment-node-book field--type-comment field--label-hidden comment-wrapper"> <h2 class="title comment-form__title">Ajouter un commentaire</h2> <drupal-render-placeholder callback="comment.lazy_builders:renderForm" arguments="0=node&amp;1=214&amp;2=comment_node_book&amp;3=comment_node_book" token="sYSuQMghlx0xCAUDqXvngNEvgVyPnyCe-RJ6u6n_6dw"></drupal-render-placeholder> </section> Fri, 04 Mar 2022 13:55:34 +0000 vincentl 214 at https://www.vincentliefooghe.net