On Thu, Jul 9, 2020 at 11:20 PM Brian Bouterse <bmbou...@redhat.com> wrote: > > This is all done. I've pushed my code to the links below. You can now use > get_current_authenticated_user in both viewsets and tasks and it will give > you the user, which lets you use signals to automatically add object-level > permissions anywhere automatically. Also tasks have RBAC themselves > (including cancelation and deletion restriction), and support queryset > filtering. > > https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC > https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC > > Here are a few random topics I've been thinking about: > > ## What should the default policy be? > > I propose Pulp ship with a very permissive policy, and this is effectively > with RBAC off (also a requirement, e.g. Katello's usage). Each viewset would > have an AccessPolicy but it would by default ship with the following single > rule which allows everything. > > { > "action": ["*"], > "principal": "authenticated", > "effect": "allow", > }
I think, we can satisfy Katello as well with a very restrictive policy. They are using the one and only available account who happens to be admin anyway. > > ## How can we adopt user-controllable policies? > > The highest goal here is to have users in total control of the policy. This > is in-line with what drf-access-policy recommends: > https://rsinger86.github.io/drf-access-policy/loading_external_source/ > > I propose we store the json policy for each Viewset, e.g. > FileRemoteAccessPolicy which governs File Remotes as a blob that can by > editable via the API itself. This allows us to ship a simple policy like ^ > and allow users to do what they want. We can provide many example policies > also. > > [idea] We could make a sub-resource called "access_policy" so for FileRemote > for example you could read the policy here: > > GET /pulp/api/v3/remotes/file/file/access_policy > PUT /pulp/api/v3/remotes/file/file/access_policy > > It would not support PATCH because we don't allow partial policy changes, > it's one blob. It wouldn't support DELETE because there is always a policy. > It wouldn't support POST because you're modifying a resource in-place. > > ## Requirements driving this > > In my discussions with galaxy_ng their deployment on the cloud versus > on-premise will need a drastically different policy. This tells me that we > need pluggable policies at initial launch. > > ## My main concerns at this point: > > 1) Galaxy_ng also needs flexibility between their cloud versus on-premise > deployment regarding what the obj-level permissions created are. If ^ is > implemented the user can have total control over the policy, but zero control > over what permissions are assigned to newly created objects. For example that > happens in this signal here: > https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC?expand=1#diff-bdb7fbb7c563d6651a309aff97001cb6R8-R12 > > 2) Also can an admin "fix" object-level permissions? Right now they are only > in the DB. I suspect the answer is for us to turn on more django-guardian > admin integration: > https://github.com/django-guardian/django-guardian#admin-integration > > I have to think about this last part more... Meanwhile I plan to go forward > with the user-controllable policies next. Input and feedback is welcome. > > Cheers, > Brian > > > > > On Wed, Jul 8, 2020 at 4:53 PM Brian Bouterse <bmbou...@redhat.com> wrote: >> >> My next goal is to have object-level permissions assigned through signals so >> that anywhere you save the model the permissions are correctly created. To >> do this I need to get a few things working: >> >> 1) Move the permissions creation to the signals [done] >> 2) Have the user be well-known, this is accomplished by pulpcore picking up >> this dependency https://github.com/PaesslerAG/django-currentuser [done] >> 3) Have the user information persisted in tasks so signals can work there >> also ... there are two obvious options >> >> option a) Have tasks themselves have RBAC which we know we need anyway, then >> query the RBAC permissions inside a task to determine which user has the >> object level permissions for this task. This is what I'm currently >> prototyping. It at least will provide a mechanism we can use for now until >> we find something better. >> >> option b) Add a user field to the Task itself and have the RBAC assign >> permissions to them. The concern with this is that while this is nice, it >> would be nicer if we had this type of visibility on everything in Pulp from >> an auditing project dedicated to keeping this type of info. Option (b) is >> still viable, just maybe not the best way. Comments/feedback is welcome. >> >> Also I've collaborated with @alikins from galaxy_ng project and together we >> wrote this requirements doc for their plugin: >> https://hackmd.io/JisLkfyeT2myAD2khEwU0A >> >> On Wed, Jul 1, 2020 at 6:43 PM Brian Bouterse <bmbou...@redhat.com> wrote: >>> >>> The demo advertisement for tomorrow is here: >>> https://www.redhat.com/archives/pulp-dev/2020-June/msg00076.html >>> >>> On Wed, Jul 1, 2020 at 6:41 PM Brian Bouterse <bmbou...@redhat.com> wrote: >>>> >>>> Another productive RBAC day! See the latest code at the links below. >>>> Here's what's new: >>>> >>>> * policy is now shorter thanks to machinery checking both model-level and >>>> object-level permissions with one call. The other two are also available >>>> * sync is now restricted on both 'modify_repo_content' permissions AND >>>> read permission on the remote being used to sync >>>> * modify is now restricted on 'modify_repo_content' permission >>>> * moved the permission checking machinery to be "global checks" >>>> * added data migration that sets is_staff=True, so the django-admin >>>> interface can be used (this is getting a slight rework tomorrow morning >>>> tho) >>>> >>>> https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC >>>> https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC >>>> >>>> Tomorrow's demo is advertised here. It will also include an overview of >>>> some of the unsolved problems with some possible solutions. >>>> >>>> Cheers, >>>> Brian >>>> >>>> >>>> On Tue, Jun 30, 2020 at 5:08 PM Brian Bouterse <bmbou...@redhat.com> wrote: >>>>> >>>>> Today I accomplished a few more things: >>>>> >>>>> * finished my ldap notes: https://hackmd.io/ED9UpscNSRW86Le3xNzVeg >>>>> * moving the checks from a mixin to be "global checks" so they are >>>>> available everywhere, this is a feature from drf-access-policy: >>>>> https://rsinger86.github.io/drf-access-policy/reusable_conditions/ >>>>> * added a has_obj_or_module_perms method allowing policy writers to just >>>>> use that instad of carrying "two entries" in the policy, one for >>>>> model-level, one for object-level >>>>> >>>>> Need to: >>>>> * clean up the "sync" policy code >>>>> * Add global condition check facilities for the perms of a 'remote' param >>>>> * add policy language restricting the /modify/ endpoint also for >>>>> FileRepository >>>>> * push my code >>>>> >>>>> New Challenge: We need to also have the permissions assignments happen >>>>> for objects created by tasks. django-guardian recommends this happen >>>>> inside signals >>>>> (https://django-guardian.readthedocs.io/en/latest/userguide/assign.html#assigning-permissions-inside-signals). >>>>> The challenge (thanks @mdellweg for identifying) is that the user/group >>>>> context information is well-known in the viewset but not in a task. >>>>> Soooooo ... the idea is: >>>>> >>>>> 1. Switch the perms addition to the model itself via signals so it's >>>>> automatic everywhere (including in tasks) >>>>> 2. Preserve the user and group "request context" into the tasking system. >>>>> I can see a straightforward path to how to do this so I plan to prototype >>>>> this soon also. >>>>> >>>>> Feedback is welcome! >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On Fri, Jun 26, 2020 at 6:16 PM Brian Bouterse <bmbou...@redhat.com> >>>>> wrote: >>>>>> >>>>>> Today I got the "sync" RBAC working, but I need to give it some more >>>>>> thought. The extra challenge with this parts is that "having permission >>>>>> to read a Remote" is already defined in one place, on >>>>>> FileRemoteAccessPolicy, yet the AccessPolicy that needs to perform the >>>>>> enforcement is FileRepositoryAccessPolicy for its "sync" action. This is >>>>>> a bit challenging considering the following goals: >>>>>> >>>>>> * We don't want to duplicate code, e.g. having the >>>>>> FileRepositoryAccessControl begin to inspect permissions for FileRemote >>>>>> directly, when FileRemoteAccessPolicy already does that >>>>>> * Currently permissions are granted at two levels: Model-level and >>>>>> File-level permissions and permissions are granted from either level. >>>>>> * We want to keep the policy in charge. If we start to bury the behavior >>>>>> in methods and functions then policy writers are no longer in control. >>>>>> >>>>>> All of ^ together tells me that I should work on creating two things >>>>>> next: >>>>>> 1) A way for policy writers to express which parameter refers to objects >>>>>> that also need their permissions checked. For example the policy should >>>>>> be able to say "remote is a parameter and it needs X permission". This >>>>>> is akin to the has_module_level_perms and has_obj_level_perms here >>>>>> except we also need to identify which parameter is being checked instead >>>>>> of the object the AccessPolicy itself governs. >>>>>> 2) A single way to check model-level and object-level permissions at >>>>>> once and allow if *either* passes. We would still allow policy writers >>>>>> to call either model-level or file-level checks also. >>>>>> >>>>>> I'll work on ^ next. Ideas and feedback are welcome. I pushed no new >>>>>> code today because it's a mess and not runnable at my stopping point. >>>>>> >>>>>> >>>>>> On Thu, Jun 25, 2020 at 6:18 PM Brian Bouterse <bmbou...@redhat.com> >>>>>> wrote: >>>>>>> >>>>>>> Here's another push to the branch (it includes the following >>>>>>> additions): >>>>>>> https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1 >>>>>>> >>>>>>> * A FileRepositoryAccessPolicy which provides RBAC for Repositories >>>>>>> (not yet sync) >>>>>>> * A new Mixin allowing the two policies to share some common components >>>>>>> >>>>>>> Next up: >>>>>>> * have the pup_file define the fileContentAdmin group programmatically >>>>>>> * Extend the FileRepositoryAccessPolicy to restrict sync operations >>>>>>> * Write up and organize the PoC into a clear, organized format >>>>>>> >>>>>>> Also of interest today @ttereshc and I had a great convo asking what to >>>>>>> do about potential problems when we use Django groups to be a "role". >>>>>>> My write up will address this in more detail than I can go into here. >>>>>>> We are also looking at what the django-role-permissions project could >>>>>>> offer us: >>>>>>> https://django-role-permissions.readthedocs.io/en/stable/utils.html >>>>>>> >>>>>>> I expect the PoC to be done by tomorrow and write-up by Monday, so I'm >>>>>>> going to schedule the public review meeting for next week towards the >>>>>>> end of the week. >>>>>>> >>>>>>> >>>>>>> On Wed, Jun 24, 2020 at 5:49 PM Brian Bouterse <bmbou...@redhat.com> >>>>>>> wrote: >>>>>>>> >>>>>>>> Moar progress! Today the following things got done: Today's changes >>>>>>>> are available here: >>>>>>>> https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1 >>>>>>>> >>>>>>>> * Got scoped querysets working! This restricts list views to only show >>>>>>>> objects a user has permissions to view. A db reset was all that was >>>>>>>> needed I think I didn't have all the changes in when I applied my >>>>>>>> earlier migrations >>>>>>>> * Added "detail view" restriction, and while it's in the policy and >>>>>>>> working DRF does a strange thing on "retrieve" where if it's not in >>>>>>>> the queryset (due to scoping ^) the user receives a 404, not a >>>>>>>> permission denied >>>>>>>> * Got permissions cleaning up on resource deletion now too >>>>>>>> >>>>>>>> Next up: >>>>>>>> * have the pup_file define the fileContentAdmin group programmatically >>>>>>>> * Make similar policies for FileRepository which governs itself and >>>>>>>> the "sync" action >>>>>>>> * Write up and organize the PoC into a clear, organized format >>>>>>>> >>>>>>>> Questions and feedback are welcome! >>>>>>>> >>>>>>>> On Tue, Jun 23, 2020 at 5:54 PM Brian Bouterse <bmbou...@redhat.com> >>>>>>>> wrote: >>>>>>>>> >>>>>>>>> Lots of progress today! I have a mostly-complete policy for RBAC for >>>>>>>>> FileRemote. It's surprising how little code all of this ended up >>>>>>>>> being. >>>>>>>>> >>>>>>>>> Here's the actual RBAC stuff, it's all in pulp_file: >>>>>>>>> https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1 >>>>>>>>> Here's the parts that go in core. Note the LDAP stuff is all >>>>>>>>> optional, the only real requirement are two lines 1) enabling >>>>>>>>> guardian in INSTALLED_APPS and 2) adding it as an >>>>>>>>> AuthenticationBackend: >>>>>>>>> https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC >>>>>>>>> >>>>>>>>> I have some "how to use notes" here: >>>>>>>>> https://hackmd.io/DRqGFyRsSDmN7E4TtOPf-w The idea is that it >>>>>>>>> implements the FileRemote portions of this requirements docs: >>>>>>>>> https://hackmd.io/kZ1oYp8TTkeuC5KL_ffjGQ >>>>>>>>> >>>>>>>>> Here is the short list of things for FileRemote that still don't >>>>>>>>> work. This is mainly so I remember what to do next. :) >>>>>>>>> * The get_objects_for_user from DjangoGuardian I don't think it likes >>>>>>>>> Master/Detail or maybe it's how/where I'm using it. I haven't yet >>>>>>>>> debugged this. For this reason it doesn't provide list restriction >>>>>>>>> * It still needs "detail view" restriction. This is straightforward. >>>>>>>>> * The group should be programmatically defined, in this case it was >>>>>>>>> "defined in LDAP". It could *also* live in LDAP (or other external >>>>>>>>> group definition system) but the plugin builds permissions off of it >>>>>>>>> so it should also define it. This is easy. >>>>>>>>> >>>>>>>>> Feedback is welcome. I'm going to continue building this and then >>>>>>>>> schedule a public review of FileRemote, Content modification for file >>>>>>>>> repos, and sync restriction next week. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On Mon, Jun 22, 2020 at 5:14 PM Brian Bouterse <bmbou...@redhat.com> >>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>> # ldap PoC updates >>>>>>>>>> Now users, groups, and group membership are populating from ldap >>>>>>>>>> automatically on login (with auth backed by ldap also)! I'll be >>>>>>>>>> sharing my configs for both ldap and how to configure >>>>>>>>>> django-auth-ldap here soon in an organized way. This was done with >>>>>>>>>> django-auth-ldap and 0 customization to pulp code. It's 100% enabled >>>>>>>>>> through settings so this work is more of an approach we can document >>>>>>>>>> for users that they can enable and not a feature Pulp ships itself. >>>>>>>>>> >>>>>>>>>> # django-admin progress >>>>>>>>>> Thanks to @alikins existing PRs, I got django admin enabled and able >>>>>>>>>> to view/edit users, groups, group membership, and permissions at >>>>>>>>>> both the user and group levels. This is important because this will >>>>>>>>>> be the primary mechanism of administrators. This part is looking >>>>>>>>>> good. >>>>>>>>>> >>>>>>>>>> # new resources to help us out >>>>>>>>>> Through collaboration with @ttereshc and someone off list named >>>>>>>>>> @adelton (who actually authored this reference approach I referenced >>>>>>>>>> early on in this exploration), this very cool repository of testing >>>>>>>>>> tools was identified: https://github.com/adelton/webauthinfra It >>>>>>>>>> has a treasure trove of testing containers which Pulp devs in the >>>>>>>>>> future can test against. It keeps the user/group check in the apache >>>>>>>>>> which is fine alternative to the django-auth-ldap approach above. >>>>>>>>>> Pulp doesn't have to choose, it could work with either just >>>>>>>>>> configured differently. The pending PoC outline will go over these >>>>>>>>>> alternative approaches in detail. >>>>>>>>>> >>>>>>>>>> # Next Steps: back to the PoC itself >>>>>>>>>> Now that we have demonstrated good options of external >>>>>>>>>> users/groups/membership loading into Pulp we can confidently move >>>>>>>>>> back to finishing the RBAC PoC itself. I've started back into this. >>>>>>>>>> So the remaining work are the two steps below: >>>>>>>>>> >>>>>>>>>> 1. Finish the PoC that uses RBAC to restrict remotes, sync, and >>>>>>>>>> repository content modification. Currently I prototyped restriction >>>>>>>>>> of operations on Remotes, but I need to replicate the access >>>>>>>>>> policies to Repositories and Sync next. >>>>>>>>>> 2. Write it up and share it. >>>>>>>>>> 3. Schedule public meeting to review it (targeting next-week) >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Fri, Jun 19, 2020 at 5:09 PM Brian Bouterse <bmbou...@redhat.com> >>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>> I got the LDAP users both authenticating and importing into Pulp! >>>>>>>>>>> Next I'll do the groups and then I think the ldap parts will be >>>>>>>>>>> done. >>>>>>>>>>> >>>>>>>>>>> FYI: I'm going to write up the implementation design and have that >>>>>>>>>>> come with this proof of concept code . This will let us know what >>>>>>>>>>> choices it makes, why it makes them, and we can determine if these >>>>>>>>>>> are the right choices together. >>>>>>>>>>> >>>>>>>>>>> On Wed, Jun 17, 2020 at 4:57 PM Brian Bouterse >>>>>>>>>>> <bmbou...@redhat.com> wrote: >>>>>>>>>>>> >>>>>>>>>>>> I got a lot further on this today. I have the test ldap setup with >>>>>>>>>>>> several test users and groups. I have django-auth-ldap configured >>>>>>>>>>>> mostly authenticating username/password against ldap instead of >>>>>>>>>>>> the internal database first. Once that is fully working the users >>>>>>>>>>>> will auto-populate into django and the groups should follow easily. >>>>>>>>>>>> >>>>>>>>>>>> Once that's done I'll be unblocked to finish the RBAC PoC. The >>>>>>>>>>>> rest of the parts are straightforward given the testing I've >>>>>>>>>>>> already done. More updates to come. >>>>>>>>>>>> >>>>>>>>>>>> On Mon, Jun 15, 2020 at 5:03 PM Brian Bouterse >>>>>>>>>>>> <bmbou...@redhat.com> wrote: >>>>>>>>>>>>> >>>>>>>>>>>>> I got the ldap reference implementation performing auth really >>>>>>>>>>>>> nicely against a test ldap with this guide: >>>>>>>>>>>>> https://www.nginx.com/blog/nginx-plus-authenticate-users/ Now >>>>>>>>>>>>> there are some new challenges though: >>>>>>>>>>>>> >>>>>>>>>>>>> * Great that we can auth users, but we need nginx to >>>>>>>>>>>>> extract-and-forward the group information to Pulp itself. That >>>>>>>>>>>>> way a middleware can create the user AND group info in the >>>>>>>>>>>>> backend. >>>>>>>>>>>>> * we have to figure this out all again in Apache... >>>>>>>>>>>>> >>>>>>>>>>>>> Maybe we should be integrating Pulp directly against >>>>>>>>>>>>> django-auth-ldap [0]. I am going to try that next. The work I've >>>>>>>>>>>>> done isn't 100% reusable there, but most of it is because the >>>>>>>>>>>>> test server and configs I used can all be reused directly with >>>>>>>>>>>>> django-auth-ldap. The concern with this approach is that we would >>>>>>>>>>>>> be supporting LDAP (and transitively Active Directory) but are >>>>>>>>>>>>> there other directory services Pulp needs to support? >>>>>>>>>>>>> >>>>>>>>>>>>> I also emailed Bin Li asking for info on how their user and group >>>>>>>>>>>>> management works. >>>>>>>>>>>>> >>>>>>>>>>>>> On Tue, Jun 9, 2020 at 11:48 AM Adrian Likins >>>>>>>>>>>>> <alik...@redhat.com> wrote: >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Fri, Jun 5, 2020 at 8:23 PM Brian Bouterse >>>>>>>>>>>>>> <bmbou...@redhat.com> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> 1) django admin (the built in django UI) will be the mechanism >>>>>>>>>>>>>>> administrators use to assign permissions to users and groups. >>>>>>>>>>>>>>> This means the use of django admin with pulp is very likely (to >>>>>>>>>>>>>>> me). >>>>>>>>>>>>>>> >>>>>>>>>>>>>> Hopefully https://github.com/pulp/pulpcore/pull/705 will be >>>>>>>>>>>>>> useful here. >>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> 2) externally defined users and groups will need to be >>>>>>>>>>>>>>> "replicated" to django's db at login time, probably using >>>>>>>>>>>>>>> headers from the webserver This is consistent w/ the approach >>>>>>>>>>>>>>> recommended here: >>>>>>>>>>>>>>> https://www.adelton.com/django/external-authentication-for-django-projects >>>>>>>>>>>>>> >>>>>>>>>>>>>> >>>>>>>>>>>>>> This is more or less what galaxy_ng ends up doing, at least for >>>>>>>>>>>>>> the scenarios where it runs hosted with external SSO. >>>>>>>>>>>>>> https://github.com/ansible/galaxy_ng/blob/master/galaxy_ng/app/auth/auth.py#L51 >>>>>>>>>>>>>> for example. >>>>>>>>>>>>>> > > _______________________________________________ > Pulp-dev mailing list > Pulp-dev@redhat.com > https://www.redhat.com/mailman/listinfo/pulp-dev _______________________________________________ Pulp-dev mailing list Pulp-dev@redhat.com https://www.redhat.com/mailman/listinfo/pulp-dev