ITIM : Object might have been deleted

Contexte

Sur notre instance ITIM, nous avons mis en place la "corbeille", ce qui permet de pouvoir récupérer des objets supprimés pendant plusieurs jours.

Cependant suite à la "restauration" d'un utilisateur à partir de la corbeille, il était impossible de modifier ou supprimer l'objet.

La procédure de récupération dans la corbeille était la suivante :

  • recherche dans la corbeille, à partir du matricule
  • récupération au format LDIF
  • modification du fichier LDIF
  • import / ajout dans la branche ou=People

A un moment de l'import (via Apache Directory Studio), une erreur est apparue, mais l'utilisateur a bien été créé dans ITIM. On pouvait faire une recherche, et l'utilisateur s'affichait dans l'écran, par contre si on sélectionnait l'objet, ITIM affichait une erreur : "CTGIMF007E The specified object cannot be found in the directory server. The object might have been moved or deleted before your request completed".

La recherche dans l'annuaire à partir du matricule donnait bien les bonnes données attendues :

/opt/ibm/ldap/V6.2/bin/ldapsearch -L -D cn=root -w myP@SSword -b ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,o=MYCORP-iir "(employeenumber=EXT4040323)" erglobalid ercreatedate

dn: erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR
erglobalid: 2711683785790239385
ercreatedate: 202405231326Z

Par contre, la tentative de modification ou de suppression en direct dans l'annuaire tombait en erreur, même avec l'option -k, qui permet de forcer les "Server Administration Control" :

/opt/ibm/ldap/V6.2/bin/ldapdelete -D cn=root -w myP@SSword -k erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR
Operation 0 deleting entry erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR
ldap_delete: No such object

Dans le fichier d'audit (audit.log) on constate bien le problème :

AuditV3--2025-02-11-13:49:57.642+00:00--V3 Delete--bindDN: cn=root--client: 127.0.0.1:50412--connectionID: 151452--received: 2025-02-11-13:49:57.641+00:00--No such object
controlType: 1.3.18.0.2.10.15
criticality: true
controlType: 1.3.6.1.4.1.42.2.27.8.5.1
criticality: false
entry: erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR

Afin de tenter de comprendre le souci, on tente de faire la suppression en mode "Full Debug" (option -d 65535) :

/opt/ibm/ldap/V6.2/bin/ldapdelete -D cn=root -w myP@SSword -d 65535 erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR > /tmp/debug_delete.log 2>&1
Operation 0 deleting entry erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR
ldap_delete: No such object

Par rapport à une suppression correcte, on voit effectivement apparaître une différence sur une opération

Sur notre objet en erreur :

