Skip to content
Cybrotrix
  1. Home
  2. Insights
  3. Security
Security 5 min read Cybrotrix Engineering

RBAC that people actually understand

Role explosion is the usual failure mode of access control. How we design roles around responsibilities, scope them to organizations and teams, and keep them auditable.

RBAC Identity Governance

Role-based access control has one recurring failure mode: role explosion. It starts with a handful of sensible roles. Then a team needs a slight variation, then another team needs a different one, and two years later there are three hundred roles, nobody can say what most of them grant, and the safest way to get anything done is to ask for admin. At that point RBAC is not protecting anything.

We have designed access control for platforms where organizations, teams and projects all need distinct permissions. The principles below are what kept the model small enough for people to understand.

Design roles around responsibilities

A role should answer the question "what is this person here to do?" not "which buttons may they click?" Roles like Viewer, Contributor, Reviewer, Maintainer and Administrator map to responsibilities people recognize. A role named after a screen or a feature is a sign that permissions are being assembled per request rather than designed.

Keep the set small and stable. New capabilities join existing roles based on responsibility rather than spawning new roles. If a genuinely new responsibility appears, that is when a new role is justified, and it should be rare.

Separate roles from scopes

The variation people want is almost never a different set of permissions. It is the same permissions over a different set of things. Contributor on this repository, Viewer on that one, Maintainer for the whole team. Model that as a role assignment at a scope: organization, team, project, repository. Scopes form a hierarchy, and an assignment at a higher scope applies to everything beneath it unless something more specific overrides it.

With scopes doing the work, the role catalogue stays flat. Five roles times any number of scopes covers what three hundred roles were trying to express.

Make permissions explicit and coarse enough to reason about

Under each role sits a set of permissions: repo.read, repo.push, pullrequest.approve, pipeline.run, release.approve. Permissions are what the code checks. Roles are what people assign. Keep permissions coarse enough that the list fits on a page, and keep the mapping from roles to permissions in one place, versioned and reviewed.

Resist the temptation to expose permissions directly to administrators as a customization surface. That is how role explosion begins again, one level down.

Separation of duties as a rule, not a hope

Some combinations are dangerous: the person who authors a change should not be the only one who approves it; the person who approves a production release should not be the one who deployed it. Encode these as rules the platform enforces: a pull request needs an approver other than the author; a release needs approval from someone with release.approve who did not trigger the pipeline. Rules beat policy documents because they cannot be forgotten.

Make the effective permission answerable

The question administrators ask most is "why can this person do that?" The system must answer it: this user has Maintainer on team X, which grants release.approve, which applies to project Y because it belongs to team X. If the answer requires reading a database, the model is too complicated. We build the explanation into the permission check so it can be surfaced in the UI and in audit logs.

Audit everything about access

Role assignments, scope changes and permission mapping changes are recorded with who, when and why. Access reviews become a report over that log. When someone leaves a team, removing one assignment removes everything it granted, and the log shows it.

A working heuristic: if you cannot explain the access model to a new administrator in ten minutes with a whiteboard, it will not be administered correctly.

It stays small on purpose

A small role set, hierarchical scopes, explicit permissions, enforced separation of duties and an explainable effective-permission check. None of it is novel. What makes it work is refusing to add roles when the pressure comes. That refusal is a design decision, and it is the one that keeps RBAC something people can actually understand.

Written by Cybrotrix Engineering. Opinions reflect our engineering practice at the time of writing. Discuss this with us
Next step

Let's Build What Comes Next.

Have a technology challenge, modernization initiative, or product idea? Let's engineer the solution.