While working on an internal tool for managing virtual environments, a feature request added into the tool was the ability to share environments with other users. To implement this securely, we needed a way to determine what level of access a given subject (user) had to a particular object (environment or tenant). Given that we may need various roles for a given object (i.e. admin, editor, and viewer), we needed an authorization layer that could handle hierarchical role-based access control (HRBAC).
To minimize the amount of custom code to handle authorization, we decided to leverage Google Zanzibar for a number of reasons:
- the Zanzibar design favors for quick writes while offering efficient, low-latency lookups
- the graph-based model naturally handles nested roles, group membership, and resource hierarchies
- Zanzibar has been proven to work at scale, lending to an efficient and reliable authorization system
A Zanzibar implementation I was particularly drawn to was AuthZed's SpiceDB. SpiceDB offers a mature, open-source, and actively maintained solution with comprehensive documentation, a flexible and extensible schema model, and Kubernetes support through its dedicated operator, making it straightforward to deploy and manage in production environments.
There are many great articles written on how to configure SpiceDB to handle complex role-based access control, for example this article goes into great depth to discuss relation-based access control (ReBAC). But, I do want to dive into how one can make a hierarchical role-based access control (HRBAC) possible via SpiceDB.
I've created a GitHub repository for this example: (https://github.com/irby/spicedb-hrbac-example)
Consider the following schema:
definition user {}
definition role {
// A role belongs to a specific tenant
relation tenant: tenant
// Users can be assigned to this role
relation assignee: user
// Define the hierarchical permissions
permission admin = assignee
permission editor = assignee + admin
permission viewer = assignee + editor
}
definition tenant {
// Direct role assignments within this tenant
relation admin_role: role
relation editor_role: role
relation viewer_role: role
// Computed permissions based on role assignments
permission admin = admin_role->assignee
permission editor = editor_role->assignee + admin
permission viewer = viewer_role->assignee + editor
}
With this schema, we've defined the following relations:
- A
user
can be assigned to atenant
via arole
- A
role
can be one of the following:admin
editor
viewer
- These roles have the following hierarchy
- an
admin
inherently haseditor
andviewer
access - an
editor
inherently hasviewer
access - a
viewer
only has its own access.
- an
- These roles are tenant-scoped. A role relationship to tenant A is logically separate from a role relationship to tenant B.
While a relatively simple implementation, this gives us enough flexibility to configure the HRBAC we require for our internal tool. Combined with SpiceDB's robust SDKs and APIs, this proof of concept demonstrates that we can achieve scalable, maintainable authorization without the burden of building and maintaining custom logic from scratch.
Top comments (0)