Aller au contenu

ReBAC Zanzibar pour les autorisations relationnelles fines

ReBAC Zanzibar pour les autorisations relationnelles fines

Section intitulée « ReBAC Zanzibar pour les autorisations relationnelles fines »

Le contrôle d’accès par relations, ou ReBAC (Relationship-Based Access Control), traite les autorisations comme un graphe de liens entre identités, ressources et conteneurs. C’est le bon choix quand les droits dépendent d’une chaîne de partage réelle, pas d’un rôle plaqué sur une organisation qui change tous les matins.

→ Lire l’explication complète de la marmotte

RBAC, ABAC et l’explosion combinatoire des rôles

Section intitulée « RBAC, ABAC et l’explosion combinatoire des rôles »

Le RBAC (Role-Based Access Control) associe une identité à un rôle, puis un rôle à des permissions. Il reste excellent pour des privilèges stables et transverses : administrateur de plateforme, opérateur de sauvegarde, lecteur de journaux. Une matrice rôle-permission se relit, s’exporte et se recertifie sans convoquer un graphe de théorie des ensembles au comité d’audit.

Il échoue lorsque le droit dépend simultanément de l’appartenance à une équipe, d’un partage explicite, de la hiérarchie d’un dossier, de l’organisation cliente et du statut du document. Créer les rôles lecteur-client-A-équipe-X, lecteur-client-A-équipe-Y, puis leurs variantes éditeur, propriétaire et invité, transforme le référentiel en générateur de mots de passe pour imprimante. Chaque nouvelle combinaison métier devient un rôle, chaque exception devient un autre rôle, et l’audit ne sait plus expliquer pourquoi il existe.

L’ABAC (Attribute-Based Access Control) évalue des attributs, par exemple department=finance, tenant=acme ou classification=internal, contre une politique. Il réduit les rôles lorsque les règles découlent de propriétés objectives et assez stables. En revanche, encoder « membre de l’équipe qui gère le dossier parent partagé avec le client du projet » dans des attributs impose soit de recopier des données relationnelles, soit de joindre plusieurs sources pendant la décision. Le premier choix crée de la dérive, le second transforme le point de décision en moteur de requêtes distribuées.

ReBAC représente directement ce qui compte : Alice est membre de l’équipe Alpha, Alpha est collaboratrice du dossier Delta, Delta contient le document Contrat-7. La permission résulte de relations nommées, pas d’un rôle combinatoire. Le compromis central est net : on gagne une granularité naturelle, des partages explicables et une délégation locale ; on paie un modèle à concevoir, un graphe à maintenir cohérent et des vérifications potentiellement plus coûteuses.

La recommandation est de conserver RBAC pour les privilèges d’administration de la plateforme et d’adopter ReBAC pour les ressources dont les droits suivent des relations métier variables. Mélanger les deux est normal. Faire de ReBAC le moteur de chaque autorisation d’interface, y compris l’accès à une page de préférences, est une façon coûteuse de démontrer qu’un graphe sait marcher.

Les principes de gouvernance des identités restent applicables : une relation donne un droit, elle doit donc avoir un propriétaire, une source d’autorité et une règle de suppression. ReBAC ne transforme pas un annuaire incomplet en vérité métier.

Un tuple relationnel est un triplet sujet#relation@objet : user:alice#member@team:alpha, selon une notation lisible, signifie qu’Alice est membre d’Alpha. Les implémentations de type Zanzibar stockent généralement cette information sous une forme voisine de user:alice member team:alpha. Le sujet peut être un utilisateur, un groupe, un compte de service ou un ensemble d’utilisateurs défini par une relation.

Le modèle de schéma définit les types d’objet, les relations directes et les permissions calculées. Une relation directe est écrite dans le graphe, par exemple team:alpha#member@user:alice. Une permission calculée est dérivée, par exemple document:contrat-7#viewer si l’utilisateur est membre de l’équipe éditrice du dossier parent, ou s’il a reçu un partage direct.

La résolution parcourt le graphe à partir de la question : « Alice peut-elle lire Contrat-7 ? ». Le moteur recherche d’abord un tuple direct user:alice viewer document:contrat-7, puis les relations définies par le schéma. Il peut suivre document -> parent_folder -> viewer, puis folder -> collaborator -> team -> member. Les unions ajoutent des chemins possibles, les intersections imposent plusieurs conditions, les exclusions retirent des sujets. Les exclusions méritent une suspicion méthodique : elles compliquent les preuves d’accès et créent des effets de bord lors d’une délégation.

