Suite à l'installation d'une instance OpenDS 2.3 sur une pré-production, sur RHEL 7 et java 1.6, un utilisateur se plaignait de ne plus pouvoir faire fonctionner son application.
Lorsqu'il lançait sa recherche, il n'avait aucun résultat, mais un message d'erreur :
SEARCH operation failed Result Code: 50 (Insufficient Access Rights) Additional Information: You do not have sufficient privileges to perform an unindexed search
La résolution du problème a pris quelques heures, le temps d'écumer le guide d'administration (plutôt complet) et les différents sites internet (dont celui de Ludovic Poitou, toujours très utile).
La requête de base est la suivante :
- Scope : wholeSubTree
- Base ou=site,ou=p1,ou=repository,o=rootSuffix
- Filter : (id=*).
Sachant qu'il y a 9400 objets dans l'ou=site, et que l'attribut id est le RDN de l'objet, tous les objets ont donc un id.
Debug de l'utilisation des requêtes
Le blog de Ludovic Poitou comprenait un article qui parlait des indexes dans OpenDJ (très compatible avec OpenDS), et notamment un attribut opérationnel debugsearchindex qui permet d'avoir les comportement de l'annuaire par rapport aux index.
Exemple :
ldapsearch -p 25389 -D 'cn=directory manager' -w password -s one -b ou=site,ou=p1,ou=repository,o=rootSuffix '(id=*)' debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(id=*)[NOT-INDEXED] scope=singleLevel[LIMIT-EXCEEDED:94 17] final=[NOT-INDEXED]
L'attribut n'est pas indexé. On va donc ajouter un index, de type substring.
Création d'un index
dsconfig create-local-db-index --port 4444 --hostname localhost --bindDN "cn=Directory Manager" \ --bindPassword password --backend-name userRoot \ --index-name id --set index-type:substring \ --trustAll --no-prompt
Puis on lance le rebuild-index
rebuild-index --port 4444 -h localhost -D "cn=directory manager" -w password --baseDN o=rootSuffix --index id --start 0 --trustAll
A ce stade, si on lance la même requête, on a toujours le même souci.
Par contre, avec un sous-ensemble, ça fonctionne :
ldapsearch -p 25389 -D 'cn=directory manager' -w password -s one -b ou=site,ou=p1,ou=repository,o=rootSuffix '(id=ne*)' debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(id=ne*)[INDEX:id.substring][COUNT:76] scope=singleLeve l[LIMIT-EXCEEDED:9417] final=[COUNT:76]
Note : la recherche en (id=*) nécessite un index de type présence. Il faut donc créer un index de type substring ET presence.
Après avoir faire la création et le rebuilt, on peut vérifier les index :
bin/dbtest list-index-status -b "o=rootSuffix" -n userRoot Index Name Index Type JE Database Name Index Status ---------------------------------------------------------------------------------------- id2children Index o_rootSuffix_id2children true id2subtree Index o_rootSuffix_id2subtree true uid.equality Index o_rootSuffix_uid.equality true id.presence Index o_rootSuffix_id.presence true id.substring Index o_rootSuffix_id.substring true
Cependant, la recherche sur id=* ne fonctionne toujours pas avec un compte "normal"
bin/ldapsearch -p 25389 -D 'cn=directory manager' -w password -s one -b ou=site,ou=p1,ou=repository,o=rootSuffix '(id=*)' debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(id=*)[INDEX:id.presence][LIMIT-EXCEEDED] scope=singleL evel[LIMIT-EXCEEDED:9417] final=[LIMIT-EXCEEDED:9417]
Changement de la limitation sur les index
Il faut alors jouer avec la propriété index-entry-limit, qui spécifie le nombre maximum des entrées garder dans un index. Dans notre cas, sachant qu'on a actuellement 9400 entrées de type site, et d'autres objets qui ont également un attribut id, on va fixer la valeur à 12 000.
bin/dsconfig set-local-db-index-prop --port 4444 --hostname localhost --bindDN "cn=Directory Manager" \ --bindPassword password --backend-name userRoot \ --trustAll --no-prompt \ --index-name id \ --set index-entry-limit:12000
Après avoir lancé le rebuild,
bin/ldapsearch -p 25389 -D 'cn=directory manager' -w password -s one -b ou=site,ou=p1,ou=repository,o=rootSuffix '(id=*)' debugsearchindex dn: cn=debugsearch debugsearchindex: filter=(id=*)[INDEX:id.presence][COUNT:10084] scope=singleLeve l[LIMIT-EXCEEDED:9417] final=[COUNT:10084]
A ce niveau, la recherche fonctionne, mais on se heurte à une autre limite :
SEARCH operation failed Result Code: 4 (Size Limit Exceeded) Additional Information: This search operation has sent the maximum of 1000 entries to the client
Modification des limites du compte
Par défaut, on a des limites sur le nombre de résultats retournés :
- ds-rlim-lookthrough-limit : 5000
- ds-rlim-size-limit : 1000
Il faut donc modifier ces valeurs. Par exemple via un fichier LDIF :
dn: cn=VliPre, ou=account, ou=security, o=rooutSuffix changetype:modify add: ds-rlim-size-limit ds-rlim-size-limit: 15000 - add: ds-rlim-lookthrough-limit ds-rlim-lookthrough-limit: 15000
Après toutes ces modifications, le compte peut bien récupérer toutes les entrées.
Par contre, on peut se poser la question sur l'intérêt de récupérer des milliers d'entrées.
Désactivation globale du privilège
En derner recours, il est possible de désactiver globalement le privilège unindexed-search, en passant par ds-config.
On peut voir configuration en cours :
/opt/OpenDS-2.3.0/bin/dsconfig get-global-configuration-prop \ --port 4444 --hostname localhost --trustAll --bindDN "cn=Directory Manager" --bindPassword password --no-prompt Property : Value(s) --------------------------------------:------------------------ bind-with-dn-requires-password : true default-password-policy : Default Password Policy disabled-privilege : - entry-cache-preload : false etime-resolution : milliseconds idle-time-limit : 0 ms lookthrough-limit : 5000 max-allowed-client-connections : 0 proxied-authorization-identity-mapper : Exact Match reject-unauthenticated-requests : false return-bind-error-messages : false save-config-on-successful-startup : true size-limit : 1000 smtp-server : - time-limit : 1 m workflow-configuration-mode : auto writability-mode : enabled
Il est possible de modifier la valeur avec ds-config :
/opt/OpenDS-2.3.0/bin/dsconfig set-global-configuration-prop \ --port 4444 --hostname localhost --trustAll --bindDN "cn=Directory Manager" --bindPassword password --no-prompt \ --set disabled-privilege:unindexed-search
Ceci supprimer les avertissements et erreurs, au détriment des performances, puisque le paramétrage autorise n'importe qui à faire des recherches non indexées.
On peut voir la nouvelle configuration :
/opt/OpenDS-2.3.0/bin/dsconfig get-global-configuration-prop \ --port 4444 --hostname localhost --trustAll --bindDN "cn=Directory Manager" --bindPassword password --no-prompt Property : Value(s) --------------------------------------:------------------------ bind-with-dn-requires-password : true default-password-policy : Default Password Policy disabled-privilege : unindexed-search entry-cache-preload : false etime-resolution : milliseconds idle-time-limit : 0 ms