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 :
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.
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.
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]
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
Par défaut, on a des limites sur le nombre de résultats retournés :
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.
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