Comprendre le modèle de permissions RBAC de gitrust¶
Ce que vous allez comprendre¶
- Analyser comment les 4 rôles (Reader, Developer, Maintainer, Owner) s'appliquent à un dépôt.
- Évaluer la différence entre accès direct et accès via équipe, et comment le rôle effectif est calculé.
- Comparer le modèle gitrust avec les ACL Unix (user/group/other).
Le problème concret¶
Vous avez un dépôt privé alice/myproject. Alice souhaite que :
- Bob puisse lire le code (pas pusher).
- L'équipe backend-devs puisse pusher.
- Charlie, membre de backend-devs, soit quand même restreint en lecture seule.
Sans un modèle de permissions précis, impossible de savoir quel accès Charlie obtient réellement.
L'analogie¶
Le modèle gitrust ressemble aux ACL Unix, mais à deux dimensions.
Sur Unix, chaque fichier a trois niveaux : user (propriétaire), group, other. Le niveau effectif est le premier qui correspond, dans cet ordre.
Gitrust fonctionne de manière similaire, avec deux axes :
| Axe Unix | Axe gitrust |
|---|---|
user |
accès individuel direct (resource_shares) |
group |
accès via équipe (team_repository_access) |
other |
accès public (resources.is_public) |
La différence clé : gitrust prend le maximum entre l'accès individuel et l'accès équipe, pas le premier correspondant.
Le modèle¶
Les 4 rôles et leur hiérarchie¶
graph LR
R[Reader] --> D[Developer]
D --> M[Maintainer]
M --> O[Owner]
| Rôle | Permissions cumulatives |
|---|---|
| Reader | Clone, browse (lecture seule) |
| Developer | Reader + push sur branches non protégées |
| Maintainer | Developer + gestion dépôt (settings, collaborateurs, labels, protection de branches) |
| Owner | Maintainer + suppression, transfert |
La hiérarchie est strictement cumulative : un Maintainer a toutes les permissions d'un Developer, qui a toutes celles d'un Reader.
Sources d'accès¶
Un utilisateur peut accéder à un dépôt par trois chemins indépendants :
flowchart TD
User[Utilisateur]
subgraph "Accès individuel"
Owner["Owner (resources.owner_id)"]
Share["resource_shares
(read / write / admin)"]
Public["Accès public
(resources.is_public = true)"]
end
subgraph "Accès équipe"
TeamMember["team_members
(l'utilisateur est membre)"]
TeamAccess["team_repository_access
(permission de l'équipe sur le dépôt)"]
end
Effective["Rôle effectif
= max(individuel, équipe)"]
User --> Owner
User --> Share
User --> Public
User --> TeamMember
TeamMember --> TeamAccess
Owner -->|"owner (full)"| Effective
Share -->|"read/write/admin"| Effective
Public -->|"read only"| Effective
TeamAccess -->|"read/write/admin"| Effective
Calcul du rôle effectif¶
Le rôle effectif d'un utilisateur sur un dépôt est le maximum de tous ses accès :
rôle_effectif = max(
owner_directement ? owner : none,
resource_shares.permission_level,
is_public ? read : none,
max(team_repository_access.permission pour chaque équipe dont il est membre)
)
Exemple — réponse au problème concret :
| Utilisateur | Accès individuel | Accès via équipe | Rôle effectif |
|---|---|---|---|
| Alice | owner | — | owner |
| Bob | read (partagé directement) | — | read |
| Charlie | read (partagé directement) | write (via backend-devs) | write (max) |
| Dave (membre backend-devs) | — | write | write |
Charlie obtient write car le max(read, write) = write. Pour restreindre Charlie en lecture seule malgré son appartenance à backend-devs, il faudrait le retirer de l'équipe ou utiliser une protection de branche.
Arbre de décision¶
flowchart TD
Q1{L'utilisateur\nest-il owner ?}
Q1 -->|Oui| Full[Accès owner\n(toutes permissions)]
Q1 -->|Non| Q2{resource_shares\nexiste pour cet utilisateur ?}
Q2 -->|Oui| Q3{Dépôt public ?}
Q2 -->|Non| Q3
Q3 -->|Oui| Q4[Accès public = read]
Q3 -->|Non| Q4b[Pas d'accès public]
Q4 --> Q5{Membre d'une équipe\navec accès au dépôt ?}
Q4b --> Q5
Q5 -->|Oui| Calc["Rôle = max(share, public, team)"]
Q5 -->|Non| Calc2["Rôle = max(share, public)"]
Calc --> Result[Rôle effectif final]
Calc2 --> Result
Mapping vers les niveaux ResourceService¶
ResourceService (rustwarden-core) utilise les niveaux "read", "write", "admin". Le mapping gitrust est :
| Niveau ResourceService | Rôle gitrust |
|---|---|
"read" |
Reader |
"write" |
Developer |
"admin" |
Maintainer |
owner (ownership directe) |
Owner |
Alternatives et compromis¶
Pourquoi pas un modèle RBAC pur avec des rôles nommés par dépôt ? Gitea/Forgejo utilisent des rôles nommés (reporter, developer, maintainer). Gitrust utilise des niveaux numériques (read < write < admin) héritables, ce qui simplifie le calcul du maximum mais rend impossible l'attribution de permissions non hiérarchiques (ex : « peut créer des issues mais pas pusher »).
Pourquoi pas des ACL par fichier ? La granularité fichier (comme dans Perforce) crée une complexité de maintenance considérable pour des équipes de 3-20 personnes. Les protections de branches couvrent 90 % des besoins de contrôle granulaire.
Vérifier votre compréhension¶
-
Alice est owner de
myrepo. Elle partage le dépôt avec Bob enread. L'équipeopsa accès enadmin. Bob rejointops. Quel est le rôle effectif de Bob ? -
Un visiteur anonyme accède à un dépôt dont
resources.is_public = true. Peut-il pusher ? Pourquoi ?