Logo


Culture de l'ingénierie,
esprit d'exécution

  • Accueil
  • Qui sommes nous ?
  • Notre offre
  • Nos produits
  • Publications
  • Recrutement
  • Contact
  • Anonymisation - Etude de PostgreSQL Anonymizer

    La protection des données personnelles est un point crucial de tout système d’information. Il l’est devenu d’autant plus depuis la mise en place du RGPD il y a quelques années. Ce règlement a contraint les professionnels à mettre en place des solutions pour assurer la confidentialité de ces données et ainsi, respecter la vie privée.

    Parmi les points critiques d’un système d’information, on trouve, entre autre, les bases de données qui peuvent contenir une quantité incroyable de données sensibles (noms, coordonnées, informations bancaires, …). Mais ces bases de production (et leur contenu) sont souvent utilisées par les développeurs eux-mêmes, des prestataires externes, … pour faire des tests de leurs applications ou logiciels, et tous ces acteurs peuvent donc avoir accès à toutes ces données sensibles. Une des solutions possibles est d’anonymiser ces bases pour assurer la confidentialité des données personnelles, et ainsi éviter d’identifier des personnes en particulier.

    Dans cet article, je vais vous présenter un outil permettant d’anonymiser une base de données PostgreSQL pour pouvoir l’utiliser dans un environnement de développement (ou de recette) en préservant la confidentialité des données : PostgreSQL Anonymizer.

    RGPD, données personnelles et anonymisation

    Le RGPD (Règlement Général sur la Protection des Données) règlemente le traitement des données personnelles dans l’Union Européenne et est entré en vigueur le 25 mai 2018. Il oblige les entités collectant des données personnelles à se mettre dans une démarche et une réflexion pour assurer la protection de ces données :

    Mais qu’est-ce qu’une donnée personnelle ? C’est une information permettant d’identifier une personne physique :

    Pour assurer la sécurisation des données et préserver leur confidentialité, la CNIL propose, entre autres, comme solution, l’anonymisation de ces données, empêchant ainsi l’identification d’une personne physique de manière irréversible. L’anonymisation consiste notamment à supprimer les données d’identification directe (nom, prénom, …), les valeurs rares (les personnes centenaires ou les personnes vivant dans des endroits peu peuplés seront facilement identifiables), … tout en conservant un jeu de données cohérent et utilisable. L’anonymisation peut se faire à l’aide de différentes techniques :

    Attention, il faut différencier l’anonymisation et la pseudonymisation : la pseudonymisation remplace une donnée directement identifiante (nom, prénom, …) par une donnée indirectement identifiante (pseudo, numéro, …) ce qui permet tout de même de retrouver d’autres infos personnelles. Contrairement à l’anonymisation qui est un processus irréversible, la pseudonymisation est un processus réverssible. Cependant, la pseudonymisation reste une mesure recommandée, à défaut d’anonymisation complète. Le but est de compliquer la récupération des données personnelles.

    Le RGPD se base sur 3 critères pour garantir l’anonymat des données :

    • l’individualisation : il ne doit pas être possible d’isoler un individu dans le jeu de données
    • la corrélation : il ne doit pas être possible de relier entre eux des ensembles de données distincts concernant un même individu
    • l’inférence : il ne doit pas être possible de déduire, de façon quasi certaine, de nouvelles informations sur un individu

    (source CNIL)

    Présentation de PostgreSQL Anonymizer

    PostgreSQL Anonymizer est une extension de PostgreSQL permettant d’anonymiser une base de données. Elle est, à l’heure où j’écris cet article, en version beta mais est très performante dans la version actuelle.

    PostgreSQL Anonymizer permet d’anonymiser une base en déclarant des règles de “masquage” sur les colonnes “sensibles”.

    PostgreSQL Anonymizer propose 3 façons d’anonymiser une base de données :

    PostgreSQL Anonymizer contient tout un ensemble de fonctions de masquage basiques :

    PostgreSQL Anonymizer permet aussi d’utiliser ses propres fonctions de masquage personnalisées pour des besoins spécifiques ou un peu plus complexes.

    PostgreSQL Anonymizer propose une image docker qui contient PostgreSQL accompagné de l’extension PostgreSQL Anonymizer. Cette image docker évite d’installer l’extension PostgreSQL Anonymizer directement sur la base de production (non intrusif), et permet ainsi de cloisonner le processus d’anonymisation de cette base (ex : sur un autre serveur) sans interférer avec la base originale.

    Mise en oeuvre

    Dans cet exemple, nous allons générer avec PostgreSQL Anonymizer, un dump anonymisé à partir d’un dump d’une base non-anonymisée (ex : une base de prod). Pour cela, nous allons utiliser l’image docker de l’extension.

    Pré-requis :

    Présentation de l’exemple

    Nous allons prendre un exemple simpliste d’une base de données bancaires contenant une table personne avec leurs nom, prénom, date de naissance, coordonnées et commentaire et une table compte_bancaire d’une personne contenant la date d’ouverture, l’IBAN et le montant qu’il y a sur le compte.

    Diagramme de la base

    Voici le contenu des tables :

    Table personne

    Table compte bancaire

    Installation de PostgresSQL Anonymizer

    Récupérer la dernière version de l’image docker de PostgreSQL Anonymizer :

    docker pull registry.gitlab.com/dalibo/postgresql_anonymizer
    

    Lancer un conteneur docker de PostgreSQL Anonymizer nommé test_pganonymizer_container en spécifiant les identifiants Postgres correspondants à la base que vous souhaitez anonymiser (ici test_pga). Cela va lancer Postgres en ajoutant l’extension à PostgreSQL Anonymizer :

    docker run -d --name test_pganonymizer_container -p 6543:5432 -e POSTGRES_USER=test_pga -e POSTGRES_PASSWORD=test_pga -e POSTGRES_DB=test_pga registry.gitlab.com/dalibo/postgresql_anonymizer
    

    Récupérer le script d’initialisation (init_pg_anonymizer.sql) de l’extension PostgreSQL Anonymizer :

    wget https://scub-france.github.io/anonymisation-base-de-donnees-avec-postgresql-anonymizer/init_pg_anonymizer.sql
    
    SELECT pg_catalog.set_config('search_path', 'public', false);
    CREATE EXTENSION IF NOT EXISTS anon CASCADE;
    SELECT anon.init();
    

    Initialiser l’extension PostgreSQL Anonymizer sur la base de données test_pga avec le script précédent :

    cat init_pg_anonymizer.sql | docker exec -i test_pganonymizer_container psql -U test_pga
    

    Si l’installation s’est bien passée, vous devriez voir dans les logs l’anonymisation d’une adresse mail :

         partial_email     
    -----------------------
     te******@te******.net
    (1 row)
    

    A partir de là, vous avez un conteneur prêt pour générer un dump anonymisé de la base de données que vous souhaitez. Pour l’exemple, ce sera notre base de données bancaires.

    Télécharger le dump source de la base de données bancaire dump_source.sql :

    wget https://scub-france.github.io/anonymisation-base-de-donnees-avec-postgresql-anonymizer/dump_source.sql
    

    Restaurer la base de données bancaires dans le conteneur d’anonymisation :

    cat dump_source.sql | docker exec -i test_pganonymizer_container psql -U test_pga
    

    Règles / Masques basiques

    L’ajout d’une règle de masquage sur une colonne consiste en une requête SQL. Cet ajout se fait en déclarant la fonction à appliquer sur la colonne par l’intermédiaire du SECURITY LABEL et en passant les paramètres souhaités (nom de colonne, variable, constante, …) :

    SECURITY LABEL FOR anon ON COLUMN nom_colonne IS 'MASKED WITH FUNCTION nom_fonction(nom_colonne_ou_params)';
    

    ou pour l’ajout d’une constante :

    SECURITY LABEL FOR anon ON COLUMN nom_colonne IS 'MASKED WITH VALUE ''La constante''';
    

    Voici la présentation de quelques fonctions de masquages que nous allons appliquer sur notre exemple :

    Pour un aperçu plus exhaustif des règles de masquage, consulter cette page.

    Règles / Masques personnalisés

    Pour définir une règle de masquage personnalisée pour un comportement spécifique, il suffit d’écrire une fonction SQL qui implémente la règle et déclarer cette fonction comme règle sur la colonne souhaitée.

    CREATE OR REPLACE FUNCTION anon.date_naissance_tronquee(date_initiale TIMESTAMP)
        RETURNS TEXT
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
    RETURN date_trunc('year', initial_value) + interval '5 month';
    END;
    $$;
    
    SECURITY LABEL FOR anon ON COLUMN public.personne.date_naissance IS 'MASKED WITH FUNCTION anon.date_naissance_tronquee(date_naissance)';
    
    CREATE OR REPLACE FUNCTION anon.nom_minuscule(seed TEXT, salt TEXT)
        RETURNS TEXT
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
    RETURN lower(anon.pseudo_last_name(seed, salt));
    END;
    $$;
    
    SECURITY LABEL FOR anon ON COLUMN public.personne.nom IS 'MASKED WITH FUNCTION anon.pseudo_last_name(nom || id, ''1234'')';
    SECURITY LABEL FOR anon ON COLUMN public.personne.nom_formate IS 'MASKED WITH FUNCTION anon.nom_minuscule(nom || id, ''1234'')';
    

    Toutes les règles déclarées précédemment sont disponibles dans le fichier regles.sql :

    wget https://scub-france.github.io/anonymisation-base-de-donnees-avec-postgresql-anonymizer/regles.sql
    

    Déclarer l’ensemble des règles de masquage dans le conteneur d’anonymisation :

    cat regles.sql | docker exec -i test_pganonymizer_container psql -U test_pga
    

    Génération du dump anonyme

    Pour générer le dump anonyme de la base source, il faut utiliser la commande pg_dump_anon qui s’utilise comme la commande pg_dump :

    docker exec -i test_pganonymizer_container pg_dump_anon -h localhost -U test_pga > dump_anonyme.sql
    

    Une fois le dump anonyme restauré sur une autre base, voici le résultat de l’anonymisation : Table personne anonymisée

    Table compte bancaire anonymisée

    Une fois l’anonymisation terminé, vous pouvez faire un peu de nettoyage (arrêt et suppression du conteneur) :

    docker container stop test_pganonymizer_container
    docker container rm test_pganonymizer_container
    

    Avantages / Inconvénients

    Avantages

    Inconvénients

    Problèmes génériques à l’anonymisation

    Astuces

    Comme vu précédemment, le temps de traitement peut être long sur les bases volumineuses à cause des requêtes faites sur les tables de références pour générer des valeurs aléatoires (noms, villes, …). Pour éviter ces nombreux accès en base et avoir un traitement beaucoup plus rapide, vous pouvez remplacer les appels aux fonctions fake…() par des fonctions personnalisées s’appuyant sur des tableaux de valeurs. Voici un exemple d’une fonction de génération aléatoire de villes s’appuyant sur un tableau :

    CREATE OR REPLACE FUNCTION anon.ville_personnalisee()
        RETURNS TEXT
        LANGUAGE plpgsql
    AS
    $$
    BEGIN
        RETURN anon.random_in(ARRAY['Paris', 'Londres', 'Washington', 'Tokyo']);
    END;
    $$;
    

    Conclusion

    PostgreSQL Anonymizer, avec ces nombreuses fonctions de masquage et de remplacement, est un outil très efficace pour générer des dumps anonymisés de votre base Postgres, et ainsi, se conformer au RGPD. La principale difficulté va être dans le choix des différentes règles d’anonymisation afin d’assurer la confidentialité totale des données (ou du moins, de s’en approcher fortement). Cette réflexion sur la confidentialité des données devrait se faire dès la conception de la base (quand c’est possible).

    Liens :