Le RBAC Snowflake échoue rarement parce qu'il manque des rôles. Il échoue parce qu'il y en a trop, et que personne ne sait qui a accès à quoi.
La checklist
- Moins de 20 Functional Roles (profils métier) au total
- Aucun
GRANTdirect aux utilisateurs - Tous les rôles suffixés par leur environnement (
_DEV,_PRD,_RCT) ACCOUNTADMINréservé aux opérations exceptionnelles- Future Grants configurés sur les schémas critiques
- 100% des rôles définis dans Terraform
- Audit d'accès possible en moins de 5 minutes
- Managed Access Schemas sur les zones sensibles
Le modèle à adopter
Le modèle fonctionne en trois couches :
- Functional Roles : profils métier (
FR_DATA_ENGINEER_DEV) - Access Roles : privilèges techniques (
AR_BRZ_RAW_READ_DEV) - Utilisateurs : un seul Functional Role, héritant de N Access Roles

Implémentation : les 3 couches
1. Access Roles — la couche technique
Les Access Roles portent uniquement des privilèges techniques sur des objets. Ils ne sont jamais assignés directement à un utilisateur.
-- Lecture sur les tables brutes du bronze
CREATE ROLE AR_BRZ_RAW_READ_DEV;
GRANT USAGE ON DATABASE BRONZE_DEV TO ROLE AR_BRZ_RAW_READ_DEV;
GRANT USAGE ON SCHEMA BRONZE_DEV.RAW TO ROLE AR_BRZ_RAW_READ_DEV;
GRANT SELECT ON ALL TABLES IN SCHEMA BRONZE_DEV.RAW
TO ROLE AR_BRZ_RAW_READ_DEV;
-- Écriture dans le silver (Data Engineer uniquement)
CREATE ROLE AR_SLV_AGGREGATE_WRITE_DEV;
GRANT USAGE ON DATABASE SILVER_DEV TO ROLE AR_SLV_AGGREGATE_WRITE_DEV;
GRANT USAGE ON SCHEMA SILVER_DEV.AGGREGATE TO ROLE AR_SLV_AGGREGATE_WRITE_DEV;
GRANT SELECT, INSERT, UPDATE, DELETE
ON ALL TABLES IN SCHEMA SILVER_DEV.AGGREGATE
TO ROLE AR_SLV_AGGREGATE_WRITE_DEV;
Convention de nommage : AR_<SCHEMA>_<OBJET>_<PRIVILEGE>_<ENV>.
2. Future Grants — automatiser les nouveaux objets
Sans Future Grants, chaque nouvelle table créée doit être GRANT-ée à la main. Avec, Snowflake applique automatiquement les privilèges à tout futur objet du schéma.
-- Toute nouvelle table du bronze sera lisible par AR_BRZ_RAW_READ_DEV
GRANT SELECT ON FUTURE TABLES IN SCHEMA BRONZE_DEV.RAW
TO ROLE AR_BRZ_RAW_READ_DEV;
-- Idem pour les vues
GRANT SELECT ON FUTURE VIEWS IN SCHEMA BRONZE_DEV.RAW
TO ROLE AR_BRZ_RAW_READ_DEV;
-- Toute nouvelle table du silver sera insérable par AR_SLV_AGGREGATE_WRITE_DEV
GRANT SELECT, INSERT, UPDATE, DELETE
ON FUTURE TABLES IN SCHEMA SILVER_DEV.AGGREGATE
TO ROLE AR_SLV_AGGREGATE_WRITE_DEV;
3. Functional Roles — la couche métier
Les Functional Roles représentent des profils métier : un Data Engineer n'a pas les mêmes accès qu'un Analyste. Ils héritent des Access Roles, jamais l'inverse.
CREATE ROLE FR_DATA_ENGINEER_DEV;
CREATE ROLE FR_DATA_ANALYST_DEV;
-- Data Engineer : lecture bronze + écriture silver + lecture gold
GRANT ROLE AR_BRZ_RAW_READ_DEV TO ROLE FR_DATA_ENGINEER_DEV;
GRANT ROLE AR_SLV_AGGREGATE_WRITE_DEV TO ROLE FR_DATA_ENGINEER_DEV;
GRANT ROLE AR_GLD_REPORT_READ_DEV TO ROLE FR_DATA_ENGINEER_DEV;
-- Analyste : lecture seule sur gold (pas d'accès au bronze)
GRANT ROLE AR_GLD_REPORT_READ_DEV TO ROLE FR_DATA_ANALYST_DEV;
Convention : FR_<PROFIL>_<ENV>. Un Data Engineer DEV ne doit jamais hériter de droits d'un Data Engineer PRD.
4. Assignation à l'utilisateur
L'utilisateur reçoit un seul Functional Role. Snowflake résout la chaîne d'héritage automatiquement.
-- ✅ Bon : un seul rôle, héritage automatique
GRANT ROLE FR_DATA_ENGINEER_DEV TO USER mikael.paulhiout;
GRANT ROLE FR_DATA_ANALYST_DEV TO USER alice.duval;
-- ⛔ Mauvais : grants directs sur la personne = impossible à auditer
GRANT SELECT ON TABLE BRONZE_DEV.RAW.SALES
TO USER mikael.paulhiout; -- 🚫 à proscrire
Pour qu'un utilisateur puisse se connecter, il faut aussi lui donner un rôle par défaut :
ALTER USER mikael.paulhiout
SET DEFAULT_ROLE = FR_DATA_ENGINEER_DEV;
Architecture enterprise
Pour les plateformes à fort volume, ajouter :
- Database Roles : gouvernance par domaine (un rôle par domaine métier, transverse aux schémas)
- Managed Access Schemas : empêchent les propriétaires de tables d'accorder des droits arbitraires
- Future Grants : automatisation des nouveaux objets (voir ci-dessus)
- Terraform : versionning et audit complet
Managed Access Schema en SQL
-- Par défaut, le propriétaire d'un schéma peut GRANT à qui il veut.
-- En Managed Access, seul le propriétaire du schéma (souvent un rôle de plateforme)
-- peut accorder des droits, pas le propriétaire de la table.
ALTER SCHEMA SILVER_DEV.AGGREGATE
SET MANAGED ACCESS;
Après ça, seul SYSADMIN (ou un rôle technique avec OWNERSHIP sur le schéma) peut faire des GRANT dans ce schéma. Les CREATE TABLE continuent de fonctionner, mais le créateur de la table n'en devient pas propriétaire.
Database Roles pour la gouvernance transverse
-- Un Database Role "DATA_ENGINEER" portable cross-database
CREATE DATABASE ROLE ANALYTICS_DEV.DR_DATA_ENGINEER;
-- Grant sur tous les warehouses techniques
GRANT USAGE ON WAREHOUSE DEV_DEN_WH
TO DATABASE ROLE ANALYTICS_DEV.DR_DATA_ENGINEER;
-- Un seul grant à faire évoluer quand un nouveau domaine est ajouté
GRANT DATABASE ROLE ANALYTICS_DEV.DR_DATA_ENGINEER
TO ROLE FR_DATA_ENGINEER_DEV;
Tout cela en Terraform
# access_role.tf
resource "snowflake_role" "ar_brz_raw_read_dev" {
name = "AR_BRZ_RAW_READ_DEV"
}
resource "snowflake_grant_privileges_to_role" "ar_brz_raw_read_dev" {
role_name = snowflake_role.ar_brz_raw_read_dev.name
on_schema_object {
future {
object_type_plural = "TABLES"
in_schema = "BRONZE_DEV.RAW"
}
privileges = ["SELECT"]
}
}
# functional_role.tf
resource "snowflake_role" "fr_data_engineer_dev" {
name = "FR_DATA_ENGINEER_DEV"
}
resource "snowflake_role_grants" "fr_data_engineer_dev" {
role_name = snowflake_role.fr_data_engineer_dev.name
roles = [
snowflake_role.ar_brz_raw_read_dev.name,
snowflake_role.AR_SLV_AGGREGATE_write_dev.name,
snowflake_role.ar_gld_report_read_dev.name,
]
}
terraform plan devient votre audit d'accès. Un git log vous dit qui a changé quoi et quand.
Le payoff
Le RBAC n'est pas une contrainte. C'est ce qui permet à votre plateforme de scaler : ajouter un nouveau domaine = créer un nouveau schéma + un Access Role, jamais de GRANT à la main. Et le jour où l'audit SOC2 demande "qui a accès à quoi ?", la réponse tient en une requête.