Skip to main content

Understanding how Casbin Works

In this post I will explain RBAC design and implementation using the Casbin library. For a SaaS platform that deals with multiple Resource Hierarchies, and roles that inherit permissions from higher levels Casbin is a performant alternative to consider.

What is RBAC?​

RBAC is a method of restricting access to resources based on the Roles that an individual holds. Let's look at Azure's RBAC system in the next section to better understand how Hierarchical RBAC works, and then we can try to implement a system which is similar.

Understanding Azure's Hierarchical RBAC​

Azure Hierarchy

There is a role called Owner for all resources in Azure, suppose if I have Owner role assigned to me at subscription level, that means I am the Owner of all the resource groups and resources under that subscription. If I have Owner at resource group level, then I am the Owner of all the resources under that resource group.

This image shows that I have Owner access at Subscription level. Subscription Owner

When I check the IAM of a Resource Group under this Subscription, you can see I have inherited Owner access from the Subscription. RG Owner

So this is how Azure's RBAC is hierarchical, most of the enterprise software use hierarchical RBAC because of the hierarchical nature of the resource levels in this tutorial, we'll try to implement a similar system in this tutorial using Casbin.

How Casbin Works?​

Before the implementation we have to understand what is Casbin and how it works at a high level. This is required because each RBAC system will differ based on the requirement. So understanding Casbin helps us to fine tune the model.

What is ACL?​

ACL is where users are mapped to actions and actions to resources.

The model definition​

Let's take a simple example ACL model

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
  1. The request_definition is the query template of the system. For example, a request alice, write, data1 can be read as can subject alice do action write on object data1.

  2. The policy_definition is the assignment template of the system. For example, by creating a policy alice, write, data1 you're assigning permission to subject alice for doing action write on object data1.

  3. The policy_effect defines the effect of the policy.

  4. Given a request and set of policies, the matchers section matches the request with policy.

Now let's test the model on Casbin editor​

Open editor and paste the above model in the Model editor.

Paste the following in the Policy editor

p, alice, read, data1
p, bob, write, data2

and the following in the Request editor

alice, read, data1

Result will be

true

Visual representation of the ACL model, policy and request matching​

acl

What is RBAC?​

In RBAC a user is assigned a role for a resource, a role can contain arbitrary actions. And the request checks if the user can do the action on resource.

The model definition​

Let's take a simple example RBAC model

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && r.obj == p.obj
  1. The role_definition is a graph relation builder which uses a Graph to compare the request object with the policy object.

Now let's test the model on Casbin editor​

Open editor and paste the above model in the Model editor.

Paste the following in the Policy editor

p, alice, reader, data1
p, bob, owner, data2

g, reader, read
g, owner, read
g, owner, write

and the following in the Request editor

alice, read, data1
alice, write, data1
bob, write, data2
bob, read, data2
bob, write, data1

Result will be

true
false
true
true
false

Visual representation of the RBAC model, policy and request matching​

rbac

The g - Role to action mapping table has a Graph mapping the role to action mapping. This Graph can be coded as a list of edges, as shown in the policy which is a common way of representing a Graph

g, reader, read
g, owner, read
g, owner, write
info

p indicates a normal policy which can be compared using == operator. g is a Graph based comparison function. You can define multiple Graph comparators by adding a numerical suffix like g, g2, g3, ... and more.

What is Hierarchical RBAC?​

In Hierarchical RBAC there are more than one type of resources and there is an inheritance relationship between the resource types, for example subscription is one type and resourceGroup is another type, sub1 of type Subscription can contain multiple resourceGroups rg1, rg2 of type ResourceGroup.

Similar to the resource hierarchy there will be two types of roles and actions. Subscription roles and actions, ResourceGroup roles and actions. And there is a arbitrary relationship between the Subscription role and ResourceGroup role, for example consider a Subscription Role sub-owner, this role is inherited by a ResourceGroup Role rg-owner, meaning if I am assigned sub-owner on Subscription sub1, then I automatically also get rg-owner role on rg1 and rg2.

The model definition​

Let's take a simple example Hierarchical RBAC model

[request_definition]
r = sub, act, obj

[policy_definition]
p = sub, act, obj

[role_definition]
g = _, _
g2 = _, _

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && g(p.act, r.act) && g2(p.obj, r.obj)
  1. The role_definition is a graph relation builder which uses a Graph to compare the request object with the policy object.

Now let's test the model on Casbin editor​

Open editor and paste the above model in the Model editor.

Paste the following in the Policy editor

p, alice, sub-reader, sub1
p, bob, rg-owner, rg2

// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

and the following in the Request editor

alice, rg-read, rg1

Result will be

true

Visual representation of the RBAC model, policy and request matching​

hrbac

The g - Role to (Action, Role) Mapping table has a Graph mapping the role to action, role mapping. This Graph can be coded as a list of edges, as shown in the policy which is a common way of representing a Graph


// subscription role to subscription action mapping
g, sub-reader, sub-read
g, sub-owner, sub-read
g, sub-owner, sub-write

// resourceGroup role to resourceGroup action mapping
g, rg-reader, rg-read
g, rg-owner, rg-read
g, rg-owner, rg-write

// subscription role to resourceGroup role mapping
g, sub-reader, rg-reader
g, sub-owner, rg-owner

The g2 - Sub to RG Mapping table has a Graph mapping subscription to resourceGroup.

// subscription resource to resourceGroup resource mapping
g2, sub1, rg1
g2, sub2, rg2

Subject Matching Visual representation​

hrbac-sub-match

Action Matching Visual representation​

hrbac-act-match

Object Matching Visual representation​

hrbac-obj-match

info

When a request is submitted to Casbin, this matching happens for all the policies, if at least one policy matches then the result of the request is true, if no policy matches the request, then the result is false

Conclusion​

In this tutorial, we learnt how different authorization models work and how it can be modeled using Casbin. In the second part of this tutorial we will implement this in a demo Spring Boot Application and secure the APIs using Casbin.