<div dir="ltr"><div>I've gotten various feedback and I want to relay some of the changes based on that.</div><div><br></div><div>1) Pulp should ship a "user isolation" policy by default. If users want other things they can configure it further. This is a change from my original proposal of Pulp shipping an "RBAC is off" policy. This will work for Katello because all Katello calls show up as one user anyway.</div><div><br></div><div>2) We have challenges around assigning permissions. This is the proposed solution that was discussed at open floor today:  <a href="https://pulp.plan.io/issues/7210">https://pulp.plan.io/issues/7210</a>  I've added this to my pulpcore PR (link below)</div><div><br></div><div><a href="https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC">https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC</a></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jul 10, 2020 at 2:20 PM David Davis <<a href="mailto:daviddavis@redhat.com" target="_blank">daviddavis@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Wed, Jul 8, 2020 at 4:54 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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:</div><div><br></div><div>1) Move the permissions creation to the signals [done]</div><div>2) Have the user be well-known, this is accomplished by pulpcore picking up this dependency <a href="https://github.com/PaesslerAG/django-currentuser" target="_blank">https://github.com/PaesslerAG/django-currentuser</a> [done]<br></div><div>3) Have the user information persisted in tasks so signals can work there also ... there are two obvious options</div><div><br></div><div>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.<br></div></div></blockquote><div><br></div><div>Are task permissions mutable? If so, then what happens if someone kicks off a task and then this permission gets removed?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div><br></div><div>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.</div><div><br></div><div>Also I've collaborated with @alikins from galaxy_ng project and together we wrote this requirements doc for their plugin:  <a href="https://hackmd.io/JisLkfyeT2myAD2khEwU0A" target="_blank">https://hackmd.io/JisLkfyeT2myAD2khEwU0A</a></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 1, 2020 at 6:43 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">The demo advertisement for tomorrow is here:  <a href="https://www.redhat.com/archives/pulp-dev/2020-June/msg00076.html" target="_blank">https://www.redhat.com/archives/pulp-dev/2020-June/msg00076.html</a></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 1, 2020 at 6:41 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Another productive RBAC day! See the latest code at the links below. Here's what's new:</div><div><br></div><div>* policy is now shorter thanks to machinery checking both model-level and object-level permissions with one call. The other two are also available</div><div>* sync is now restricted on both 'modify_repo_content' permissions AND read permission on the remote being used to sync</div><div>* modify is now restricted on 'modify_repo_content' permission</div><div>* moved the permission checking machinery to be "global checks"</div><div>* 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)</div><div><br></div><div><a href="https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC" target="_blank">https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC</a></div><div><a href="https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC" target="_blank">https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC</a></div><div><br></div><div>Tomorrow's demo is advertised here. It will also include an overview of some of the unsolved problems with some possible solutions.</div><div><br></div><div>Cheers,</div><div>Brian</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 30, 2020 at 5:08 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Today I accomplished a few more things:</div><div><br></div><div>* finished my ldap notes: <a href="https://hackmd.io/ED9UpscNSRW86Le3xNzVeg" target="_blank">https://hackmd.io/ED9UpscNSRW86Le3xNzVeg</a></div><div>* moving the checks from a mixin to be "global checks" so they are available everywhere, this is a feature from drf-access-policy:  <a href="https://rsinger86.github.io/drf-access-policy/reusable_conditions/" target="_blank">https://rsinger86.github.io/drf-access-policy/reusable_conditions/</a></div><div>* 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</div><div><br></div><div>Need to:<br></div><div>* clean up the "sync" policy code<br></div><div>* Add global condition check facilities for the perms of a 'remote' param</div><div>* add policy language restricting the /modify/ endpoint also for FileRepository</div><div>* push my code<br></div><div><br></div><div>New Challenge: We need to also have the permissions assignments happen for objects created by tasks. django-guardian recommends this happen inside signals (<a href="https://django-guardian.readthedocs.io/en/latest/userguide/assign.html#assigning-permissions-inside-signals" target="_blank">https://django-guardian.readthedocs.io/en/latest/userguide/assign.html#assigning-permissions-inside-signals</a>). 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:</div><div><br></div><div>1. Switch the perms addition to the model itself via signals so it's automatic everywhere (including in tasks)</div><div>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.</div><div><br></div><div>Feedback is welcome!</div><div><br></div><div><br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 26, 2020 at 6:16 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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:</div><div><br></div><div>* We don't want to duplicate code, e.g. having the FileRepositoryAccessControl begin to inspect permissions for FileRemote directly, when FileRemoteAccessPolicy already does that</div><div>* Currently permissions are granted at two levels: Model-level and File-level permissions and permissions are granted from either level.</div><div>* 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.</div><div><br></div><div>All of ^ together tells me that I should work on creating two things next:</div><div>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.<br></div><div>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.</div><div><br></div><div>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.<br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jun 25, 2020 at 6:18 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Here's another push to the branch (it includes the following additions):  <a href="https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1" target="_blank">https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1</a></div><div><br></div><div>* A FileRepositoryAccessPolicy which provides RBAC for Repositories (not yet sync)</div><div>* A new Mixin allowing the two policies to share some common components</div><div><br></div><div>Next up:</div><div><div>* have the pup_file define the fileContentAdmin group programmatically</div><div>* Extend the FileRepositoryAccessPolicy to restrict sync operations</div><div>* Write up and organize the PoC into a clear, organized format</div><div><br></div><div>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:  <a href="https://django-role-permissions.readthedocs.io/en/stable/utils.html" target="_blank">https://django-role-permissions.readthedocs.io/en/stable/utils.html</a></div><div><br></div><div>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.</div><div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 24, 2020 at 5:49 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Moar progress! Today the following things got done: Today's changes are available here:  <a href="https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1" target="_blank">https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1</a></div><div><br></div><div>* 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</div><div>* 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<br></div><div>* Got permissions cleaning up on resource deletion now too</div><div><br></div><div>Next up:</div><div>* have the pup_file define the fileContentAdmin group programmatically</div><div>* Make similar policies for FileRepository which governs itself and the "sync" action</div><div>* Write up and organize the PoC into a clear, organized format</div><div><br></div><div>Questions and feedback are welcome!<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 23, 2020 at 5:54 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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.</div><div><br></div><div>Here's the actual RBAC stuff, it's all in pulp_file:   <a href="https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1" target="_blank">https://github.com/pulp/pulp_file/compare/master...bmbouter:rbac-PoC?expand=1</a></div><div>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:  <a href="https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC" target="_blank">https://github.com/pulp/pulpcore/compare/master...bmbouter:rbac-PoC</a></div><div><br></div><div>I have some "how to use notes" here:  <a href="https://hackmd.io/DRqGFyRsSDmN7E4TtOPf-w" target="_blank">https://hackmd.io/DRqGFyRsSDmN7E4TtOPf-w</a>  The idea is that it implements the FileRemote portions of this requirements docs:   <a href="https://hackmd.io/kZ1oYp8TTkeuC5KL_ffjGQ" target="_blank">https://hackmd.io/kZ1oYp8TTkeuC5KL_ffjGQ</a></div><div><br></div><div>Here is the short list of things for FileRemote that still don't work. This is mainly so I remember what to do next. :)<br></div><div>* The <a href="https://django-guardian.readthedocs.io/en/latest/api/guardian.shortcuts.html#get-objects-for-user" target="_blank">get_objects_for_user</a> 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</div><div>* It still needs "detail view" restriction. This is straightforward.<br></div><div>* 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.</div><div><br></div><div>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.<br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jun 22, 2020 at 5:14 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div># ldap PoC updates</div><div>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 <a href="https://django-auth-ldap.readthedocs.io/en/latest/example.html" target="_blank">django-auth-ldap</a> 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.<br></div><div><br></div><div># django-admin progress</div><div>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.<br></div><div><br></div><div># new resources to help us out</div><div>Through collaboration with @ttereshc and someone off list named @adelton (who actually authored <a href="https://www.adelton.com/django/external-authentication-for-django-projects" target="_blank">this reference approach</a> I referenced early on in this exploration), this very cool repository of testing tools was identified:  <a href="https://github.com/adelton/webauthinfra" target="_blank">https://github.com/adelton/webauthinfra</a>  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.<br></div><div><br></div><div># Next Steps:  back to the PoC itself</div><div>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:</div><div><br></div><div>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.</div><div>2. Write it up and share it.</div><div>3. Schedule public meeting to review it (targeting next-week)<br></div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 19, 2020 at 5:09 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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.<br></div><div><br></div><div>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.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jun 17, 2020 at 4:57 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>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.</div><div><br></div><div>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.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jun 15, 2020 at 5:03 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I got the ldap reference implementation performing auth really nicely against a test ldap with this guide:  <a href="https://www.nginx.com/blog/nginx-plus-authenticate-users/" target="_blank">https://www.nginx.com/blog/nginx-plus-authenticate-users/</a> Now there are some new challenges though:<br></div><div><br></div><div>* 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.</div><div>* we have to figure this out all again in Apache...</div><div><br></div><div>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?<br></div><div><br></div><div>I also emailed Bin Li asking for info on how their user and group management works.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jun 9, 2020 at 11:48 AM Adrian Likins <<a href="mailto:alikins@redhat.com" target="_blank">alikins@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jun 5, 2020 at 8:23 PM Brian Bouterse <<a href="mailto:bmbouter@redhat.com" target="_blank">bmbouter@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>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).<br></div><div><br></div></div></blockquote><div>Hopefully <a href="https://github.com/pulp/pulpcore/pull/705" target="_blank">https://github.com/pulp/pulpcore/pull/705</a> will be useful here.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>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:  <a href="https://www.adelton.com/django/external-authentication-for-django-projects" target="_blank">https://www.adelton.com/django/external-authentication-for-django-projects</a></div></div></blockquote><div><br></div><div>This is more or less what galaxy_ng ends up doing, at least for the scenarios where it runs hosted with external SSO. </div><div><a href="https://github.com/ansible/galaxy_ng/blob/master/galaxy_ng/app/auth/auth.py#L51" target="_blank">https://github.com/ansible/galaxy_ng/blob/master/galaxy_ng/app/auth/auth.py#L51</a> for example. </div><div> </div></div></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>
_______________________________________________<br>
Pulp-dev mailing list<br>
<a href="mailto:Pulp-dev@redhat.com" target="_blank">Pulp-dev@redhat.com</a><br>
<a href="https://www.redhat.com/mailman/listinfo/pulp-dev" rel="noreferrer" target="_blank">https://www.redhat.com/mailman/listinfo/pulp-dev</a><br>
</blockquote></div></div>
</blockquote></div>