DEV Community

Cover image for Design Decision for Role-Based Access Control (RBAC)
Rajdip Bhattacharya
Rajdip Bhattacharya

Posted on

Design Decision for Role-Based Access Control (RBAC)

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:

hld

Detailed diagram:

lld

Design Outcomes

  • Having a separate table for permissions is purely a design choice, and not a mandate. Having a separate permission table allows you to scope permissions for specific resources. For example, the role ORGANIZATION_ADMIN won't be applicable to a Document resource. 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 ADMIN would 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)

Collapse
 
kriptonian profile image
Sawan Bhattacharya

Super helpful