Aller au contenu

Masquage dynamique pour tests et développement

Le masquage dynamique de données affiche une valeur transformée selon l’identité qui la lit, sans modifier nécessairement la donnée source. C’est une option valable quand les données doivent rester cohérentes et consultables, mais ce n’est pas une anonymisation et certainement pas un permis de copier la production dans chaque environnement.

→ Lire l’explication complète de la marmotte

Masquage dynamique, anonymisation et données de test

Section intitulée « Masquage dynamique, anonymisation et données de test »

Le compromis central est brutal : le masquage dynamique conserve la valeur originale quelque part et protège son affichage, tandis que l’anonymisation supprime ou transforme durablement le lien avec la personne concernée. On gagne en fraîcheur, en cohérence relationnelle et en fidélité fonctionnelle. On paie par une dépendance forte au moteur qui applique la politique, aux identités et aux chemins d’accès.

Cette distinction décide de l’architecture. Une base exportée vers un environnement de développement n’est plus protégée par un masque dynamique appliqué sur la source : l’export contient les valeurs réellement lues par le compte qui l’a produit. Si le compte peut lire les colonnes brutes, le fichier aussi. Le fichier CSV devient alors un actif sensible avec la mobilité naturelle d’une chaussette dans un sèche-linge.

Le masquage dynamique convient à trois cas précis :

  1. Un environnement de test partagé interroge une base centralisée, sans export libre.
  2. Des équipes de support ou de recette doivent reproduire un comportement métier sur des données actuelles.
  3. Les données doivent conserver leurs formats, leurs cardinalités et leurs relations, mais pas leur contenu lisible.

Pour les développements autonomes, les pipelines d’intégration continue ou les bases locales, la recommandation est différente : produire un jeu dérivé par pseudonymisation déterministe et suppression des attributs inutiles. Le catalogue des sujets de données doit distinguer ces flux, car traiter de la même façon une console de recette et un dump de base est une erreur de périmètre, pas un détail d’implémentation.

Le masquage dynamique ne rend pas une donnée anonyme. Une date de naissance tronquée, un code postal conservé et un historique de commande restent souvent réidentifiants par recoupement. Les données quasi-identifiantes, c’est-à-dire les attributs qui identifient une personne une fois combinés, doivent être traitées comme des données sensibles même sans nom ni adresse électronique.

Architecture de masquage dynamique et contrôle des accès

Section intitulée « Architecture de masquage dynamique et contrôle des accès »

Le mécanisme doit être placé sur le chemin obligatoire de lecture. En pratique, cela signifie un moteur de base de données, une vue contrôlée, une passerelle d’interface de programmation ou un proxy applicatif. Le choix dépend du protocole utilisé, mais la règle reste fixe : aucune identité de test ou de développement ne doit disposer d’un chemin alternatif vers les tables brutes.

Un contrôle d’accès fondé sur les rôles, ou RBAC (Role Based Access Control), suffit lorsque les profils sont stables : développeur, recette, support, administrateur de données. Un contrôle d’accès fondé sur les attributs, ou ABAC (Attribute Based Access Control), devient préférable quand la politique dépend aussi de l’environnement, de l’application appelée, du ticket d’incident ou de la plage horaire. Ajouter des rôles à l’infini pour représenter chaque exception transforme vite l’annuaire en terrarium administratif.

La politique doit s’écrire colonne par colonne, pas table par table. Les catégories minimales sont :

  • masquage total : afficher une constante ou NULL pour les données sans usage de test ;
  • masquage partiel : conserver les derniers caractères d’un numéro seulement si ce format est requis ;
  • pseudonymisation déterministe : produire toujours la même valeur de remplacement pour une même entrée ;
  • généralisation : remplacer une date par son mois, une adresse par une région ;
  • accès brut exceptionnel : réserver à une identité nominative, avec justification et journalisation.