Le modèle doit limiter la profondeur de parcours, interdire les cycles non maîtrisés et prévoir des index sur les objets, relations et sujets. Une requête de vérification ne doit pas déclencher une exploration non bornée parce qu’un groupe contient un groupe qui contient un groupe, jusqu’à la disparition thermique de l’univers. Les moteurs sérieux imposent une profondeur maximale, mais cette limite ne remplace pas un schéma sans récursion accidentelle.

Les relations d’autorisation ne remplacent pas l’authentification. Un jeton d’identité falsifié, volé ou émis pour le mauvais locataire rend toute décision ReBAC irréprochable et tout de même désastreuse. La fédération, la durée de vie des sessions, l’authentification multifacteur et la séparation des comptes de service restent des dépendances de sécurité, pas des détails périphériques. Les faiblesses des protocoles historiques, telles que celles documentées pour NTLM, ne deviennent pas moins graves parce que la dernière étape utilise un joli graphe.

Une vérification d’autorisation doit répondre sur un état identifiable du graphe. Sans cela, une lecture peut voir l’ajout d’un partage mais pas sa suppression liée, ou l’inverse. Le risque n’est pas théorique : une révocation peut être acceptée par le service qui écrit la relation alors qu’un service qui contrôle l’accès lit encore une réplique ancienne.

Google Zanzibar associe les écritures à une révision du magasin de données et retourne un jeton de cohérence, souvent nommé zookie. Un service conserve ce jeton après une modification ou une vérification, puis l’envoie à la vérification suivante pour exiger une lecture au moins aussi récente. Le résultat évite le phénomène de « nouveau problème », où un droit supprimé semble réapparaître parce que deux lectures consultent des états incompatibles.

Tous les moteurs inspirés de Zanzibar n’offrent pas les mêmes garanties ni les mêmes noms d’option. Il faut donc documenter le contrat exact : cohérence forte, cohérence à terme, lecture au moins aussi récente, ou lecture à une révision précise. Une option appelée fully_consistent sur une plaquette ne garantit rien si le stockage des tuples, le cache d’autorisation et le cache applicatif n’obéissent pas au même horizon de fraîcheur.

Après une révocation critique, deux règles s’imposent :

  1. invalider ou borner les caches de décision par version de graphe, jamais seulement par durée arbitraire ;
  2. réévaluer les sessions qui portent des autorisations matérialisées, car supprimer un tuple ne retire pas un document déjà téléchargé ni une clé déjà délivrée.

Un zookie ne résout ni l’exfiltration antérieure ni les copies locales. Il garantit une cohérence de décision, pas une gomme temporelle. Pour les documents sensibles, la révocation doit s’accompagner de chiffrement par objet, de contrôle de téléchargement, de journalisation et, selon le risque, d’une rotation de clé. La cryptographie appliquée protège les données au repos ou en transit, mais ne décide pas qui mérite la clé.

Exemple de modèle ReBAC pour un partage documentaire

Section intitulée « Exemple de modèle ReBAC pour un partage documentaire »

Le schéma suivant peut être chargé dans OpenFGA, une implémentation libre d’un modèle de relations inspiré de Zanzibar. Il sépare le rôle administratif global, qui resterait dans RBAC, des droits sur les documents partagés.

{
"schema_version": "1.1",
"type_definitions": [
{
"type": "user",
"relations": {},
"metadata": null
},
{
"type": "team",
"relations": {
"member": { "this": {} }
},
"metadata": null
},
{
"type": "folder",
"relations": {
"collaborator": { "this": {} },
"viewer": {
"union": {
"child": [
{ "this": {} },
{ "computedUserset": { "relation": "collaborator" } }
]
}
}
},
"metadata": null
},
{
"type": "document",
"relations": {
"parent": { "this": {} },
"viewer": {
"union": {
"child": [
{ "this": {} },
{
"tupleToUserset": {
"tupleset": { "relation": "parent" },
"computedUserset": { "relation": "viewer" }
}
}
]
}
}
},
"metadata": null
}
]
}

Avec les tuples user:alice member team:alpha, team:alpha collaborator folder:client-acme et folder:client-acme parent document:contrat-7, la permission doit exprimer explicitement la traversée équipe vers dossier. Le schéma ci-dessus mérite donc une attention : collaborator accepte un sujet direct, mais ne déduit pas automatiquement les membres d’une équipe. Il faut soit définir une relation de type ensemble d’utilisateurs, soit écrire les collaborateurs individuels. Cette distinction est l’erreur classique : croire que le moteur infère une sémantique métier absente du schéma.

