1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-02-06 22:00:09 +00:00
bramw_baserow/enterprise/docs/RBAC-guide.md

243 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 👩‍💻 RBAC guide
This documentation explain the general principles of the *Role based access
control* (RBAC) in Baserow. This is a technical documentation intended for
people who want to understand how RBAC works internally.
First you need to read the general `/docs/permissions-guide.md` file before
checking this one to understand the basic principles of the permission system.
## 📖 Glossary
This glossary extends the Permissions system related glossary.
**Role**: a *Role* is a set of *Operation* that can be assigned to a *Subject*.
When a *Role* is assigned to a *Subject*, this subject is granted the
*Permissions* for all *Operations* of this *Role*.
**Custom Role**: this term represents a *Role* that a *Actor* (likely admin) has
created, versus a *Role* that Baserow has created in its default set.
**Team**: a collection of *Subject* records, so that they can be managed in one
go. This would enable those with high *Role* to manage *Subjects* in bulk,
without having to assign *Role* individually to each *Subject*. A *Team* is
linked to only one *Workspace*.
**Role assignment**: an triplet that represents the assignation of a *Role* on a
*Subject* over a particular *Scope*.
**Scope**: by default, a *Role assignment* apply to all *Objects* of the
*Workspace*, but a *Role* application area can be limited to a specific *Object*
instance, the *Scope* of the *Role*. In this case, the *Permissions* granted by
the *Role* only apply to this *Object* and all its children *Objects*. The
default *Scope* for a *Role assignment* is the *Workspace*. For the `Database`
application the extra allowed *Scopes* are `Database` and `Table`.
## 📃 Main principles
These are some fondations on which the RBAC is based:
- The following structural roles exist:
- **NO_ROLE**: to remove all permissions on the given *Scope* (and all its
children by inheritance, see below).
- **NO_ROLE_LOW_PRIORITY**: same as previous but if a *Team* has a *Role* at
the same scope, the *Team* role is considered. It's necessary mostly because
we can't remove the role at the group level for a `User`.
- **VIEWER**: the set of read only operations. An operation is read only if it
doesn't modify any data in the database.
- In addition to the structural roles, a few Roles exists by default. Here's a
quick overview of their purpose:
- **ADMIN**: can do anything on the *Workspace*.
- **BUILDER**: can do anything but the permission management.
- **EDITOR**: can create/update/delete rows in Tables.
- **COMMENTER**: can only comment rows.
- An *Actor* can have different *Role assignments* at different *Scopes*
including `Workspace`, `Application` and `Table`.
- A *Team* can have different *Roles assignments* at different *Scopes*
including `Workspace`, `Application` and `Table`.
- an *Actor* can be in multiple *Teams*. These *Teams* have an influence on the
way *Roles* are determined for this *Actor*. See below for more information.
To compute the *Role* to use when deciding to allow or not a *Permission
request* the following rules are applied:
- **Rule of closest ancestor *Role***: for an operation done on a given
*Context*, the *Role assignment* on the closest ancestor of this *Context*
(including itself) is considered regardless if it's a *Team* or an *Actor*
*Role*.
- **Rule of Actor *Role* precedence**: on a given *Scope*, if there are at the
same time some *Role assignments* for the *Actor* itself and for at least one
of the *Teams* they belongs to, the *Actor* *Role* always takes precedence over
the Team *Roles* unless it's the `NO_ROLE_LOW_PRIORITY` *Role*.
- **Rule of *Team* *Roles* inheritance**: if there is no *Actor* role on a given
*Scope* or if it is `NO_ROLE_LOW_PRIORITY` then the *Operation sets* of the
*Roles* of all *Teams* are "unioned". As the result, the most permissive
*Team* *Role* wins.
- **Rule of reverse *Scope* inheritance**: when an *Actor* has a *Role
assignment* with at least one of the `VIEWER` *Operations* on a given *Scope*,
all ancestors of this *Scope* *Object* automatically gain the `VIEWER` *Role*
even if they have `NO_ROLE` assigned according to the previous rules. This
allow the *Actor* to being able to see all intermediate *Objects* and access
the child *Object*. This automatic *Role* is ignored when applying the *Rule
of closest ancestor*.
To summarize:
- Tables roles > Database roles > Workspace roles
- Actor roles > Team roles
- `NO_ROLE_LOW_PRIORITY` => use Team A roles + Team B roles + ...
- Any Role at level n -> Viewer role at level n-1
## 🎮 Examples
Given the previous rules a few examples to illustrate them:
---
**The Actor A has the following assignments**:
- BUILDER on Workspace 1
- VIEWER on Table 10 (child of Database 5)
**Result**:
- This Actor is BUILDER everywhere but VIEWER for the Table 10 and all children
of the Table 10. (Rule of closest ancestor Role)
---
**The Actor A has the following assignments**:
- BUILDER on Workspace 1
- VIEWER on Table 10 (child of Database 5)
They are in the Team T with the following assignments:
- COMMENTER on Table 10
- NO_ROLE on Table 20 (also child of Database 5)
**Result**:
- The actor is VIEWER for the Table 10 and all children of the Table 10. (Rule
of Actor Role precedence)
- The actor is NO_ROLE for the Table 20 and all children of the Table 20. (Rule
of closest ancestor Role)
- This Actor is BUILDER everywhere else. (Rule of closest ancestor Role)
---
**The Actor A has the following assignments**:
- VIEWER on Workspace 1
They are in the Team T1 with the following assignments:
- COMMENTER on Table 10
They also are in the Team T2 with the following assignments:
- BUILDER on Table 10
**Result**:
The actor is BUILDER for the Table 10 and all children of the Table 10. (Rule of
Team Roles inheritance) This Actor is VIEWER everywhere else. (Rule of most
precise role)
---
**The Actor A has the following assignments**:
- NO_ROLE on Workspace 1
They are in the Team T1 with the following assignments:
- COMMENTER on Workspace 1
They also are in the Team T2 with the following assignments:
- BUILDER on Workspace 1
**Result**:
This Actor is NO_ROLE everywhere. (Rule of Actor Role precedence)
---
**The Actor A has the following assignments**:
- NO_ROLE_LOW_PERMISSION on Workspace 1
They are in the Team T1 with the following assignments:
- COMMENTER on Workspace 1
They also are in the Team T2 with the following assignments:
- BUILDER on Workspace 1
**Result**:
This Actor is COMMENTER and BUILDER everywhere (so BUILDER as it is the most
permissive). (Rule of Team Roles inheritance)
---
**The Actor A has the following assignments**:
- NO_ROLE on Workspace 1
- EDITOR on Table 10 (child of Database 5)
**Result**:
- The actor is EDITOR for the Table 10 and all children of the Table 10. (Rule
of closest ancestor Role)
- The Actor is VIEWER for the Database 5, the Application 5 and the Workspace 1.
(Rule of reverse Scope inheritance)
- This Actor is NO_ROLE everywhere else. (Rule of closest ancestor Role)
## ⚙️ Technical details
If you want to give a particular *Actor* a *Role* on a given *Scope* you have to
create a `RoleAssignment`. This is the central object of the RBAC system. The
whole information necessary to check a Permission request is stored in this
object. Here's the data model:
![Data model](./RBACDataModel.jpg)
[source](https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1&title=Diagramme%20sans%20nom.drawio#R7Zpbj5s4GIZ%2FTaRupVZgQxIuk8wkXW13t2patdOblQe%2BAB2DkXFO%2FfU1YALE5FBtJpnp5CbCr83Jz%2Fu9spN08ChaTThJgr%2BZB7SDDG%2FVwTcdhBzbkp%2BZsC6ErokLweehV0hmJUzDH6BEQ6nz0IO0MVAwRkWYNEWXxTG4oqERztmyOWzGaPOuCfFBE6Yuobr6JfREUKh91Kv0dxD6QXlns%2BsUPREpB6s3SQPisWVNwrcdPOKMieIoWo2AZnNXzktx3nhH7%2BbBOMTimBM%2BL3FkTpbf6Oi9CCDwPiw%2BfnujXmNB6Fy98ARi4KE7Zly%2BVvwXrNXTi3U5JeDJGVJNxkXAfBYTelupQ87msQfZfQ3Zqsa8ZyyRoinF7yDEWuEmc8GkFIiIql5YheJr7fguu9RbW7VuVurKeWNdNmLB11%2FrjdpZWbM6LW9V53mDzCiyGbMYCmUcUqr6KbkHOiTug5%2B%2F1ohRxquxqeDsAUqxg3Cv3x8MsOyZsViUugczMqcS01CnpkCmbM5d2IOqdD%2FhPog941R9ZZRqN1CemACLQL69HKAq9I3x1uiVplVFWlqWAyUiXDRLgaiK8jeX2lz9AwvlW1VD2GyWymetuVIe1B6iknKv%2FoJvTc23HxmFQZpKz0bZ1G6btrJk5qllEAqYJiSf8KUMrqb99iOfSW%2FUgA%2FRyBkMj7aC1K2u5dg3%2B8ywAC5gdQw%2BXAalQmf2kHR8riyrvDKxGhXUssq2dwNt8PpVOF0NTgd1c%2Fd74UIe%2BtlhS850VYWMa8Ou6fM00gcdmT7mS0gfpBl8Or%2F%2Fni0%2FkPHqcwq8g%2BSFjU9Aoj9eTBJtB1Hf0GOo1xJDlvFIMYR1Si5LIGP0hfGHNJ%2F0HNQgSWjoSrOxWJEj9xReDjq7d5jdhtNZ2PUvmftV1t%2FVeg7lfhX1d42kf965b504948O9WPtE4wm%2Fp3z7p%2FR8NN%2Ff%2BLpcjVej8uAfvrLhv0g1a3M3p7y3xUkrTxO5oHWWT8X8n0PubUjeDERji27EeGOnuDdcwa4%2FVwC%2FKkE7bHb%2B4sFbevTOFrVvdbASweLJqfmrLaUk5IIlVtD2XTlbMpFNR5m9SAXanSgOqLQ83LrtBVy004787PKWeScphbR1nJqszQ%2BUIz4sYrR1L8uuWJCFnpqmPR95RUTwuVPCOXmpHtpTPrG0ny%2BmPLF5QkwbbBsvsW5NCZ9RXjFhOzt0Ls4JvuK6YjQw%2BfDtHtv16D0bwJcfWX2fPZYGoEWTrsXDP1m7bTssZxH2mO1MtED7vdYLvwvSLjfOwTprIWj%2F8J%2BhYQs62AlnQiSbFZ%2FsSh%2B%2F6n%2Bp4JvfwI%3D)
We can see that the Subject and Scope are two Django GenericForeign keys as they
can be different kind of objects.
When we want to assign a Role, we have to:
- set the `GroupUser.permissions` property to the Role UID, if the Actor is a
`User` and the Scope of the Role assignment is the Workspace. This behavior
helps to keep the compatibility between the `RolePermissionManagerType` and
the `BasicPermissionManagerType`
- otherwise, create a new RoleAssignment object with the given data.
Then when we want to check a Permission request the `RolePermissionManagerType`
and the role `handler` are responsible to implement the rules listed in the Main
principle section.
## 🤔 A few considerations
- There are no automatic deletion cascades for the two GenericForeignKeys of a
`RoleAssignment`, so we have manually added the related model delete signals
handler to propagate a deletion when a *Subject* or a *Scope* linked to
`RoleAssignment` is deleted.
**TBD**:
- The roles endpoint is missing in the RBAC land.
- Some naming are bad and should be changed.
- Use the `HierarchicalMixin` instead of the `ObjectScopeType`.
- The system is almost ready to support Custom roles creation.
- We should add a page that shows for each object of a workspace, which role
have the Actors to help users on debugging their role assignments.
- For now the real time update for permission is partially implemented. The user
just has a message to tell them they have to refresh it's page to get the new
permissions. It could be a bit more reactive without having the user to
refresh the page.