Three essential RBAC best practices

Dec 23rd, 2021

Sylvia Fronczak avatar

Sylvia Fronczak

Authorization  |  

RBAC

rbac-best-practices
Adding RBAC to application

Many of us have at one time or another implemented or considered implementing our own role-based access control (RBAC). Though it can seem simple at first, you must take care to ensure you're following best practices. Otherwise, you'll end up with a system or model that's difficult to maintain, doesn't meet the needs of your customers, or is difficult to replace.

In this post, we'll cover some best practices you should take into account.

Defining Role-Based Access Control
(RBAC)

Let's briefly review RBAC. With RBAC, we limit an application user's actions based on roles. And these roles often tie directly to business functions. They contain a collection of permissions, and every user assigned to that role inherits those permissions.

For example, users in purchasing roles may have access to create or approve purchase orders. The people in receiving have access to receive material or stock against the purchase orders. And later, those with accounting roles will be able to review and pay purchase orders.

Additionally, roles can include a hierarchy, where everyone in purchasing is able to create purchase orders, but only a select few are able to approve purchase orders.

To properly configure roles, you'll need to understand the business model, teams, responsibilities, and constraints that define permissions for your business and application.

Consider the three primary rules of RBAC

Let's take a closer look at how these roles and permissions work. With RBAC, we use three primary rules to implement our permission model:

  1. Role assignment: A subject can exercise a permission only if the subject has selected or been assigned a role.
  2. Role authorization: A subject's active role must be authorized for the subject. With rule 1 above, this rule ensures that users can take on only roles for which they are authorized.
  3. Permission authorization: A subject can exercise a permission only if the permission is authorized for the subject's active role. With rules 1 and 2, this rule ensures that users can exercise only permissions for which they are authorized.

Keeping that in mind, you may realize that you can easily fulfill this with a few database tables and straightforward code.

Next, let's look at why teams tend to roll their own system for role-based access.

Why create your own RBAC system?

Building an RBAC system can seem very simple at first, so it makes sense why  many choose to go their own route and create their own role-based access control system. When building applications, we often want to do the simplest thing that works. And following that premise, we often have to decide between building functionality ourselves, pulling in libraries and utilities, or using external SaaS solutions.

From personal experience, I've seen a few different reasons why teams have wanted to implement their own RBAC:

  1. The existing RBAC system appears to be insufficient for the current use case. Alternatively, the existing RBAC system seems overly complex or overengineered for a simple use case.
  2. The team feels a DIY solution will take less time during a prototyping or MVP stage than integrating with a third-party solution.
  3. Existing permission systems tie the application to a particular platform or cloud vendor. It may not make sense to implement a solution in one platform if you will soon be moving to a different platform.

While these are valid reasons to consider rolling your own RBAC solution, you then bear the responsibility of learning and following best practices. These practices ensure that you provide the appropriate level of access in a maintainable way.

rbac-best-practices

What best practices should you follow for RBAC?

In this section, let's look at high-level best practices and what they mean for your implementation.

1. Build your authorization model for evolution

Earlier in this post, we talked a little bit about what makes up roles and how they apply to business functions. Next, we'll look at what we should keep in mind when building out the authorization model.

  1. First, take inventory of the business. What resources exist, and who has permission to read, write, delete, and/or act upon those resources in some way? Consider what bottlenecks inappropriate permissions may create when a workflow is held up because permissions are too restricted. Learn what happens when a role only has a few people in it and they're all out of the office. How do you handle delegations? Furthermore, what happens when someone has too much privilege within the system? You should be aware of how these permissions affect the business from a process and monetary standpoint.
  2. Start with a coarse-grained model. Use as few roles, resources, and permissions as needed. Then gradually build in complexity as requirements and understanding of permissions change. If you start with too many fine-grained roles and permissions, you'll overcomplicate the model. And oftentimes this requires redesigning the model once nuances of permissions are more fully understood. Alternatively, if redesigning doesn't happen, overly complicated and incorrect models can lead to a maintenance nightmare, and admins default to "give the new person all these roles, because we can't figure out which ones they really need."
  3. Build roles in a hierarchy so that maintenance carries less of a burden. With the proper hierarchy, you can easily control permissions for all users and for those with specialized roles. For example, all users may be able to access their profile and edit certain characteristics. There's no need to build that for each and every role.
  4. Use the principle of least privilege. When designing roles, ensure that users will have the permission needed to do their job, but no more. This will take some tweaking as sometimes, even when interviewing business folks and auditing processes, we’ll make incorrect assumptions about what level of access particular roles need, until reality hits.

2. Design and implement your system for modification

Next, let's look at the actual implementation of your system.

  1. Use a simple and reusable API. Your RBAC must answer this question: is the current user allowed to perform this action on this resource? Adding more complexity than that will make moving to a third-party system more difficult in the future.
  2. Decouple your application logic from your RBAC system. Here, you'll want to consider separation of concerns so that you can independently change your application and your authorization system. For many, that means creating a generic wrapper around authorization so that replacing the system in the future will only require changes in one place and not every place that you check permissions.
  3. Keep authorization checks as close to the edge or API controller as possible. This will reduce overly complicated business logic that relies on permission checks in determining flow. It can be a sign of poor design if permission checks litter your application logic and increase the complexity of one API call or process. So if you’re finding that permission checks are used to control programming flow within an API, consider whether a separate endpoint is warranted for certain business functions.
  4. Don't build everything at once. For the MVP of RBAC, consider skipping the UI and making changes to the authorization structure through scripts or other auditable methods. Oftentimes, the UI for managing roles and user assignments takes a long time to perfect. If your user base is small, look at ways to add functionality iteratively while still keeping application resources secure. And before building a UI, consider whether that's a good use of your engineering time. Building systems that aren't differentiators to your primary business, especially when at a growth stage, can cause a tremendous loss in productivity.

3. Provide auditable RBAC data and governance

For our third best practice, let's look at what our system needs from a governance standpoint.

  1. Include auditability from day one. That doesn't mean that the sleekest UI with ad hoc reporting needs to be complete on day one. But you need a way to validate who added or removed which users to and from what roles.
  2. Resources need their own audit trail. It's not enough that your system allows the right people to perform the right actions. You'll also need to tie that in so that you can see who created, modified, or deleted resources.
  3. Make adding and removing users and roles easy and fast. In case of breaches or other scenarios where access must be removed quickly, you don't want to find that you have multiple permission systems that must all be updated across the company. Though this conflicts with creating an MVP for your RBAC system, you'll run into this need sooner rather than later and should plan accordingly. Also, you'll need to consider integration with other systems in your organization to speed up onboarding, off-boarding, and role changes.

Summary

We covered three best practices and multiple considerations for each. Use these when developing your role-based access model. And as you may have noticed, it's not as simple as it seems from the beginning.

So you may feel stuck, wondering if you should tie yourself to your cloud provider, use the not-quite-right solution others in your org use, or write your own. Let's consider another option. With Aserto, you can have cloud-based authorization as a service that will keep your application logic and authorization logic decoupled and make sure you're spending your engineering time on the most critical features for your customers.

You can sign-up to Aserto today and see how simple adding authorization can be.

This post was written by Sylvia Fronczak. Sylvia is a software developer that has worked in various industries with various software methodologies. She’s currently focused on design practices that the whole team can own, understand, and evolve over time.

Sylvia Fronczak avatar

Sylvia Fronczak