RFC: Taxonomy-level permission enforcement

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

  1. Create organization Allowed
  2. Create organization Forbidden
  3. Clone the Organization admin role into Allowed Organization admin and assign the clone to organization Allowed
  4. Create a user
    1. Assign it to both organizations
    2. Assign the role to it
  5. Create a subnet an assign it to organization Forbidden
  6. 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

  1. The user can freely pick both organizations
  2. The user sees the Infrastructure > Subnets menu item in both organizations (and any)
  3. The user can go to Infrastructure > Subnets in both organizations (and any)
  4. 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

  1. The user can freely pick both organizations
  2. The user sees the Infrastructure > Subnets menu item in organization Allowed and in any
    1. The user does not see the menu item in Forbidden organization
  3. The user can go to Infrastructure > Subnets in in organization Allowed and in any
    1. When navigating to /subnets in Forbidden organization, the user gets an error page stating that the user does not have view_subnets permission in the current organization and location scope

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?

  1. The new behaviour seems to be more in-line with what people intuitively expect.
  2. The current two-level permission checking does not cover all cases
    1. 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
  3. 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

See also

1 Like