041:13:14:48 T-344201472 fber_get_next_nb: length=0
041:13:14:48 T-344201472 fber_get_next_nb: tag 0x30 len=85 contents:
041:13:14:48 T-344201472 fber_dump_with_fd: buf=0x16befa0 ptr=0x16befa0 end=0x16beff5 sd=3
041:13:14:48 T-344201472           current len=85, contents:
T-344201472:    +---------------------------------------------------------+
T-344201472:    |OSet| Address = 016C1520  Length = 0055 |     ASCII      |
T-344201472:    +---------------------------------------------------------+
T-344201472:    |0000|0201026B 84000000 4C0A0120 04454F55|...k....L.. .EOU|
T-344201472:    |0010|3D302C4F 553D5045 4F504C45 2C455247|=0,OU=PEOPLE,ERG|
T-344201472:    |0020|4C4F4241 4C49443D 30303030 30303030|LOBALID=00000000|
T-344201472:    |0030|30303030 30303030 30303030 2C4F553D|000000000000,OU=|
T-344201472:    |0040|41554348 414E2C4F 3D415543 48414E2D|MYCORP,O=MYCORP-|
T-344201472:    |0050|49495204 00                        |IIR..           |
T-344201472:    +---------------------------------------------------------+
041:13:14:48 T-344201472 put_msg_in_queue: storing msgid=2 in queue
041:13:14:48 T-344201472 put_msg_in_table: storing msgtype=0x6b, msgid=2 in table
041:13:14:48 T-344201472 is_last_msg: returning TRUE, msgid=2
041:13:14:48 T-344201472 ldap_msg_table_get_message: returning rc=107
041:13:14:48 T-344201472 fber_scanf fmt ({iaa) offset=3 length=85

Sur une entrée sans erreur :

041:13:22:36 T394422016 fber_get_next_nb: length=0
041:13:22:36 T394422016 fber_get_next_nb: tag 0x30 len=16 contents:
041:13:22:36 T394422016 fber_dump_with_fd: buf=0xa89fa0 ptr=0xa89fa0 end=0xa89fb0 sd=3
041:13:22:36 T394422016           current len=16, contents:
T394422016:     +---------------------------------------------------------+
T394422016:     |OSet| Address = 00A89FC0  Length = 0010 |     ASCII      |
T394422016:     +---------------------------------------------------------+
T394422016:     |0000|0201026B 84000000 070A0100 04000400|...k............|
T394422016:     +---------------------------------------------------------+
041:13:22:36 T394422016 put_msg_in_queue: storing msgid=2 in queue
041:13:22:36 T394422016 put_msg_in_table: storing msgtype=0x6b, msgid=2 in table
041:13:22:36 T394422016 is_last_msg: returning TRUE, msgid=2
041:13:22:36 T394422016 ldap_msg_table_get_message: returning rc=107
041:13:22:36 T394422016 fber_scanf fmt ({iaa) offset=3 length=16

Il semble donc y avoir un problème avec un objet intermédiaire dans l'arborescence.

Aucune information sur internet, même ChatGPT n'est pas capable de donner une réponse.

Investigations du côté DB2

L'annuaire IBM Directory Server utilse une base de données DB2 comme moteur de stockage (il faut bien placer les produits de l'éditeur...).

On peut trouver quelques éléments techniques sur les liens entre ISDS et DB2 via le site IBM :

https://www.ibm.com/docs/en/sdse/6.4.0?topic=caches-directory-server-db…

Pour cela, il faut se connecter avec l'utilisateur propriétaire de la base et de l'annuaire. Dans notre cas, c'est idsldap.

La table ldap_entry est la table principale dans DB2, elle contient l'objet complet (sa représentation LDIF), ainsi qu'un identifiant technique (EID = Entry ID), le DN et quelques colonnes techniques :

  • EID : Entry ID, identifiant unique, c'est la clé qui est utilisée ensuite dans toute la base
  • PEID : Parent EID, identifiant du parent (le LDAP étant une structure hiérarchique)
  • DN_TRUNC : le DN de l'objet, en majuscules, tronqué à 240 caractères
  • DN : le DN de l'objet complet (1000 caractères)
  • CREATOR : qui a créé l'objet
  • MODIFIER : le compte qui a modifié l'objet
  • MODIFY_TIMESTAMP : timestamp de la dernière modification
  • CREATE_TIMESTAMP : timestamp de la création
  • ENTRYDATA : données de l'entrée au format LDIF (24 000 caractères maximum)
  • ENTRYBLOB : le BLOB contenant toute l'entrée
  • ENTRYSIZE : taille des données

On trouve ensuite une table par attribut indexé, afin de faciliter et accélérer les recherches. La structure de ces tables est toujours la même. Exemple pour l'attribut SN :

$ db2 describe table sn

                                Data type                     Column
Column name                     schema    Data type name      Length     Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
EID                             SYSIBM    INTEGER                      4     0 No    
SN                              SYSIBM    VARCHAR                    128     0 No    
RSN                             SYSIBM    VARCHAR                    128     0 Yes   
  • EID : Entry ID de l'entrée
  • SN : Valeur de l'attribut
  • RSN : Reverse SN (valeur de l'attribut à l'envers)

On remarque donc que le nom des colonnes et le nom de la table sont identiques.

Notre investigation va donc commencer en recherchant le EID qui correspond à notre DN (la valeur de dn_trunc doit être en majuscules) :

su - idsldap

db2 connect to idsldap

db2 "select eid from ldap_entry where dn_trunc = 'ERGLOBALID=2711683785790239385,OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR'"

db2 "select ENTRYDATA from ldap_entry where dn_trunc = 'ERGLOBALID=2711683785790239386,OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR'"

On constate qu'il n'y a pas de EID pour ce DN, ce qui pourrait expliquer que

Pour une entrée correcte :

db2 "select eid from ldap_entry where dn_trunc = 'ERGLOBALID=2711683785790239386,OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR'"

EID        
-----------
    2382915

Nous allons alors tenter une recherche sur une valeur partielle :

db2 "select eid from ldap_entry where dn_trunc LIKE '%2711683785790239385%'"

EID        2110475
-----------
    2110475

db2 "select dn_trunc from ldap_entry where eid = 2110475"

DN_TRUNC                                                                                                                                                                                                                                        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ERGLOBALID=2711683785790239385,OU=RECYCLEBIN,OU=ITIM,OU=MYCORP,O=MYCORP-IIR   

Par contre si on récupère le LDIF de l'objet (ENTRYDATA), on y trouve notre DN attendu :

2110475
dn: erglobalid=2711683785790239385,ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,O=MYCORP-IIR

En fait le fonctionnement de la recherche LDAP fait une jointure entre les tables de type index et la table ldap_entry. Globalement, si je fais une recherche de ce type :

ldapsearch -L -D cn=root -w myP@SSword -b ou=0,ou=people,erglobalid=00000000000000000000,ou=MYCORP,o=MYCORP-iir "(employeenumber=XFR2094002)"

Ceci peut se traduire par une requête DB2 :

db2 "select e.entrydata, e.dn FROM ldap_entry e, employeenumber en WHERE en.employeenumber = 'XFR2094002' AND e.eid = en.eid"

Dans notre cas, l'objet avait été récupéré de la "corbeille" ITIM, et réinjecté dans la branche active, mais visiblement avec quelques soucis.

On peut voir l'arborescence d'une entrée via un select dans la table ldap_desc :

db2 "select * from ldap_desc where deid = 2110475"

DEID        AEID       
----------- -----------
    2110475          11
    2110475          39
    2110475         176
    2110475         178
    2110475         185
    2110475     2110475

Et si on regarde le premier sous-niveau :

db2 "select dn from ldap_entry where eid=185"
OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR 

On constate donc que le DN correspondant à la colonne EID n'est pas le même que le parent direct (d'où sans doute la donnée apparue en mode Debug)

Correction du problème

On peut alors corriger le problème en alignant la valeur des colonnes DN et DN_TRUNC dans la table ldap_entry :

db2 "update ldap_entry set dn_trunc = 'ERGLOBALID=2711683785790239385,OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR' where eid = 2110475"
db2 "update ldap_entry set dn = 'ERGLOBALID=2711683785790239385,OU=0,OU=PEOPLE,ERGLOBALID=00000000000000000000,OU=MYCORP,O=MYCORP-IIR' where eid = 2110475"

Suite à cette manipulation, l'objet peut être visualisé et modifié dans ISIM.

Catégorie
Tag

Ajouter un commentaire

Plain text

  • Aucune balise HTML autorisée.
  • Les adresses de pages web et les adresses courriel se transforment en liens automatiquement.
  • Les lignes et les paragraphes vont à la ligne automatiquement.