Aller au contenu
medium

RBAC, ABAC et politiques d'autorisation

18 min de lecture

L'autorisation détermine ce qu'un utilisateur authentifié peut faire. Trois modèles dominent : RBAC (rôles), ABAC (attributs contextuels) et ReBAC (relations entre objets). Le bon choix dépend de votre cas : RBAC suffit pour "admin/éditeur/lecteur", ABAC permet des règles dynamiques ("accès si même département + heures ouvrées"), ReBAC gère les partages complexes ("éditeurs de ce document").

Ce guide vous donne les clés pour modéliser l'autorisation dans vos systèmes. À la fin, vous saurez :

  • Distinguer RBAC, ABAC et ReBAC, et quand utiliser chaque modèle
  • Concevoir une architecture PDP/PEP découplée
  • Écrire des politiques testables avec Policy-as-Code
  • Éviter les erreurs classiques (explosion de rôles, ABAC trop complexe)

Prérequis : avoir lu Les bases de l'IAM et OAuth 2.x.

Ces deux concepts sont souvent confondus. Pourtant, ils répondent à des questions différentes et interviennent à des moments distincts du flux de sécurité.

ÉtapeQuestionRésultat
Authentification (AuthN)Qui es-tu ?Identité vérifiée
Autorisation (AuthZ)Que peux-tu faire ?Permissions accordées ou refusées

L'authentification vient avant l'autorisation. Vous ne pouvez pas autoriser quelqu'un que vous ne connaissez pas.

Le RBAC attribue des permissions via des rôles.

Utilisateur → Rôle → Permissions
├── "admin" → [read, write, delete]
├── "editor" → [read, write]
└── "viewer" → [read]

Avantages :

  • Simple à comprendre et implémenter
  • Facile à auditer (qui a quel rôle ?)
  • Bien supporté par tous les systèmes

Inconvénients :

  • Explosion de rôles : admin-us, admin-eu, admin-project-x, admin-project-y-read-only...
  • Pas de contexte dynamique (heure, localisation, sensibilité des données)

Le critère de décision tient en une question : vos permissions dépendent-elles uniquement de la fonction de la personne, ou aussi du contexte de la demande ? Tant que la réponse est « la fonction seule », RBAC suffit et vous évitez une complexité inutile. La ligne multi-tenant est celle qui bascule le plus souvent : elle fonctionne au début, puis chaque nouveau client ajoute son jeu de rôles et le nombre devient ingérable.

SituationRBAC adapté ?
Permissions statiques par fonction métierOui
Équipe de moins de 100 personnesOui
Multi-tenant avec isolation strictePossible, avec réserve
Accès contextuel (heure, geo, risque)Non

L'ABAC décide selon des attributs plutôt que selon une appartenance. La différence pratique est qu'aucune permission n'est stockée quelque part : elle est calculée à chaque demande à partir des quatre familles d'attributs ci-dessous. C'est ce qui donne sa souplesse au modèle, et c'est aussi ce qui rend le débogage difficile, puisqu'il n'existe pas de liste à consulter pour savoir qui a accès à quoi.

Type d'attributExemples
Sujetdépartement, niveau de clearance, fonction
Ressourceclassification, propriétaire, date création
Actionread, write, delete, approve
Contexteheure, IP, géolocalisation, device

Exemple de règle ABAC :

ALLOW read document
WHERE subject.department == resource.department
AND resource.classification <= subject.clearance
AND context.time BETWEEN 08:00 AND 18:00
AND context.geo IN ['FR', 'DE', 'ES']

Avantages :

  • Très flexible, gère les cas complexes
  • Pas d'explosion de rôles
  • Décisions contextuelles

Inconvénients :

  • Plus complexe à implémenter et débugger
  • Collecte des attributs peut être coûteuse
  • Difficile à auditer ("pourquoi cet accès ?")

Le ReBAC modélise les permissions comme des relations entre objets.

Graphe ReBAC : Alice est owner de doc-123, Bob est viewer, Team-X contient Bob, doc-123 est dans folder-A

Règle : "Les viewers d'un dossier peuvent lire les documents qu'il contient"

Les systèmes ReBAC (Google Zanzibar, OpenFGA, SpiceDB) traversent le graphe de relations pour calculer les permissions.

Avantages :

  • Naturel pour les hiérarchies (org, dossiers, projets)
  • Permissions héritées automatiquement
  • Modèle puissant pour le sharing/collaboration

Inconvénients :

  • Complexité du graphe
  • Performance (traversée de graphe)
  • Moins intuitif que RBAC

