> ## Content Index
> Fetch the complete content index at: https://www.idriss-benbassou.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Masquage dynamique Snowflake : protéger les données PII
- URL: https://www.idriss-benbassou.com/masquage-dynamique-snowflake-securiser-les-colonnes-pii/
- Published: 2025-12-16T20:12:26.000Z
- Updated: 2025-12-22T11:48:30.000Z
- Author: Idriss BENBASSOU
- Tags: Snowflake, #rating-2

Dans l'article précédent sur [les droits d'accès](https://www.idriss-benbassou.com/users-acces-snowflake-roles-droits-et-erreurs-a-eviter/), 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 un `SELECT` sur une table mais tu ne veux pas que tout le monde voie les données sensibles ou personnelles comme 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 :

1. **Droits d'accès** : “est-ce que tu as le droit de lire l'objet ?”
2. **Masking** : “ok tu lis la table… mais qu'est-ce que tu as le droit de voir toutes les colonnes ?”

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ées
  - `PAYROLL_PII` : peut tout voir
  - `MASKING_ADMIN` : Admin qui peut créer et appliquer les policies

### 1) Table de test des employés

```sql
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

```sql
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 :

```sql
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

```sql
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)

```sql
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)

```sql
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)

```sql
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

```sql
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**

```sql
USE ROLE FINANCE_ANALYST;

SELECT EMP_ID, FULL_NAME, EMAIL, IBAN, SALARY
FROM FINANCE_DB.MART_FINANCE.EMPLOYEES;

```

On peut voir :

- Email masqué (`a***@corp.com`)
- Iban masqué (avec juste les 4 derniers)
- Salary = `NULL`

![](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2025/12/Capture-d---e--cran-2025-12-16-a---20.42.35.png)

**Avec le rôle PII**

```sql
USE ROLE PAYROLL_PII;

SELECT EMP_ID, FULL_NAME, EMAIL, IBAN, SALARY
FROM FINANCE_DB.MART_FINANCE.EMPLOYEES;

```

Là tu vois tout en clair.

![](https://storage.ghost.io/c/60/f1/60f18be4-df79-4956-8e4a-c2fa80212e93/content/images/2025/12/Capture-d---e--cran-2025-12-16-a---20.46.44.png)

****Avec le rôle PII**

## Aller plus loin : Formation Snowflake

J'ai regroupé tous mes articles Snowflake dans un parcours complet.

👉 [Accéder à la Formation Snowflake](https://www.idriss-benbassou.com/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](https://calendly.com/idriss-benbassou-datavio/30min?ref=idriss-benbassou.com)