Anomalie #180
Synchronisation entre la base de données du SI et le LDAP
100%
Description
Si on ne fait pas attention, la base de données du SI et le LDAP peuvent se retrouver désynchronisés (i.e. les informations présentes de chaque côté ne sont pas cohérentes). Quand ça arrivera (et ça arrivera un jour, par loi de Murphy), ce sera très chiant à gérer.
Dans quel cas les deux bases de données peuvent être désynchronisées ?
- Remise à zéro d'une des deux bases
- Bug dans le code
- LDAP non accessible, ce qui empêche le SI d'écrire dedans
- Modification du LDAP en dehors du SI
Pour le LDAP non accessible, ça peut se résoudre en empêchant le SI d'écrire dans sa propre base tant qu'il n'a pas réussi à écrire dans le LDAP.
D'autres idées ?
Related issues
Updated by Baptiste Jonglez over 9 years ago
Pour l'instant, on utilise des signaux (notamment post_save()) pour enregistrer des objets dans le LDAP quand des objets sont sauvés dans la base postgresql. Ça ne semble pas convenir si le LDAP tombe : les données seront quand même enregistrées dans la base du SI (à confirmer)
Une manière peut-être plus satisfaisante est de redéfinir la méthode save() : https://docs.djangoproject.com/en/1.6/topics/db/models/#overriding-model-methods
Par contre, ce n'est pas clair de savoir si l'écriture LDAP a échouée ou non (exception ?)
Updated by Baptiste Jonglez over 9 years ago
Il y a une autre possibilité : ne pas chercher à tout prix à garder le SI et le LDAP synchronisés, et se garder la possibilité de regénérer tout le LDAP à partir du SI quand la synchro est perdu.
20:57 <@zorun> du coup, soit on s'assure autant que possible que ça reste synchro, et on regénère complètement (à la main) dans les cas vraiment tordus
20:57 <@zorun> soit on s'occupe pas trop de la synchro, et le SI regénère le LDAP quand il voit que c'est pas synchro
Détection de perte de synchronisation : timestamp, numéro de séquence, etc (pas forcément évident à coder correctement)
Updated by Pierre-Arnaud Poudret over 9 years ago
<lemur> c'est un peu pénible à écrire mais c'est faisable
<lemur> et si on fait des controles, on peut intégrer les corrections pour le même prix et ne faire qu'un script
<zorun> euh, ça me paraît pas évident
<zorun> à moins de, en gros, générer tout et comparer si c'est identique :)
<lemur> je pensais à parcourir les tables, interroger le ldap pour trouver les enrgistrements correspondants, vérifier qu'il n'y en a pas en trop... type de donnée par type de donnée. clairement c'est laborieux à écrire
- albatros vote pour git :)
- lemur réfléchit à l'idée de tout générer et comparer
<zorun> lemur: tu rajoutes sur https://www.illyse.org/issues/180 ?
<zorun> effectivement, ça a l'air laborieux
<zorun> mais en fait, c'est aussi un peu laborieux de générer
<zorun> c'est dur à automatiser, il faudra le faire pour chaque type de données
<zorun> enfin, j'ai l'impression
<lemur> oui, à coder c'est de la dentelle
<zorun> ouaip
<zorun> bon, je surveille mon riz et je lis la partie VPN
<albatros> et faire un diff du ldif ?
<lemur> albatros: ouais
<lemur> genre générer tout dans une autre branche (voire un autre daemon openldap), exporter la branche de prod et la branche de test, puis comparer
<lemur> ça promet des faux positifs mais ça se tente peut-être
<lemur> et ça permettrait d'automatiser les corrections dn par dn, plutôt que de tout virer et tout regénérer
<zorun> yep
<zorun> enfin, automatiser les corrections, je suis pas fan
<zorun> ça peut faire plus de dégats qu'autre chose :)
<zorun> par contre, remonter qu'il y a un problème, oui
<lemur> ouais
<albatros> ce serait mieux de péter une alerte
<albatros> et de réparer à la main
Updated by Fabien Michel over 9 years ago
Baptiste Jonglez a écrit :
La fonctionnalité est implémentée dans le model Member de la manière suivante :Pour l'instant, on utilise des signaux (notamment post_save()) pour enregistrer des objets dans le LDAP quand des objets sont sauvés dans la base postgresql. Ça ne semble pas convenir si le LDAP tombe : les données seront quand même enregistrées dans la base du SI (à confirmer)
Une manière peut-être plus satisfaisante est de redéfinir la méthode save() : https://docs.djangoproject.com/en/1.6/topics/db/models/#overriding-model-methods
Par contre, ce n'est pas clair de savoir si l'écriture LDAP a échouée ou non (exception ?)
Dans la fonction save :
- On désactive l'autocommit
- On enregistre en base
- On enregistre dans le LDAP
- Si ca échoue on rollback sinon on commit
J'ai préféré cette méthode (rollback) pour s'assurer qu'on ne puisse pas, à l'inverse, écrire dans le LDAP et rien en base. Ce qui a mon sens serait encore pire.
Updated by Fabien Michel over 9 years ago
<lemur> je pensais à parcourir les tables, interroger le ldap pour trouver les enrgistrements correspondants, vérifier qu'il n'y en a pas en trop... type de donnée par type de donnée. clairement c'est laborieux à écrire
<zorun> effectivement, ça a l'air laborieux
<zorun> mais en fait, c'est aussi un peu laborieux de générer
<zorun> c'est dur à automatiser, il faudra le faire pour chaque type de données
<zorun> enfin, j'ai l'impression
<lemur> oui, à coder c'est de la dentelle
C'est peut-être pas aussi compliqué.
Exemple dans le model Member, il y une méthode sync_with_ldap qu'il faut de toute façon écrire pour chaque type de donnée pour faire la synchro lors de la sauvegarde.
"Il suffit" alors de parcourir chaque membre et d'appeler cette fonction.
On fait ça pour chaque type de donnée à synchro et "pof" on régénère le LDAP.
Par contre, pour blinder le truc, il faut impérativement écrire moultes tests sur cette fonction qui sera vitale pour notre SI.
Updated by Fabien Michel over 9 years ago
Fabien Michel a écrit :
Dans la fonction save :
- On désactive l'autocommit
- On enregistre en base
- On enregistre dans le LDAP
- Si ca échoue on rollback sinon on commit
Pour ne pas répéter notre self, j'ai réfléchi à l'idée de généraliser cette surcharge de save dans un model custom en définissant la correspondance des champs dans le model principal ou un truc du genre. Mais il y a a mon avis trop de choses spécifiques à chaque type de données et la généralisation ne sera pas pertinente.
Updated by Fabien Michel over 9 years ago
En faite on peut généraliser un minimum. J'ai créer un modèle abstrait CoinLdapSyncModel qui appel la méthode sync_to_ldap que l'on doit donc définir dans le modèle. Cette méthode d'occupe de la synchronisation avec LDAP.
Si elle échoue alors le modèle abstrait, qui surcharge la méthode save, fait en sorte que la sauvegarde en base n'est pas lieu.
Updated by Fabien Michel over 9 years ago
Par ailleurs cela permettra, je pense, de repérer les modèles utilisant ce modèle abstrait dans le tas et donc d'automatiser le script de re-génération du LDAP.
Updated by Baptiste Jonglez over 9 years ago
- Status changed from Nouveau to Fermé
- Assignee changed from Pierre-Arnaud Poudret to Fabien Michel
- Target version set to 0.1
- % Done changed from 0 to 100
Super :)