RBAC and ABAC¶
Two ways to decide what an authenticated user may do: role-based access control (RBAC) grants permissions to roles and puts users in roles; attribute-based access control (ABAC) evaluates rules over attributes of the user, the data and the request.
Before reading
Why it matters¶
A platform with a few tables and a few teams can grant access one table at a time. With hundreds of tables, many teams, sensitive columns and regional rules, that becomes unmanageable: grants pile up, nobody can review them, and new tables are either open to everyone or closed to everyone. The access model decides whether permissions can be understood and kept correct as the platform grows.
How it works¶
With RBAC, permissions are attached to roles, such as analyst, finance_reader or orders_engineer, and users or groups are assigned to roles. Granting someone access means adding them to a role. RBAC is simple to understand and audit: list a role's permissions, list its members. Most engines and catalogs support it with GRANT statements. Its weakness is the number of roles. Every combination of conditions, such as analyst in the EU allowed to see personal data, needs its own role, and roles multiply.
With ABAC, a policy is a rule over attributes. User attributes come from the identity provider: department, region, clearance, groups. Resource attributes come from the catalog: domain, classification tags, owner. Context attributes describe the request: time, purpose, network. A rule might say: users may read columns tagged pii only if they have privacy training and the data's region matches theirs. One rule covers every table that carries the tag, including new ones, so policies stay few even as data grows. The cost is that it is harder to answer "what can this user see?" without evaluating the rules, and attributes must be reliable: a wrong tag or an out-of-date department grants or denies wrongly.
In practice the two are combined. Roles grant broad access to domains or layers; attribute rules handle sensitivity, regions and row-level restrictions within that access.
A third model, relationship-based access control (ReBAC), decides from relationships, such as "a user can see an order if they are the seller of the order". It suits applications with sharing and ownership, such as data products shown to marketplace sellers, and is implemented by systems modelled on Google's Zanzibar paper, such as OpenFGA.
Where policies live matters as much as which model. A policy decision point evaluates the rules; a policy enforcement point, such as the query engine, the catalog or an API, asks it and applies the answer. Policies can live inside each product, in the engine's grants or the catalog's rules, or in a central policy engine that several enforcement points query. Central policies give one place to review and change rules, but every enforcement point must actually ask.
flowchart LR
U[User request:<br/>SELECT from clean_customers] --> PEP[Enforcement point:<br/>query engine]
PEP -->|user, groups, region,<br/>table, column tags| PDP[Decision point:<br/>policy engine]
PDP -->|allow, with mask on email<br/>and filter region = EU| PEP
PEP --> R[Rows returned<br/>with policy applied]
ATTR[(Attributes:<br/>IdP groups,<br/>catalog tags)] --> PDP
Key terms¶
- RBAC: permissions granted to roles; users get permissions through roles.
- ABAC: permissions decided by rules over user, resource and context attributes.
- ReBAC: permissions decided from relationships between users and objects.
- Policy decision point: the component that evaluates access rules.
- Policy enforcement point: the component that applies the decision to a request.
- Least privilege: granting only the access a user or service needs.
Example¶
The shop has analysts, who need sales data everywhere, and regional managers, who need only their region's customers.
With RBAC alone:
GRANT SELECT ON shop.fct_daily_sales TO ROLE analyst;
-- copies of shop.clean_customers, one per region
GRANT SELECT ON shop.customers_eu TO ROLE manager_eu;
GRANT SELECT ON shop.customers_us TO ROLE manager_us;
-- one table copy and one role per region, plus one per new region
With ABAC, one rule over one table:
allow read on tables with domain = "customers"
when user.group contains "regional-manager"
with row filter: region = user.region
If the shop added a third region, RBAC would need a new table and a new role; ABAC would need only managers with the new region in the identity provider.
Pitfalls¶
- Role explosion. Encoding every condition into roles produces hundreds that nobody can review.
- Grants to individuals. Grant to roles or groups so access can be reviewed and removed.
- Unreliable attributes. ABAC is only as correct as the tags and user attributes it reads.
- Enforcement points that skip the policy engine. A direct path to the data bypasses every rule.
- No access reviews. Permissions accumulate; review them regularly with the data owners.
Learn more¶
- NIST SP 800-162, Guide to Attribute Based Access Control: https://csrc.nist.gov/pubs/sp/800/162/upd2/final
- Zanzibar: Google's Consistent, Global Authorization System: https://research.google/pubs/zanzibar-googles-consistent-global-authorization-system/
Related¶
Row-level security and masking · Governance as code · Multi-tenancy · Catalogs