Dans les articles sur les accès et les rôles système, on a vu comment structurer les droits avec des rôles. Sauf qu'on n'a jamais posé en clair le modèle sur lequel tout ça repose.

Quand tu fais un GRANT SELECT ... TO ROLE ..., c'est du RBAC. Quand le rôle qui a créé une table décide qui peut y accéder, c'est du DAC. Et Snowflake utilise les deux en même temps.

DAC + RBAC : le modèle de contrôle d'accès de Snowflake

Snowflake combine deux modèles :

RBAC (Role-Based Access Control) : C'est tout ce qu'on a vu dans l'article sur les accès. Les privilèges sont donnés à des rôles, et les rôles sont donnés ensuite aux utilisateurs. Donc on ne donne jamais un droit explicitement à un user mais plutôt à un rôle, et ensuite on attribue le rôle au user.

DAC (Discretionary Access Control) : C'est un modèle où le propriétaire d'un objet décide qui peut y accéder. Dans Snowflake, chaque objet (table, vue, schéma, base...) a un rôle propriétaire, c'est le rôle qui a créé l'objet. Et c'est ce rôle (ou un rôle parent dans la hiérarchie) qui peut accorder ou révoquer les privilèges dessus.

💡
Le RBAC structure les droits via les rôles. Le DAC donne au propriétaire d'un objet le contrôle sur qui peut y accéder.

Concrètement, ça donne quoi ?

Prenons un exemple. Le rôle DATA_ENGINEER crée une table :

USE ROLE DATA_ENGINEER;

CREATE TABLE ANALYTICS_DB.RAW.EVENTS (
  EVENT_ID   NUMBER,
  EVENT_TYPE STRING,
  CREATED_AT TIMESTAMP
);

À ce stade, DATA_ENGINEER est le propriétaire de la table EVENTS. Si un autre rôle comme FINANCE_ANALYST essaye de lire cette table, il n'y aura pas accès, même s'il a USAGE sur la base et le schéma.

Pour lui donner accès, il faut que le propriétaire (ou un rôle parent) accorde le droit explicitement :

-- Le propriétaire DATA_ENGINEER accorde le SELECT
GRANT SELECT ON TABLE ANALYTICS_DB.RAW.EVENTS TO ROLE FINANCE_ANALYST;

C'est ça le DAC car le propriétaire (ou un rôle parent) décide.

Vérifier le propriétaire d'un objet

-- Voir qui possède une table
SHOW GRANTS ON TABLE ANALYTICS_DB.RAW.EVENTS;

Dans la colonne privilege, tu verras une ligne avec OWNERSHIP et le rôle propriétaire.

Vérifier le propriétaire d'un objet
Vérifier le propriétaire d'un objet

Transférer la propriété

Parfois un objet est créé avec un rôle qui ne devrait pas être propriétaire. Par exemple, quelqu'un crée une table avec ACCOUNTADMIN par erreur. Tu peux transférer la propriété comme suit :

GRANT OWNERSHIP ON TABLE ANALYTICS_DB.RAW.EVENTS
  TO ROLE DATA_ENGINEER
  REVOKE CURRENT GRANTS;

REVOKE CURRENT GRANTS retire les grants existants au passage. Si tu veux les garder, utilise COPY CURRENT GRANTS.

GRANT OWNERSHIP ON TABLE ANALYTICS_DB.RAW.EVENTS
  TO ROLE DATA_ENGINEER
  COPY CURRENT GRANTS;

Le piège classique avec le DAC

⚠️
C'est un cas très fréquent et c'est lorsque un utilisateur crée une table avec un nouveau rôle qui n'est rattaché à rien dans la hiérarchie. Et donc comme résultat, personne d'autre ne peut y accéder, même pas SYSADMIN.

C'est exactement pour cette raison qu'il est recommandé de toujours rattacher les nouveaux rôles à SYSADMIN et ne jamais laisser de rôle orphelin.

-- Rattacher le rôle pour éviter d'avoir un rôle orphelin
GRANT ROLE DATA_ENGINEER TO ROLE SYSADMIN;

Secondary Roles : utiliser plusieurs rôles en même temps

Par défaut dans Snowflake, un utilisateur a un seul rôle actif à la fois. Si tu es FINANCE_ANALYST et que tu veux accéder à une table qui nécessite le rôle MARKETING_READ, tu dois faire un USE ROLE. Mais tu perds alors tes droits FINANCE_ANALYST.

C'est un problème qu'on rencontre rapidement en pratique. Et les Secondary Roles le résolvent.

Exemple sans secondary roles

USE ROLE FINANCE_ANALYST;

-- OK : on a le droit
SELECT * FROM FINANCE_DB.MART_FINANCE.REVENUE;

-- ERREUR : on n'a pas le droit avec ce rôle
SELECT * FROM MARKETING_DB.MART_MARKETING.CAMPAIGNS;

-- Il faut switcher
USE ROLE MARKETING_READ;

-- OK maintenant
SELECT * FROM MARKETING_DB.MART_MARKETING.CAMPAIGNS;

-- Mais on a perdu l'accès finance
SELECT * FROM FINANCE_DB.MART_FINANCE.REVENUE;  -- ERREUR

Exemple avec secondary roles : tout d'un coup

USE ROLE FINANCE_ANALYST;
USE SECONDARY ROLES ALL;

-- OK
SELECT * FROM FINANCE_DB.MART_FINANCE.REVENUE;

-- OK aussi, grâce aux secondary roles
SELECT * FROM MARKETING_DB.MART_MARKETING.CAMPAIGNS;
💡
Avec USE SECONDARY ROLES ALL, l'utilisateur hérite des privilèges de tous les rôles qui lui sont assignés, en plus de son rôle actif. Plus besoin de switcher.

Désactiver les secondary roles

USE SECONDARY ROLES NONE;

Le comportement redevient celui par défaut avec un seul rôle actif.

Configurer les secondary roles par défaut pour un utilisateur

Pour éviter par exemple qu'un utilisateur fait la manip USE SECONDARY ROLES ALL à chaque connexion

USE ROLE SECURITYADMIN;

ALTER USER alice_toto SET DEFAULT_SECONDARY_ROLES = ('ALL');

À partir de là, les secondary roles sont activés automatiquement à chaque connexion pour cet utilisateur.

Le point subtil : OWNERSHIP et CURRENT_ROLE

Les secondary roles donnent accès aux privilèges de tous les rôles. Mais le rôle actif (CURRENT_ROLE) reste celui défini par USE ROLE. Et c'est ce CURRENT_ROLE qui détermine le propriétaire (OWNERSHIP) quand tu crées un objet.

USE ROLE FINANCE_ANALYST;
USE SECONDARY ROLES ALL;

-- Cette table sera créée avec FINANCE_ANALYST comme propriétaire
-- (pas MARKETING_READ, même si ses privilèges sont actifs)
CREATE TABLE FINANCE_DB.MART_FINANCE.TEST (ID NUMBER);

Vérifier les rôles actifs

-- Le rôle principal
SELECT CURRENT_ROLE();

-- Tous les rôles secondaires actifs
SELECT CURRENT_SECONDARY_ROLES();

Aller plus loin : Formation Snowflake

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

👉 Formation Snowflake : tous les modules pas à pas

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