Every organization uses a set of SaaS products for their daily operations. Every such product is responsible for sheltering data and performing operations at large scale. So there should be appropriate checks as to who can do what with the data. And that's where Role-Based Access Control comes into play.
A bit about RBAC
Before we dig in, a bit of an explainer will help us start off at the same page. RBAC is a 1-1 mirror of how organizations work IRL. You as an employee will have a job role, and with your role, comes responsibilities and permissions. An employee who is an accountant will have access to the debit/credit book of the company. A DevOps engineer will be heading the pipeline development of the products. And so on.
Similarly in SaaS products, to control the access of users to specific actions and data, we put RBAC in place. Project admins (ofter the person who signed up for the product) creates teams, roles and assigns them to certain users within the product.
Whom this article is not for
Unconventional way to start, but since I'm writing this to address a very niche, I would like to set the expectations for the readers in here.
This article is not for you if:
- You are looking for a Node-based RBAC implementation
- Yes that's just about it.
But, you should read it if you:
- Are a beginner and trying to grasp the fundamentals of RBAC
- Trying to debug what went wrong in your design, or, attempting to improve your design
- Need a handbook for initial steps
- Please your seniors with a weekend blog reflection
RBAC Designs
The most basic form of RBAC system will almost always have these entities in some form or the other:
- Organization: The unit under which users, resources, and roles reside. This is where the action takes places.
- User: The actors, using the platform and taking actions.
- Resource: Items which are being acted upon by the users. It can be docs, VMs, databases, etc. These are what we protect using roles.
- Role: The gatekeeper, preventing/allowing users' access to resources.
- Permission: Associated with roles, define what a role will permit its users to do.
- User Group: Optionally present in infrastructures with massive number of resources. It associates with multiple roles and users.
The Design
- An organization is the host. Everything in our infrastructure (except
permissions) are tied up with the organization. - An organization can have multiple users →
1 x N - An organization can have multiple roles →
1 x N - An organization can have multiple resources →
1 x N - An organization can have multiple user groups →
1 x N - A role can be associated with multiple permissions, and permission can be associated with multiple roles →
M x N - A role can be associated with multiple users, and a user can be associated with multiple roles →
M x N - A role can be associated with multiple resources, and a resource can be tied up with multiple roles →
M x N - A role can be tied up with multiple user groups, and a user group can be tied up with multiple roles →
M x N - A user can be tied up with multiple user groups, and a user group can be tied up with multiple users →
M x N
High-level diagram:
Detailed diagram:
Design Outcomes
- Having a separate table for
permissionsis purely a design choice, and not a mandate. Having a separate permission table allows you to scope permissions for specific resources. For example, the roleORGANIZATION_ADMINwon't be applicable to aDocumentresource. So, you could have an optional list of acceptable/unacceptable resource types per resource. - A user can be tied up with both roles and user groups simultaneously.
- User groups are never tied with resources directly.
- There can be roles, that may not be tied with any resources at all. For example, a role having
ADMINwould imply administrative access over the organization, and hence won't have any resource mapping. - We could have chosen a higher order join-table, but having binary join-tables provide a ton of flexibility at the cost of some data repetition.
The Least Privilege model
Usually, this is where I conclude my blogs with a Conclusion, but I thought about making this section a bit more informative. This is not related to how you should implement a RBAC system, but how you should use it properly.
The Least Privilege Model states that actors should be granted the least possible set of permissions required for it to operate efficiently.
Consider you have created a pipeline that will fetch your code from your SCM, build an artifact, and deploy it to AWS Lambda. So collectively, it will require the following permissions:
- Read repository on SCM
- Pull code from SCM
- Push deployment to AWS Lambda
This is how you build a restrictive system with the least access.
Why does this matter? — Say that your deployment script gets a new change that was pushed unchecked. This can now affect other resources without your knowledge.
The only takeaway from this section would be this: your home-brewed RBAC system should be fine-grained enough so that users relying on your product can apply this principle.


Top comments (1)
Super helpful