Lisez d'abord la ligne Auditabilité, c'est elle qui se paye le plus cher en exploitation. Un modèle très flexible mais dont personne ne sait expliquer une décision devient impossible à défendre devant un auditeur, et impossible à corriger quand un accès surprend. La ligne Complexité mesure l'effort de mise en place, mais l'auditabilité mesure l'effort permanent, celui que vous subirez à chaque incident.

CritèreRBACABACReBAC
ComplexitéFaibleÉlevéeMoyenne-Élevée
FlexibilitéFaibleTrès élevéeÉlevée
Contexte dynamiqueNonOuiPartiel
AuditabilitéFacileComplexeTraversée de graphe
Cas d'usageApps métier classiquesDéfense, santé, financeCollaboration, SaaS multi-tenant
Exemples systèmesAWS IAM, Kubernetes RBACXACML, OPAGoogle Zanzibar, OpenFGA

Pour découpler l'autorisation du code métier, utilisez l'architecture PEP + PDP :

ComposantRôle
PEP (Policy Enforcement Point)Intercepte la requête, demande une décision, applique le résultat
PDP (Policy Decision Point)Évalue la politique, retourne ALLOW/DENY
PAP (Policy Administration Point)Interface d'administration des politiques
PIP (Policy Information Point)Fournit les attributs (user, resource, context)

Suivez le sens des flèches : le PEP ne décide de rien, il intercepte et applique. C'est le PDP qui tranche, et il ne connaît que ce qu'on lui transmet. Deux conséquences pratiques découlent de ce schéma. La latence de l'appel au PDP s'ajoute à chaque requête, ce qui impose souvent de le déployer au plus près de l'application. Et le PDP est indisponible, le comportement par défaut doit être le refus, jamais l'autorisation.

Flux de décision PDP/PEP : le Client envoie une requête au PEP, qui interroge le PDP pour obtenir une décision ALLOW/DENY basée sur les attributs du PIP

Le gain le plus concret est le troisième : modifier une règle d'accès sans redéployer l'application transforme un délai de plusieurs jours en quelques minutes. Mais c'est aussi le plus dangereux si rien ne l'encadre, puisque n'importe quelle modification de politique prend effet immédiatement en production. C'est précisément pour cela que la testabilité vient juste avant dans le tableau : elle est la contrepartie obligatoire de cette agilité.

AvantageDescription
CohérenceUne seule source de vérité pour les politiques
TestabilitéPolitiques testées indépendamment du code
ÉvolutivitéChanger les règles sans redéployer l'app
AuditabilitéLog centralisé des décisions

OPA (Open Policy Agent) est un moteur de politiques générique. Les politiques sont écrites en Rego.

Une politique Rego est une suite de règles indépendantes portant le même nom. allow est vrai dès qu'une seule d'entre elles se vérifie, ce qui revient à un OU logique entre les blocs ; à l'intérieur d'un bloc, les lignes se combinent en ET. La ligne default allow := false est la plus importante du fichier : elle impose le refus par défaut, sans quoi une requête ne correspondant à aucune règle laisserait allow indéfini plutôt que faux.

package authz
# Refus par défaut : sans règle explicite, l'accès est nié
default allow := false
# Les administrateurs ont tous les droits
allow if {
input.user.roles[_] == "admin"
}
# Le propriétaire peut modifier sa propre ressource
allow if {
input.action == "write"
input.resource.owner == input.user.id
}
# Lecture autorisée entre membres du même département
allow if {
input.action == "read"
input.user.department == input.resource.department
}

OPA ne connaît du monde extérieur que ce document input. C'est le point à retenir : le moteur n'interroge aucune base, ne consulte aucun annuaire, il évalue les règles sur les données qu'on lui remet. Toute la fiabilité de la décision repose donc sur la qualité de cet objet, et notamment sur le fait que les attributs proviennent d'une source de confiance et non du client.

Input (JSON) :

{
"user": {
"id": "alice",
"roles": ["user"],
"department": "engineering"
},
"action": "read",
"resource": {
"id": "doc-123",
"department": "engineering",
"owner": "bob"
}
}

Résultat : allow = true (même département)

OPA permet d'écrire des tests unitaires dans le langage de la politique elle-même. Deux mécanismes portent tout : un nom de règle préfixé par test_ est reconnu automatiquement comme un test, et le mot-clé with input as injecte un document input fabriqué à la place du vrai. Écrivez toujours au moins un test négatif, comme test_user_cannot_delete ci-dessous : une politique qui autorise correctement mais ne refuse jamais passerait tous les tests positifs.

package authz
test_admin_allowed if {
allow with input as {
"user": {"roles": ["admin"]},
"action": "delete",
"resource": {}
}
}
test_user_cannot_delete if {
not allow with input as {
"user": {"roles": ["user"]},
"action": "delete",
"resource": {}
}
}
test_owner_can_write if {
allow with input as {
"user": {"id": "alice", "roles": ["user"]},
"action": "write",
"resource": {"owner": "alice"}
}
}

