slides: https://hackmd.io/@pulp/SJrjjX8RI#/
[pulpcore code](https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC)
[pulp_file code](https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC)
---
## Architecture
```graphviz
digraph {
compound=true
rankdir=LR
graph [ fontname="Source Sans Pro", fontsize=20 ];
node [ fontname="Source Sans Pro", fontsize=18];
edge [ fontname="Source Sans Pro", fontsize=12 ];
user -> "drf-access-policy"[label="Request"];
"drf-access-policy" -> "task code"[label="Dispatch"];
subgraph cluster_1 {
label="Pulp";
subgraph cluster_2 {
label="Viewset";
"drf-access-policy";
}
subgraph cluster_3 {
label="Database";
Users;
Groups;
}
subgraph cluster_4 {
label="Permission Checking Machinery";
has_model_level_perms;
"...";
has_obj_level_perms;
}
subgraph cluster_5 {
label="Task";
"task code";
}
"drf-access-policy" -> has_model_level_perms;
"drf-access-policy" -> has_obj_level_perms;
"task code" -> has_model_level_perms;
"task code" -> has_obj_level_perms;
has_model_level_perms -> Users;
has_model_level_perms -> Groups;
has_obj_level_perms -> Users;
has_obj_level_perms -> Groups;
}
}
```
---
## Permissions
Three types:
* Model permissions
* Django provided, built-in
* Object-level permissions
* django-guardian provides
* reuse Django built-in permissions
* Custom Permissions
* django-guardian provides, custom names
---
## Model Permissions
Four types per model:
* add_modelname
* view_modelname
* change_modelname
* delete_modelname
Created automatically by Django
Scoped by Django Application (in the db)
Available already: Permission.objects.all()
---
## Model Permissions Example
4 types:
* file.add_fileremote
* file.view_fileremote
* file.change_fileremote
* file.delete_fileremote
---
## Object Level Permissions
django-guardian facilities
* [Assign Obj Permissions](https://django-guardian.readthedocs.io/en/latest/userguide/assign.html#assign-obj-perms)
* [Check Obj Permissions](https://django-guardian.readthedocs.io/en/latest/userguide/check.html#standard-way)
* [Remove Obj Permissions](https://django-guardian.readthedocs.io/en/latest/userguide/remove.html)
---
## Custom Permissions
Any model can define a custom permission.
[pulp_file defines "Modify Content"](https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC#diff-7b38205db1c4e6004b1a30ea0a2db477R54)
---
## Users and Groups
* Always stored in Django's DB
* Needed in DB so permissions can be related to them
* Django Admin used to view/modify users, groups, membership, and permissions
* is_staff=True needed for anyone to access Django Admin
---
## External Users/Groups
Pulp is agnostic to how groups are "brought in":
* Via django apps themselves, e.g.[django-auth-ldap](django-auth-ldap.readthedocs.io)
* Here's a whole doc on that: https://hackmd.io/ED9UpscNSRW86Le3xNzVeg
* In the webserver
* Example: [saml, kerberos, openID](https://github.com/adelton/webauthinfra)
* [Headers carrying data to Pulp from Webserver](https://www.freeipa.org/page/Environment_Variables#Proposed_Additional_Variables)
Not limited to a single one per installation
* Allowed to mix, e.g. use ldap, but also have "local" users/groups just for this Pulp installation
---
## Pulpcore changes
* enable django-guardian
* runs a few migrations of its own
* enable django admin at /admin/
* adds data migration to add 'admin' users and set is_staff=True
https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC
---
## drf-access-policy
Policy is made up of policy statements.
Each statement consists of a 4-tuple
* principal - Who
* action - What
* effect - allow/deny
* condition - extra requirements ... this contains most logic
https://rsinger86.github.io/drf-access-policy/statement_elements/
---
### PoC Requirements
https://hackmd.io/kZ1oYp8TTkeuC5KL_ffjGQ
---
## An Example Policy
[FileRemoteAccessPolicy](https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC#diff-b8a33258feb0183716da827efd0b4102R22-R76)
[FileRepositoryAccessPolicy]()
---
A whole doc with commands to test with assuming:
3 users: Alice, Bob, and Eve
Alice is a fileGlobalAdmin
Bob at the user-level gets: ["file.add_fileremote", "file.add_filerepository"]
Eve gets nothing ... Eve is evillllllll
Now try out a lot of commands:
https://hackmd.io/DRqGFyRsSDmN7E4TtOPf-w
---
## Things Missing: Part 1
Requirement: Need to assign object-level permissions inside of tasks
Problem: Duplicates the object-level permissions between tasks and view sets
Proposed Resolution:
1. Move to be signals based. [django-guardian recommends this](https://django-guardian.readthedocs.io/en/latest/userguide/assign.html#assigning-permissions-inside-signals).
2. Preserve the request's user/group context into the tasking system also
---
### Things Missing: Part 2
Requirement: Permissions are assigned at either the group or user level, whatever is granting the user the permission to use that object.
Problem: Currently they are only assigned at the "user" level.
Proposed Resolution:
1. Add in some centralized machinery that will inspect how the user received their necessary permissions and then have new permissions assignment use that
---
### Things Missing: Part 3
Requirement: An API to view all effective permissions.
Question: is this still needed, given that queryset scoping is in-place.
{"metaMigratedAt":"2023-06-15T10:02:48.969Z","metaMigratedFrom":"YAML","title":"RBAC Architecture and Proof of Concept (PoC)","breaks":true,"description":"Review of the Pulp3 RBAC PoC","contributors":"[{\"id\":\"dc40d541-bddd-4823-82c8-6e5276fe233a\",\"add\":8934,\"del\":3098}]"}