Tester les autorisations avec des cas positifs et négatifs versionnés est obligatoire. Un test doit couvrir le partage direct, l’héritage depuis le dossier, la suppression du tuple, le changement de locataire et les relations interdites. Une politique non testée est une phrase ambitieuse stockée dans un dépôt.

Surface d’attaque et exploitation du graphe d’autorisation

Section intitulée « Surface d’attaque et exploitation du graphe d’autorisation »

Le premier risque est l’escalade par écriture de tuples. Si un utilisateur peut créer member sur une équipe ou collaborator sur un dossier sans contrôle séparé, il peut se donner le droit de lecture. L’autorisation d’écrire chaque relation doit être évaluée hors de la relation qu’elle confère, idéalement par une permission d’administration distincte et limitée au tenant concerné.

Le second risque est la confusion inter-tenant. Tout identifiant d’objet doit être rattaché au locataire dans le modèle ou dans une contrainte inviolable du stockage. Vérifier viewer sur document:123 sans vérifier l’appartenance au tenant revient à croire que les identifiants préfixés sont une frontière de sécurité. Ils ne le sont pas, même avec une police monospace très rassurante.

Le troisième risque est le déni de service par graphes profonds, groupes massifs ou requêtes répétées sur des ressources très partagées. Imposer une profondeur maximale, des quotas d’écriture, une limite de cardinalité par relation et des délais de réponse. Mettre en cache les décisions positives exige une clé incluant l’identité, l’objet, la permission et la révision ; sinon un cache sert généreusement le droit d’Alice à Bruno.

L’exploitation requiert un journal d’audit immuable des écritures de tuples : auteur authentifié, relation, sujet, objet, horodatage, motif et révision résultante. Surveiller les ajouts de relations d’administration, les délégations en cascade, les suppressions en masse et les erreurs de cohérence. Sauvegarder le schéma versionné et les tuples avec leurs métadonnées d’origine. La restauration doit rejouer un état cohérent puis valider les permissions critiques, pas seulement remettre une base en ligne et espérer que le graphe se souvienne de ses bonnes manières.

Sans modèle relationnel centralisé, la décision d’accès se recopie dans chaque service : une clause SQL dans l’API, un filtre dans l’index de recherche, rien du tout dans un traitement par lot ou un export CSV. Les divergences ne se voient pas, car chaque chemin répond seul. Il devient également impossible de répondre à la question inverse, à savoir qui accède à un document donné, puisqu’aucun graphe ne permet d’énumérer les sujets d’une ressource. La recertification des partages perd sa base, le retrait d’une personne d’une équipe laisse des droits résiduels écrits en dur, et l’analyse d’un incident ne peut pas délimiter le périmètre exposé. Sans journal des écritures de relations, l’origine d’un accès accordé reste inexplicable, ce qui interdit toute reprise vérifiée après restauration.

Un système d’accès relationnel enregistre des faits : une personne appartient à une équipe, une équipe peut consulter un dossier, un dossier contient un document. Chaque fait relie un sujet, une relation et un objet. Le modèle définit ensuite les règles de calcul : une personne peut lire un document si elle a reçu ce droit directement ou si elle peut lire son dossier parent.

Quand une application demande l’accès à un document, le système cherche les liens nécessaires. Il peut trouver un droit donné directement à la personne. Sinon, il remonte vers le dossier, puis vérifie si la personne appartient à une équipe autorisée. La réponse dépend donc des liens réellement enregistrés, pas d’un grand nombre de rôles créés pour chaque combinaison de clients, d’équipes et de dossiers.

Modifier un droit doit produire une nouvelle version de l’état des liens. Après avoir retiré un accès, les vérifications suivantes doivent demander une version au moins aussi récente ; sinon une copie ancienne peut encore accepter l’accès pendant un court moment. Les caches doivent suivre cette version ou expirer rapidement.

Ce mécanisme ne protège pas contre une identité volée, un administrateur qui ajoute un lien abusif, un fichier déjà téléchargé ou une base de données restaurée avec des droits périmés. Il faut donc protéger l’authentification, limiter qui peut modifier les liens, enregistrer ces modifications, sauvegarder le modèle et vérifier régulièrement que les droits calculés correspondent aux règles métier.

À lire aussi

Pages voisines

: les deux pages se citent l’une l’autre.