La pseudonymisation déterministe permet aux jointures et aux recherches de rester fonctionnelles. Elle impose une clé secrète, car un hachage non salé d’une adresse électronique ou d’un numéro de téléphone se renverse par dictionnaire. Une fonction de hachage comme SHA-256 (Secure Hash Algorithm 256 bits) ne devient pas magique en présence d’un domaine de valeurs petit et prévisible.

Pour une valeur déterministe, utiliser un code d’authentification de message à base de hachage, ou HMAC (Hash-based Message Authentication Code), avec une clé dédiée et versionnée. La clé ne doit jamais être stockée dans une vue, une variable d’environnement applicative ou un script de migration. Une telle clé finit dans une sauvegarde, puis dans une archive, puis dans une enquête où personne ne se souvient pourquoi elle existe. La gestion du secret relève de la cryptographie appliquée et de la séparation des responsabilités, pas d’un commentaire # secret ici dans un dépôt.

PostgreSQL ne fournit pas un masquage dynamique natif équivalent à certaines offres commerciales. Des vues dédiées, des privilèges stricts et des fonctions de transformation permettent néanmoins de construire un mécanisme contrôlable. Cette approche ne protège que si les droits sur les tables sources sont retirés, y compris via les rôles hérités.

-- Table source : aucun rôle de recette ne doit recevoir SELECT dessus.
REVOKE ALL ON TABLE production.clients FROM role_recette;
-- Vue exposée à la recette : conserver le domaine pour les tests de format,
-- masquer l'identité, et ne jamais retourner le numéro complet.
CREATE VIEW recette.clients_masques
WITH (security_barrier = true) AS
SELECT
id_client,
left(nom, 1) || '***' AS nom,
regexp_replace(email, '^[^@]+', 'utilisateur') AS email,
'XXXXXX' || right(numero_client, 4) AS numero_client,
date_trunc('month', date_naissance)::date AS date_naissance,
pays
FROM production.clients;
GRANT SELECT ON recette.clients_masques TO role_recette;
REVOKE ALL ON SCHEMA production FROM role_recette;

La clause security_barrier limite certaines réécritures de requêtes autour de la vue, mais elle ne remplace pas une revue de sécurité. Les fonctions appelées par une vue doivent être déterministes si les tests dépendent de jointures ou de comparaisons, et elles ne doivent pas produire d’erreurs contenant la valeur d’origine.

Le masquage d’une colonne visible ne masque pas les métadonnées. Les comptes, les noms de tables, les tailles de lots, les identifiants séquentiels et les messages d’erreur peuvent révéler des informations métier. Les accès anonymes aux annuaires ou aux métadonnées restent une source de cartographie très rentable, comme le montre l’analyse des métadonnées LDAP anonymes.

La première attaque est le contournement par chemin direct : connexion avec un compte technique, réplica en lecture, sauvegarde, export d’administration ou connecteur analytique. La contre-mesure n’est pas un masque plus sophistiqué. Il faut interdire les privilèges directs, inventorier les connecteurs, isoler les comptes de sauvegarde et vérifier les droits effectifs, héritage compris.

La seconde attaque est l’inférence. Une requête COUNT(*), un filtre sur une valeur masquée ou une agrégation peut révéler l’information cachée. Si une vue masque un salaire mais autorise WHERE salaire > 120000, elle fournit un oracle de comparaison. Filtrer, trier, grouper et joindre sur une colonne sensible doivent être interdits ou exécutés sur une valeur pseudonymisée distincte selon le besoin métier.

La troisième attaque est l’exfiltration par l’application. Une interface peut masquer l’écran tout en retournant la réponse complète dans une interface de programmation, un journal de débogage ou une trace distribuée. Le masquage doit être testé sur la réponse réseau réelle, les erreurs et les journaux, pas seulement sur la capture d’écran qui rassure la démonstration commerciale.

La quatrième attaque vient des identités. Un jeton de service réutilisé entre production et recette détruit toute séparation logique. Les comptes humains doivent être nominatifs, les comptes machines limités à une application et les sessions courtes. La fédération d’identité peut porter les attributs nécessaires à la politique, mais elle ne corrige pas des droits de base de données trop larges. Un fournisseur d’identité ne transforme pas GRANT SELECT ON * en bonne idée par simple proximité géographique.

