There are primarily two classes of actions that need to be authorized
- Performing an action against a specific resource
- Retrieving all resources subject is authorized to access
subject- entity performing the action (org,user, ortoken)resource- object being accessed (bucket,dashboard,org, etc)action- the mode of access (readandwrite, although we could add more over time)
An access control list is stored for each resource. The list contains the subject type, subject id, and set of actions allowed.
As an example consider the table below
| ResourceType | ResourceID | SubjectType | SubjectID | Actions |
|---|---|---|---|---|
| Dashboard | 1 | User | 1 | write |
| Dashboard | 1 | Token | 1 | read |
In this example, the following statements are true
User 1is grantedwriteaccess toDashboard 1.Token 1is grantedreadaccess toDashboard 1.
It is possible however for access to be granted transitively through an organization.
For example, consider the following table
| ResourceType | ResourceID | SubjectType | SubjectID | Actions |
|---|---|---|---|---|
| Dashboard | 1 | Org | 2 | read,write |
| Org | 2 | User | 3 | read |
In this example, the following statements are true
Org 2is grantedread,writeaccess toDashboard 1User 3is grantedreadaccess toOrg 2.User 3is grantedreadaccess toDashboard(transitively throughOrg 2's access grant).
This transitive can be applied to both users and tokens (potentially to organizations as well if we that was a desirable feature).
This model can be extended by addings a roles or groups subject type and is commonly referred to as access control groups (ACG or ACLg).
It should be noted that this model is functionally equivalent to a minimal role based access control model See the role based acces control document section on ACLg.
In addition to storing an ACL for each resource, we store an Inverse ACL (IACL) so that given a subject and a resource type, we can retrieve the list of all scan the list for all resources of the resource type provided.
For example consider the table below
| SubjectType | SubjectID | ResourceType | ResourceID |
|---|---|---|---|
| User | 1 | Dashboard | 2 |
| User | 1 | Dashboard | 3 |
| User | 4 | Dashboard | 3 |
In this example
User 1has access to the list ofDashboard 2andDashboard 3.User 4has access to the list ofDashboard 3.
Just as in the ACL, a subject may have access transitively though an organization.
For example, consider
| SubjectType | SubjectID | ResourceType | ResourceID |
|---|---|---|---|
| Org | 1 | Dashboard | 2 |
| User | 3 | Dashboard | 4 |
| User | 3 | Org | 1 |
In this example
Org 1has access to the list ofDashboard 2User 3has access to the list ofDashboard 4andDashboard 2(transitively thoughOrg 1)
Implementers will have to take care to ensure that duplicate resources are not returned when constructing the list of all resources a subject can access.
Conceptually, the ACL and IACL described above can be thought of as a table
| ResourceType | ResourceID | SubjectType | SubjectID | Actions |
|---|
With two compound indexes.
- ACL - index of
(ResourceType, ResourceID, SubjectType, SubjectID) - IACL - index of
(SubjectType, SubjectID, ResourceType, ResourceID)
// TODO(desa) Tokens have a set of permissions, those permissions are used to create entries into the ACL and IACL.
Upon revokation, each entry of a tokens entries in the ACL and IACL is removed. Provided that token revocation should be relatively rare, the cost of this opperation should not be an issue. If it becomes an issue, we can simply note at a higher level that the token is no longer valid and reject the request at a different level and clean up revoked token log entries as a background task.
// TODO(desa) Orgs and users will have to be added and removed to resources through an endpoint associated with the resource
possibly something along the lines of /dashboards/:id/access (this will only work for orgs or users)
When a resource is created, if an org is provided with that request, that org will be come the owner of that resource. If no org is provided, then the resource will be owned by the user issuing the request