RFC: Taxonomy-level permission enforcement
Decision Due Date: 2025-09-21
Context and Problem Statement
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 admin
role assigned to organization Allowed
should grant permissions over the entirety of the Allowed
organization, 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. 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?”.
Model situation
- Create organization
Allowed
- Create organization
Forbidden
- Clone the
Organization admin
role intoAllowed Organization admin
and assign the clone to organizationAllowed
- Create a user
- Assign it to both organizations
- Assign the role to it
- Create a subnet an assign it to organization
Forbidden
- Log in as the user
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, unless explicitly given permissions. What really happens is that the user can go to pages in organization Forbidden
, 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.
Current behaviour
- The user can freely pick both organizations
- The user sees the
Infrastructure > Subnets
menu item in both organizations (and any) - The user can go to
Infrastructure > Subnets
in both organizations (and any) - The user doesn’t see any subnets, because the “second level” inside the page filters out the subnet in the forbidden organization
Proposal
If a role has organizations or locations assigned, the permissions granted by that role will apply only in the context of those organizations/locations. This will be honored in navigation, page access and api.
Proposed behaviour
- The user can freely pick both organizations
- The user sees the
Infrastructure > Subnets
menu item in organizationAllowed
and in any- The user does not see the menu item in
Forbidden
organization
- The user does not see the menu item in
- The user can go to
Infrastructure > Subnets
in in organizationAllowed
and in any- When navigating to
/subnets
inForbidden
organization, the user gets an error page stating that the user does not haveview_subnets
permission in the current organization and location scope
- When navigating to
Roles without taxonomies would grant their permissions globally, roles with taxonomies would grant them only within those taxonomies. When the permission checks are being done, the role’s taxonomies would be taken into consideration and compared against current taxonomies.
Notes
Inheritance is a constant source of frustration and bugs, I’d propose that the check would intentionally ignore taxonomy inheritance - if a role is expected to grant permissions in a child organization, it should be assigned to the child organization directly.
Some users expect that if a user is assigned to organization Forbidden, but do not have a view_organizations permission allowing to view it, they should not be able to select it in the organization picker. I would keep this behaviour, if the user is a member of an organization, they should be able to select it, but they shouldn’t be able to do anything there just because they are a member.
But why?
- The new behaviour seems to be more in-line with what people intuitively expect.
- The current two-level permission checking does not cover all cases
- In some cases, the in-page level does not support taxonomy-based filtering and while those cases could be fixed on their own, it would be better to address this at a more fundamental level
- Current multi-tenancy support in Foreman is a bit lacking and while this wouldn’t fix everything, it would still get us much closer to it
Alternative Designs
Although only tangentially related, in the past we’ve discussed various ideas about how to better isolate organizations within Foreman, ranging from rewriting the whole taxonomy handling with the intent to enforcing organization separation by use of sharding. Not many of those ideas got past the wild idea stage.
Decision Outcome
TBFL
Impacts
- Existing users may suddenly lose access to pages they previously could reach
- Permissions will be able to be modelled in a way that was previously impossible
- Users will see different menu items depending on current organization context
- Users will encounter explicit permission errors instead of empty pages
- Addressing some security bugs related to permissions