Le masque est une politique de sécurité, donc il doit être versionné, testé et supervisé. Chaque règle doit indiquer la colonne concernée, le type de transformation, les rôles autorisés, le propriétaire fonctionnel et la date de révision. Les tests automatisés doivent vérifier deux propriétés : un rôle non autorisé ne reçoit jamais la valeur brute, et un rôle autorisé conserve les comportements applicatifs attendus.

La rotation de la clé utilisée pour la pseudonymisation déterministe crée une rupture de cohérence. Après rotation, la même personne obtient une nouvelle valeur transformée. Si des jeux de test ou des tickets de support conservent les anciennes valeurs, il faut soit accepter cette rupture, soit maintenir temporairement plusieurs versions de pseudonymes avec un marquage explicite. Garder indéfiniment toutes les clés de masquage revient à construire une collection de dettes cryptographiques, avec étiquettes et poussière.

Les journaux doivent enregistrer l’identité, la ressource, la règle appliquée, le volume retourné et le refus éventuel. Ils ne doivent jamais enregistrer la valeur avant ou après masquage. Une journalisation qui conserve les données cachées est un masque posé sur une porte ouverte.

La sauvegarde doit inclure les définitions de vues, les politiques, les rôles et les références de clés, sans embarquer les clés elles-mêmes. La reprise doit restaurer ces objets dans un ordre déterminé : schémas, tables, fonctions, politiques, rôles, privilèges. Restaurer les tables avant les contrôles crée une fenêtre où les données sont brutes et accessibles. Cette fenêtre sera toujours découverte par le script qui tourne à l’heure où la supervision dort.

Sans masquage dynamique, les environnements de test et de développement reçoivent la production telle quelle, avec ses données personnelles exposées à chaque intervenant, interne ou externe. La valeur sensible reste visible pour qui consulte le dossier alors que la tâche ne l’exige pas, et chaque copie vers un environnement moins protégé multiplie les endroits où elle peut fuir. L’absence de transformation à la lecture selon l’identité signifie donc que le périmètre des personnes voyant des données réelles s’élargit bien au-delà de ceux qui en ont besoin, sans traçabilité de qui a vu quoi. Le masquage n’étant ni une anonymisation ni un droit de dupliquer la production partout, son absence laisse justement s’installer cette duplication : des jeux de données réels s’accumulent dans des environnements où ils n’ont aucune raison d’être, chacun devenant une fuite potentielle.

Le masquage dynamique garde les vraies données dans la base, mais décide de ce qui est montré au moment où une personne ou un programme demande une information. La décision dépend de son identité, de son rôle et parfois du contexte de la demande. Une personne chargée de tester une application peut voir un nom raccourci, une adresse modifiée et une date moins précise. Une personne autorisée pour une enquête précise peut voir davantage, si la règle le permet.

Pour que cela fonctionne, les comptes de test ne doivent pas pouvoir lire les tables contenant les valeurs originales. Ils doivent passer par une vue, une interface ou un autre point d’accès qui applique le masquage. Si un compte possède aussi un accès direct, une sauvegarde ou un export complet, le masquage ne sert plus à grand-chose.

Certaines valeurs doivent rester cohérentes. Par exemple, la même personne doit parfois garder le même faux identifiant dans plusieurs écrans. Dans ce cas, le système calcule toujours le même remplacement à partir d’une clé secrète. Cette clé doit être protégée et changée avec précaution, car son changement peut modifier tous les faux identifiants.

Le système doit aussi surveiller les recherches, les tris et les journaux. Même sans afficher une donnée, une recherche peut révéler une réponse. En cas d’échec du masque ou d’accès non prévu, la règle correcte est de refuser la lecture, pas de montrer la donnée originale.

À lire aussi

Pages voisines