Session de formation PSPO I du 15 au 16 juin démarre - Réservez votre place dès maintenant en cliquant ici !
sql 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.
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 :
(source CNIL)
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.
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.
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.
Voici le contenu des tables :
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 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
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 :
SECURITY LABEL FOR anon ON COLUMN public.personne.nom IS 'MASKED WITH FUNCTION anon.fake_last_name()';
SECURITY LABEL FOR anon ON COLUMN public.personne.prenom IS 'MASKED WITH FUNCTION anon.fake_first_name()';
SECURITY LABEL FOR anon ON COLUMN public.personne.ville_naissance IS 'MASKED WITH FUNCTION anon.fake_city()';
SECURITY LABEL FOR anon ON COLUMN public.personne.telephone IS 'MASKED WITH FUNCTION anon.random_phone()';
SECURITY LABEL FOR anon ON COLUMN public.personne.mail IS 'MASKED WITH FUNCTION anon.partial_email(mail)';
SECURITY LABEL FOR anon
ON COLUMN public.personne.commentaire IS 'MASKED WITH FUNCTION anon.lorem_ipsum(words := 5)';
SECURITY LABEL FOR anon ON COLUMN public.personne.prenom_formate IS 'MASKED WITH VALUE' 'PRENOM''';
SECURITY LABEL FOR anon
ON COLUMN public.compte_bancaire.date_ouverture IS 'MASKED WITH FUNCTION anon.random_date()';
SECURITY LABEL FOR anon ON COLUMN public.compte_bancaire.iban IS 'MASKED WITH FUNCTION anon.fake_iban()';
SECURITY LABEL FOR anon
ON COLUMN public.compte_bancaire.montant IS 'MASKED WITH FUNCTION anon.random_int_between(5000, 200000)';
Pour un aperçu plus exhaustif des règles de masquage, consulter cette page.
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 plpgsal
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)';
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 plpgsal
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'')';
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
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 :
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
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 plpgsal
AS
$$
BEGIN
RETURN anon.random_in(ARRAY['Paris', 'Londres', 'Washington', 'Tokyo']);
END;
$$;
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 :