Skip to content

Latest commit

History

History
227 lines (163 loc) 路 8.4 KB

role-based-access-control.md

File metadata and controls

227 lines (163 loc) 路 8.4 KB

Role Based Access Control (RBAC)

Understand the fundamentals of Role Based Access Control (RBAC) so that you can easily control who has access to what in your App.

Why?

RBAC lets you easily manage roles and permissions in any application and see at a glance exactly what permissions a person has. It reduces complexity over traditional Access Control List (ACL) based permissions systems and helps everyone building and maintaining the app to focus on security.

Who?

This document is relevant to anyone that is interested in developing and maintaining secure multi-person applications should learn about RBAC.

What?

The purpose of RBAC is to provide a framework for application administrators and developers to manage the permissions assigned to the people using the App(s).

Each role granted just enough flexibility and permissions to perform the tasks required for their job, this helps enforce the principal of least privilege.

The RBAC methodology is based on a set of three principal rules that govern access to systems:

  1. Role Assignment: Each transaction or operation can only be carried out if the person has assumed the appropriate role. An operation is defined as any action taken with respect to a system or network object that is protected by RBAC. Roles may be assigned by a separate party or selected by the person attempting to perform the action.

  2. Role Authorization: The purpose of role authorization is to ensure that people can only assume a role for which they have been given the appropriate authorization. When a person assumes a role, they must do so with authorization from an admin.

  3. Transaction Authorization: An operation can only be completed if the person attempting to complete the transaction possesses the appropriate role.

Default Roles

We have defined the following 7 default roles based on our experience/research into RBAC systems of several of the most popular applications including both "enterprise" (closed source) and popular open source CRM/CMS apps.

id name desc person_id
1 superadmin Can CREATE new roles. Can CREATE, UPDATE and DELETE Any content. Can PURGE deleted items. Can "ban" any user including people with "Admin" Role. 1
2 admin Can create new roles and assign existing roles. Can CREATE, UPDATE and DELETE any content. Can "ban" any user except people with "admin" Role. Can see deleted content and un-delete it. Cannot purge deleted. This guarantees audit-trail. 1
3 moderator Can neutrally moderate any content. Can ban rule-breaking people. Cannot "DELETE" content. 1
4 creator Can CREATE content. Can UPDATE their own content. Can DELETE their own content. 1
5 commenter Can COMMENT on content that has commenting enabled. 1
6 subscriber Can SUBSCRIBE to receive updates (e.g: newsletter), but has either not verified their account or has made negative comments and is therefore not allowed to comment. 1
7 banned Can login and see their past content. Cannot create any new content. Can see the reason for their banning (which the Admin has to write when performing the "ban user" action. usually linked to a specific action the person performed like a particularly unacceptable comment.) 1

These roles are loosely inspired by WordPress: https://wordpress.org/support/article/roles-and-capabilities
The superadmin and admin roles make sense: The person who can perform "system administration" tasks like updating the schemas/code, this is the superadmin or "owner" of the application. Typically there is only one superadmin, this person is ultimately responsible for everything. The people who are responsible for maintaining the site/app including the content and people are given the admin role; they can see everything that is going on.

The admin role should We have renamed "editor" to "moderator" because we feel this role is more relevant in a multi-content setting see: https://en.wikipedia.org/wiki/Moderator We have also renamed "author" to "creator" to emphasize that creating content is more than just "authoring" text. There will be various types of content not just "posts". We have added a "commenter role as an "upgrade" to subscriber, to indicate that the person has the ability to comment on content. Finally, we have added the concept of a "banned" role that still allows the person to login and view their own content, but they have no other privileges.

How?

Before creating any roles, you will need to have a baseline schema including people as person.id will be referenced by roles.

If you don't already have these schemas/tables, see: https://github.com/dwyl/app-mvp-phoenix#create-schemas

Create Roles and Permissions Schemas

Let's create the Database Schemas (Tables) to store our RBAC data, starting with Roles:

mix phx.gen.html Ctx Role roles name:string desc:string person_id:references:people

Next create the permissions schema:

mix phx.gen.html Ctx Permission permissions name:string desc:string person_id:references:people

We placed the roles and permissions resources in an :auth pipeline because we only want people with superadmin role to access them. See: /lib/auth_web/router.ex#L41-L43

Create Roles<->Permissions Associations

Next create the many-to-many relationship between roles and permissions.

mix ecto.gen.migration create_role_permissions

Open the file that was just created, e.g: priv/repo/migrations/20200723143204_create_role_permissions.exs

And replace the contents with:

defmodule Auth.Repo.Migrations.CreateRolePermissions do
  use Ecto.Migration

  def change do
    create table(:role_permissions) do
      add :role_id, references(:roles, on_delete: :nothing)
      add :permission_id, references(:permissions, on_delete: :nothing)
      add :granter, references(:people, on_delete: :nothing)
  
      timestamps()
    end
  
    create unique_index(:role_permissions, [:role_id, :permission_id])
  end
end

Create People<->Roles Associations

Now create the many-to-many relationship between people and roles:

mix ecto.gen.migration create_people_roles

Open the migration file that was just created, e.g: /Users/n/code/auth/priv/repo/migrations/20200723154847_create_people_roles.exs

Replace the contents of the file with the following code:

defmodule Auth.Repo.Migrations.CreatePeopleRoles do
  use Ecto.Migration

  def change do
    create table(:people_roles) do
      add :person_id, references(:people, on_delete: :nothing)
      add :role_id, references(:roles, on_delete: :nothing)
      add :granter, references(:people, on_delete: :nothing)
  
      timestamps()
    end
  
    create unique_index(:people_roles, [:person_id, :role_id])
  end
end

This is all we need in terms of database tables for now. Run:

mix ecto.migrate

To create the tables.

The Entity Relationship Diagram (ERD) should now look like this:

auth-erd-with-roles-permissions

Next we need to create a script that inserts the default roles and permissions during the setup of the Auth App.

Setup Default Roles & Permissions

Recommended Reading