Exécution :

Fenêtre de terminal
opa test policy.rego policy_test.rego

La sortie attendue est PASS: 3/3. Ajoutez -v pour voir le détail règle par règle, ce qui devient indispensable dès que le nombre de tests augmente et qu'il faut identifier lequel a échoué.

Kubernetes utilise un RBAC natif pour contrôler l'accès à l'API.

Ces quatre objets se lisent par paires : un objet qui définit des permissions (Role, ClusterRole) et un objet qui les attribue (RoleBinding, ClusterRoleBinding). Une permission n'existe pour personne tant que le binding correspondant n'a pas été créé. Un piège classique mérite d'être signalé : un RoleBinding peut référencer un ClusterRole, ce qui applique alors ses permissions au seul namespace du binding.

RessourceDescription
RolePermissions dans un namespace
ClusterRolePermissions cluster-wide
RoleBindingLie un Role à un sujet (user, group, SA)
ClusterRoleBindingLie un ClusterRole cluster-wide

Le manifeste ci-dessous contient deux objets séparés par ---. Ce séparateur n'est pas cosmétique : sans lui, YAML considère qu'il s'agit d'un seul document avec des clés dupliquées, ne garde que la dernière valeur de chaque clé, et kubectl apply ne crée alors que le RoleBinding. Le Role disparaît silencieusement, sans le moindre message d'erreur. Notez aussi les trois verbes get, list et watch : les trois sont nécessaires pour que kubectl get pods -w fonctionne.

# Role : permissions de lecture
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# RoleBinding : lie le role à Alice
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: production
name: alice-pod-reader
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

kubectl auth can-i interroge le serveur d'API sans exécuter l'action : c'est la commande à utiliser pour valider une politique RBAC sans risque. L'option --as emprunte l'identité d'un autre sujet, ce qui demande vous-même le droit d'impersonation. La réponse tient en un mot, yes ou no, et le code de retour suit : 0 pour une autorisation, 1 pour un refus, donc utilisable dans un test automatisé.

Fenêtre de terminal
# Tester si Alice peut lister les pods
kubectl auth can-i list pods --namespace production --as alice
# yes
# Tester si Alice peut supprimer les pods
kubectl auth can-i delete pods --namespace production --as alice
# no

Problème : Vous créez un rôle pour chaque combinaison de permissions.

admin-us-east-project-alpha
admin-us-west-project-alpha
viewer-eu-project-beta
editor-apac-project-gamma
...

Solution : Passez à ABAC pour les dimensions dynamiques (région, projet), gardez RBAC pour les niveaux (admin, editor, viewer).

Problème : la politique est ouverte « le temps de livrer », avec un allow vrai partout, et cet état provisoire n'est jamais repris.

Solution :

  • Deny by default : aucun accès sauf règle explicite
  • Revue régulière des politiques
  • Tests automatisés

Problème : L'attribut vient du client, sans vérification.

# DANGEREUX : le client peut mentir sur son rôle
allow {
input.user_claims.role == "admin"
}

Solution :

  • Les attributs doivent venir de sources fiables (IdP, base interne)
  • Valider les claims du token avec le PIP

Problème : "Pourquoi Bob a-t-il pu accéder ?" → aucune trace.

Solution :

  • Logger chaque décision (entrée, résultat, politique matchée)
  • Conserver les logs pour l'audit

Les huit étapes ci-dessous suivent l'ordre dans lequel les décisions doivent être prises, et le modèle n'est choisi qu'en quatrième position. C'est volontaire : commencer par « on fait du RBAC ou de l'ABAC » avant d'avoir inventorié les sujets, les ressources et les actions revient à choisir un outil sans connaître le problème. Les trois premières étapes ne demandent aucune technologie, juste un tableau à trois colonnes.

  1. Identifier les sujets

    Qui demande l'accès ? Users, services, machines, groupes.

  2. Identifier les ressources

    Sur quoi porte l'accès ? APIs, documents, base de données, environnements.

  3. Identifier les actions

    Que peut-on faire ? CRUD, approve, deploy, transfer...

  4. Choisir le modèle

    RBAC si simple, ABAC si contexte dynamique, ReBAC si hiérarchies/sharing.

  5. Définir les politiques

    Règles explicites, refus par défaut, versionnées dans Git.

  6. Implémenter PEP/PDP

    Découpler la décision de l'enforcement.

  7. Tester

    Tests unitaires pour chaque politique, cas nominaux et limites.

  8. Auditer

    Logs, revues régulières, alertes sur anomalies.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn