Fixes #TBFL - Taxonomy-level permission enforcement #10652
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I might be away from work for a couple of weeks, so I'm opening this as a draft for the time being to remember what I wanted to do here and hopefully spark some discussion in the meantime.
TL; DR
If a role has organizations or locations assigned, the permissions granted by that role apply only in the context of those organizations/locations.
"Steps to reproduce"-styled example
AllowedForbiddenOrganization adminrole intoAllowed Organization adminand assign the clone to organizationAllowedForbiddenBehaviour before the changes:
Infrastructure > Subnetsmenu item in both organizations (and any)Infrastructure > Subnetsin both organizations (and any)Behaviour after the changes:
Infrastructure > Subnetsmenu item in organizationAllowedand in anyForbiddenorganizationInfrastructure > Subnetsin in organizationAllowedand in anyForbiddenorganization, the user gets an error page stating that the user does not haveview_subnetspermission in the current organization and location scopeBackground
Foreman comes with a RBAC system that can be leveraged to have fine-grained control over which actions can be performed by users. The essential model is that individual permissions are linked to roles, users are assigned to roles and users are granted permissions through their roles.
Roles can be assigned to organizations and locations. There is an assumption that if a role is assigned to a taxonomy (organization or location) it applies only in the scope of that taxonomy - a clone of
Organization adminrole assigned to organizationAllowedshould grant permissions over the entirety of theAllowedorganization, but not outside of it. This is supported by documentation. This holds, as long as the user is assigned to the same and no other organization.Users, same as Roles, can be assigned to organizations and locations too. Problems (or at least undefined behaviour) arise when there is a mismatch between the taxonomies of the User and the taxonomies of the User's roles.
The permissions are enforced at two different levels. In layman's terms, one is when accessing pages, the other is about what gets shown inside those pages.
The tricky thing here is that the page-access level is not taxonomy-aware, the check is really just "does the user have the required permission, through any of their roles?".
In the model sitatuion outlined above, the expectation people seem to have is that in this case, the user should not be able to do anything in organization
Forbidden. The user probably should still have an option to select both organizations in the organization picker, after all, they're still a member of both of them, but they shouldn't be able to navigate to any pages there. What really happens is that the user can go to pages in organizationForbidden, but then the second level should kick in and filter out the things the user is not allowed to see - in this case, they shouldn't see anything.Changes introduced here
In this PR, I'm adding a set of helpers to make the page-access level checks taxonomy-aware and switching over to them. This affects what menu items show in the navigation as well as enforcing those permissions more strictly when accessing pages.
The taxonomy-awareness is implemented in a relatively straightforward way. Roles without taxonomies grant their permissions globally, roles with taxonomies grant them only within those taxonomies. When the permission checks are done, the role's taxonomies are taken into consideration and compared against current taxonomies. In here I deliberately chose to ignore taxonomy inheritance - if a role is expected to grant permissions in a child organization, it should be assigned to the child organization directly.
Note:
This soft-depends on #10370 . That PR removes one case that would otherwise have to be covered as well - without that PR, individual filters can be configured to override organization and location scoping configured on the role.
But why?
TODOs
Open questions