Dans l'article précédent sur les droits d'accès, on a posé les bases de la gestion des accès.
Sauf qu'en vrai, tôt ou tard tu tombes sur ce cas :
- Tu veux laisser
SELECTsur une table mais tu ne veux pas que tout le monde voie l'email, le téléphone, l'IBAN, le salaire, etc.
C'est là que le masquage dynamique (Dynamic Data Masking) entre en jeu et règle cette problématique.
Nb : c'est une fonctionnalité qui est disponible que dans l'edition Enterprise (ou +)
Le modèle à retenir
C'est simple, tu as deux couches :
- Droits d'accès : “est-ce que tu as le droit de lire l'objet ?”
- Masking : “ok tu lis la table… mais qu'est-ce que tu as le droit de voir la colonne des salaires ?”
Nb : Snowflake ne modifie pas la donnée stockée. Il réécrit la requête “à la volée” au moment du SELECT, en appliquant la policy.
Exemple complet
Comme d'habitude dans les articles de la formation, y'a pas mieux d'un exemple pour comprendre le concept. On reprend le même exemple que l'article des accès avec un rôle d'accès en lecture, et un rôle spécial pour voir les données sensibles.
- Table :
FINANCE_DB.MART_FINANCE.EMPLOYEES - Schéma des policies :
FINANCE_DB.SECURITY - Rôles :
FINANCE_ANALYST: peut voir la table, mais pas les colonnes masquéesPAYROLL_PII: peut tout voirMASKING_ADMIN: Admin qui peut créer et appliquer les policies
1) Table de test
CREATE DATABASE IF NOT EXISTS FINANCE_DB;
CREATE SCHEMA IF NOT EXISTS FINANCE_DB.MART_FINANCE;
CREATE OR REPLACE TABLE FINANCE_DB.MART_FINANCE.EMPLOYEES (
EMP_ID NUMBER,
FULL_NAME STRING,
EMAIL STRING,
IBAN STRING,
SALARY NUMBER
);
INSERT INTO FINANCE_DB.MART_FINANCE.EMPLOYEES VALUES
(1, 'Alice Martin', 'alice.martin@corp.com', 'FR7630006000011234567890189', 85000),
(2, 'Sam Dupont', 'sam.dupont@corp.com', 'FR7612345987650000000000123', 62000);
2) Rôles
USE ROLE USERADMIN;
CREATE ROLE IF NOT EXISTS FINANCE_ANALYST;
CREATE ROLE IF NOT EXISTS PAYROLL_PII;
CREATE ROLE IF NOT EXISTS MASKING_ADMIN;
Donner le droit de lecture à l'analyst :
USE ROLE SECURITYADMIN;
GRANT USAGE ON DATABASE FINANCE_DB TO ROLE FINANCE_ANALYST;
GRANT USAGE ON SCHEMA FINANCE_DB.MART_FINANCE TO ROLE FINANCE_ANALYST;
GRANT SELECT ON TABLE FINANCE_DB.MART_FINANCE.EMPLOYEES TO ROLE FINANCE_ANALYST;
3) Créer un schéma “SECURITY” pour les policies
USE ROLE SECURITYADMIN;
CREATE SCHEMA IF NOT EXISTS FINANCE_DB.SECURITY;
GRANT USAGE ON DATABASE FINANCE_DB TO ROLE MASKING_ADMIN;
GRANT USAGE ON SCHEMA FINANCE_DB.SECURITY TO ROLE MASKING_ADMIN;
GRANT CREATE MASKING POLICY ON SCHEMA FINANCE_DB.SECURITY TO ROLE MASKING_ADMIN;
GRANT APPLY MASKING POLICY ON ACCOUNT TO ROLE MASKING_ADMIN;
4) Créer les masking policies
Pour faire simple, on partira du principe que :
- si tu as le rôle
PAYROLL_PII→ accès à tout les champs en clair - sinon → masquer les champs sensibles
Petite astuce : IS_ROLE_IN_SESSION('...') évite pas mal de surprises quand tu as des rôles “parents/enfants”.Email (partiel)
USE ROLE MASKING_ADMIN;
CREATE OR REPLACE MASKING POLICY FINANCE_DB.SECURITY.MASK_EMAIL
AS (val STRING) RETURNS STRING ->
CASE
WHEN val IS NULL THEN NULL
WHEN IS_ROLE_IN_SESSION('PAYROLL_PII') THEN val
ELSE REGEXP_REPLACE(val, '(^.).*(@.*$)', '\\1***\\2')
END;
IBAN (garder les 4 derniers)
CREATE OR REPLACE MASKING POLICY FINANCE_DB.SECURITY.MASK_IBAN
AS (val STRING) RETURNS STRING ->
CASE
WHEN val IS NULL THEN NULL
WHEN IS_ROLE_IN_SESSION('PAYROLL_PII') THEN val
ELSE CONCAT('**** **** **** **** ', RIGHT(val, 4))
END;
Salaire (NULL)
CREATE OR REPLACE MASKING POLICY FINANCE_DB.SECURITY.MASK_SALARY
AS (val NUMBER) RETURNS NUMBER ->
CASE
WHEN val IS NULL THEN NULL
WHEN IS_ROLE_IN_SESSION('PAYROLL_PII') THEN val
ELSE NULL
END;
5) Appliquer les policies sur les colonnes
USE ROLE MASKING_ADMIN;
ALTER TABLE FINANCE_DB.MART_FINANCE.EMPLOYEES
ALTER COLUMN EMAIL SET MASKING POLICY FINANCE_DB.SECURITY.MASK_EMAIL;
ALTER TABLE FINANCE_DB.MART_FINANCE.EMPLOYEES
ALTER COLUMN IBAN SET MASKING POLICY FINANCE_DB.SECURITY.MASK_IBAN;
ALTER TABLE FINANCE_DB.MART_FINANCE.EMPLOYEES
ALTER COLUMN SALARY SET MASKING POLICY FINANCE_DB.SECURITY.MASK_SALARY;
6) Tester les policies
En mode analyst
USE ROLE FINANCE_ANALYST;
SELECT EMP_ID, FULL_NAME, EMAIL, IBAN, SALARY
FROM FINANCE_DB.MART_FINANCE.PAYROLL_EMPLOYEES;
On peut voir :
- Email masqué (
a***@corp.com) - Iban masqué (avec juste les 4 derniers)
- Salary =
NULL

Avec le rôle PII
USE ROLE PAYROLL_PII;
SELECT EMP_ID, FULL_NAME, EMAIL, IBAN, SALARY
FROM FINANCE_DB.MART_FINANCE.PAYROLL_EMPLOYEES;
Là tu vois tout en clair.

Aller plus loin : Formation Snowflake
J'ai regroupé tous mes articles Snowflake dans un parcours complet.
👉 Accéder à la Formation Snowflake
Vous voulez que je vous accompagne sur votre projet data (Snowflake, ingestion, modélisation, performance, coûts, gouvernance) ?
👉 Réserver un appel de 30 minutes

