Database
 sql >> Base de données >  >> RDS >> Database

Comment garder une trace de ce que font les utilisateurs

Dans plusieurs des projets sur lesquels nous avons travaillé, les clients nous ont demandé de consigner davantage d'actions d'utilisateurs dans la base de données. Ils veulent connaître toutes les actions que les utilisateurs effectuent dans l'application, mais capturer et enregistrer toutes les interactions humaines peut être difficile. Nous devions consigner toutes les modifications de données effectuées via le système. Cet article décrit certains des pièges que nous avons rencontrés et les approches que nous avons utilisées pour les surmonter.

Présentation

Je travaille en tant qu'architecte de solutions dans les services financiers. Il est important de garder une trace du dernier utilisateur qui a modifié une ligne. Dans les cas les plus simples, il suffit d'enregistrer l'horodatage de la modification pour avoir une traçabilité de changements. Voici un exemple simple d'une table qui stocke les accords client qui incluent last_changed colonnes pour l'utilisateur et l'horodatage.




Pourtant, dans certains cas, cela ne suffit pas. Nous devons souvent avoir une traçabilité complète (y compris avant et après les "images" des données). Dans certains cas, nous avons également besoin d'auditabilité (qui, quoi, quand).

Malheureusement, bon nombre de nos systèmes n'ont pas été conçus pour assurer la traçabilité et l'auditabilité. Nous devions faire de l'ingénierie inverse ces exigences d'opérations commerciales dans les systèmes.

Traçabilité

Dans certains cas, nous avons trouvé la traçabilité facile à réaliser. Alors que, dans d'autres, nous avons trouvé cela difficile, voire impossible. Selon votre système, la solution peut être simple. Votre accès aux données peut permettre une simple injection de journalisation des images avant et après des données. Cette journalisation peut être mise en œuvre de sorte que les résultats soient stockés dans une table de base de données plutôt que dans un fichier journal. Dans certains produits, nous y sommes parvenus de manière simple grâce à la persistance couche. Par exemple, cela était possible avec Hibernate .

Ici, vous pouvez voir une entrée pour chaque élément de piste d'audit, ainsi que des valeurs avant et après pour chaque colonne qui a changé. De plus, dans le cas où une ligne est supprimée, nous enregistrons cette information avec le functioncode indiquant supprimer. Nous avons choisi d'utiliser varchar(1) pour stocker le code de la fonction (C, R, D) spécifiant le type de modification, plutôt que le nom ou la description de « l'opération » (Create, Update, Delete) qui a été effectuée . La instance_key contient la clé primaire de l'élément qui a été ajouté, modifié ou supprimé, pour la traçabilité.




Pourtant, il se peut que votre couche d'accès aux données ne vous fournisse pas les fonctionnalités nécessaires. Pour les autres produits, notre couche d'accès aux données ne l'a pas fait. Dans ces cas, la traçabilité nécessitait des changements complexes. Par exemple, vous aurez peut-être besoin de la récupération et journalisation de toute donnée avant modification. Comme je l'écrivais, cela est possible mais peut être complexe à mettre en place. Les développeurs devraient créer une récupération de chaque ligne avant de modifier une ligne. Il ne serait pas possible qu'une mise à jour s'exécute sans une sélection.

Comment contourner la traçabilité ? Une solution possible consiste à s'assurer que vous connaissez la situation de départ de toutes les données, c'est-à-dire la situation de départ créée par toutes les données statiques chargées dans le système. Ensuite, vous devrez enregistrer toutes les modifications. En d'autres termes, quelles sont toutes les images « après » des données ? De cette façon, il serait possible de "avancer ” à partir des données statiques chargées. Toutes les mises à jour effectuées jusqu'à ce moment sont appliquées. Cette situation n'est pas idéale, mais peut être acceptable.

Un tableau simple peut être utilisé si la seule information disponible est la nouvelle valeur et non la valeur précédente.




Auditabilité

Dans certaines situations, nous devons nous assurer que toutes les actions entreprises dans le système sont entièrement vérifiables . Qui s'est connecté à quelle heure ? Quelles actions chaque utilisateur a-t-il effectuées dans le système, y compris uniquement l'affichage des données ? Ceci est important car cela peut être significatif si un utilisateur regarde un paiement.

Pour obtenir un traçage précis peut être difficile de ne regarder que l'accès à la base de données. Il faut souvent regarder à un niveau supérieur et examiner les actions ou services rendus. Dans certains cas, nous avons pu tracer chaque appel de service pour savoir ce qu'un utilisateur a fait à quel moment. Avec un contrôleur d'entrée/sortie de service Web, la journalisation des demandes de service était assez facile.

Voici un exemple de journal d'audit utilisateur simple où nous enregistrons l'action que chaque utilisateur effectue. Je discute de certaines questions concernant cette approche dans la section suivante "Preuve".




Une courte description du tableau est donnée ci-dessous :

Le user_audit table contient des entrées d'audit de données qui sont horodatées. La clé primaire est constituée de audit_entry_time tampon plus le user_id et bank_id plus le nom de l'action effectué. Les champs ont des significations qui correspondent à leurs noms. La table d'audit stocke le result de l'action, plus la class réelle qui a exécuté l'action, ses parameters d'entrée et toutes les errors .

Voici un autre exemple de piste d'audit où nous enregistrons les images avant et après des données qui ont été modifiées dans une table particulière (avec l'action effectuée, les informations d'identification de l'utilisateur et l'horodatage).




Le audit_trail table contient les entrées d'audit des images avant et après des données. La clé primaire est constituée du audit_gen_key c'est une clé générée par l'application. Les champs ont des significations qui correspondent à leurs noms. Le nom de la table de base de données pour laquelle cette entrée de piste d'audit est enregistrée est stocké dans modified_table , plus l'image "avant" est stockée dans prev_value et l'image "après" dans new_value . Le module qui effectue la modification et le funct_type de modification (Créer, Mettre à jour, Supprimer) sont également stockés. Enfin, les informations d'audit de l'user_id (et bank_id correspondant ) plus l'horodatage de la modification (date_last_changed ).

Ensuite, nous avons relevé un défi. Lors de la journalisation des informations de traçabilité et des informations d'auditabilité, la journalisation se produit deux fois. D'un point de vue d'audit, c'est ennuyeux. Les auditeurs doivent s'assurer que les informations sont les mêmes entre ces deux journaux.

Preuve

Un autre défi était d'assurer la journalisation de toutes les actions de l'utilisateur . Cela est souvent exigé par les auditeurs du secteur des services financiers.

Maintenant, nous avons un vrai défi. Notre solution consistait à assurer une traçabilité centralisée et une journalisation de l'auditabilité. Les « interfaces » centrales garantissent que toutes les implémentations de cette interface incluent la journalisation. Il était simple de s'assurer que toutes les classes appropriées implémentaient l'interface.

Bien sûr, cela ne garantit pas une preuve à 100% de la journalisation. C'est un contrôle de sécurité solide que toutes les classes appropriées se sont connectées comme requis.

Conclusion

L'ingénierie inverse de nouvelles fonctionnalités commerciales dans un système existant est toujours un défi. Cela peut être encore plus le cas lorsque la fonctionnalité implémentée va au cœur.