Casbin RBAC Guide: Standard vs. Hierarchical Roles, Maintenance, and Configuration
A common misconception about using Casbin Hierarchical RBAC is that the entire policy storage must be updated every time a user performs an action or changes state. This is incorrect. The system is designed to separate the static, structural hierarchy (which rarely changes) from the dynamic user assignments (which change frequently).
The efficiency of Hierarchical RBAC lies in this separation, minimizing the required policy updates and reducing redundancy.
The Two Types of Relationships in Policy Storageโ
Hierarchical RBAC requires two primary types of grouping rules in the policy storage (e.g., a database or CSV file), typically defined by the g and g2 rules in the policy file.
1 Static Relationships: Role Inheritance (g2 Rules)โ
The g2 rules define the fixed, structural relationships between roles, establishing the inheritance chain. These are managed by application administrators and reflect the organizational structure.
- Rule Format:
g2, child_role, parent_role - Purpose: To define a single source of truth for cascading permissions. When a child role is defined as a successor of a parent role, the child automatically inherits all permissions granted to the parent.
- Update Frequency: Low (Administrative). You only update these rules when the company's roles or internal structure fundamentally change (e.g., merging a department, creating a new top-level role). They are not tied to user activity.
Example: Static Inheritance
If an Admin inherits from a Manager, this rule is defined once and stays constant until a structural change.
| Policy Rule | Annotation |
|---|---|
g2, admin, manager | The admin role inherits all permissions of the manager role. |
p, manager, reports, view | The manager role can view reports. |
Result: An admin can automatically view reports without a separate p, admin, reports, view rule. |
2 Dynamic Relationships: User-to-Role Assignment (g Rules)โ
The g rules link a specific subject (user) to a starting role in the hierarchy. This link represents the user's current status and is the only element that changes frequently based on user lifecycle events.
- Rule Format:
g, subject, role - Purpose: To assign a user to the starting point of their effective permissions chain.
- Update Frequency: High (Dynamic/User Lifecycle). These rules are updated when a new user is onboarded, promoted, transferred, or deleted. This is typically managed via Casbin's API methods (e.g.,
enforcer.addGroupingPolicyorenforcer.deleteGroupingPolicy).
Example: Dynamic User Assignment
When a new user, Alice, is hired as an Admin, only the g rule is updated.
| Casbin API Call | Policy Rule Added | Annotation |
|---|---|---|
enforcer.addGroupingPolicy("alice", "admin") | g, alice, admin | A single entry is created linking Alice to the admin role. |
Maintenance Benefit: If the admin role inherits permissions from 5 parent roles, you still only make one policy update (g rule) instead of updating 5 separate permission groups for Alice. |
Why Hierarchical RBAC is Efficientโ
The entire system relies on Casbin's Role Manager to handle the recursive lookup [2].
- Request: User
Aliceasks to access/reports. - Lookup 1 (Dynamic): Casbin checks the
grules and finds thatAliceis assigned to theadminrole. - Lookup 2 (Static): Casbin checks the
g2rules and discovers thatadmininherits frommanager, andmanagerinherits fromexecutive. - Enforcement: Casbin checks permissions for
admin,manager, andexecutiveagainst the/reportsresource.
Because the g2 hierarchy is loaded and cached by the Role Manager upon initialization, authorization checks are fast, and the policy storage remains tidy. You only modify the storage when a user's role changes, or the organization's structure changes.
Standard RBAC vs. Hierarchical RBAC: When to Choose Eachโ
The choice between standard Casbin RBAC and Hierarchical RBAC depends on the complexity of your application's user structure and the need for role inheritance.
Casbin Standard RBAC (Model: g only)โ
Standard RBAC assigns permissions to roles, and then assigns users to those roles. The core is the grouping policy (g), which maps a subject (user) to a role.
When to Choose Standard RBAC:
- Flat Organizations: Small to medium-sized applications where roles (e.g.,
Admin,Editor,Viewer) have distinct, non-overlapping permission sets. - Simple Auditing: When you need a direct, explicit list of every permission assigned to a user without having to trace an inheritance chain.
- Performance: For very high-traffic applications, avoiding a deep recursive lookup for role inheritance can slightly speed up authorization checks.
Example Model (rbac_model.conf):
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_manager]
rm = rbac_api
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
Example Policy (rbac_policy.csv):
p, editor, articles, read
p, editor, articles, edit
g, alice, editor
g, bob, viewer
Casbin Hierarchical RBAC (Model: g and g2)โ
Hierarchical RBAC introduces g2 that maps roles to other roles. A child role automatically inherits all permissions granted to its parent.
When to Choose Hierarchical RBAC:
- Inheritance is Key: Define permissions once at a high-level role and let lower-level roles inherit them.
- Reduced Policy Management: Eliminates redundant permission lines across similar roles.
- Simulating Organizational Charts: Maps well to traditional org structures.
Example Model (rbac_hierarchy_model.conf):
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_manager]
rm = rbac_api
[policy_effect]
e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
Example Policy:
p, manager, reports, view
p, manager, audits, create
p, executive, reports, view
g, alice, director
g2, director, manager
g2, manager, executive
Decision Summaryโ
| Feature | Standard RBAC | Hierarchical RBAC |
|---|---|---|
| Role Inheritance | No (Must explicitly assign all permissions). | Yes (Child roles inherit parent permissions). |
| Complexity | Easier to trace and debug. | Reduces policy file size, but more complex lookups. |
| Policy Lines | Higher redundancy (many duplicated p lines). | Lower redundancy (single g2 lines manage many permissions). |
| Best For | Flat applications, simple permission needs, high performance. | Large enterprises, complex hierarchies, reduced maintenance. |
If you find yourself constantly duplicating permission lines across different roles that logically should share permissions, switch to Hierarchical RBAC. If your structure is simple and static, Standard RBAC is sufficient.
