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}]"}
    884 views
   owned this note