Stop project scope from cascading permissions into member users' virtual scopes
- Dominant language
- Python
- Stars
- 670
- Forks
- 183
- Avg merge
- 17h 7m
- Merged PRs (30d)
- 358
Description
Permission cascade in the virtual scope model is expressed by a `scope -> VS_member` scope binding. The binding opens the whole target virtual scope, so it must only be created where a cascade is actually wanted.
### Requirement
Upper-scope permissions cascade downward, but the hierarchy is not a single chain:
- `domain -> project` — cascade required
- `domain -> user` — cascade required
- `project -> user` — cascade MUST NOT happen. Holding vfolder delete permission on a project must not allow deleting a member's personal vfolder.
### Current behavior
`RBACWriteOps.add_bulk_members` performs three writes per member: membership of the member entity in the scope's virtual scope, the legacy scope association, and `_bind_scope_to_member_vs`, which binds the enrolling scope into the member's own virtual scope. The same helper serves every enrollment, so project member enrollment also creates `project -> VS_user`. The project member enrollment path passes no permission_cap, so the binding has no ceiling.
Permission resolution walks `entity -> entity_memberships -> scope_bindings -> scope` and OR-combines the grant at every reachable scope. Once entities owned by a user are enrolled as members of their owner's virtual scope, an entity such as a personal vfolder resolves through VS_user to the bound project scope, and project-scope role permissions apply to it.
This does not leak today only because ordinary resource entities are not yet written into entity_memberships; the backfill migration would expose it.
### Decision
Do not create the `project -> VS_user` binding at all, rather than capping it. A project's visibility of its members is already satisfied by the member user entity being a membership of VS_project; the binding adds nothing for that purpose and additionally exposes everything else the user owns.
### Scope of work
- Separate the cascade binding from member enrollment so that creating it is an explicit decision per relation kind, not a side effect shared by every caller.
- Keep the binding for domain -> project and domain -> user; drop it for project -> user.
- Audit the remaining add_bulk_members callers (container registry, group, user, resource group) for which of them intend a cascade.
- Remove any project -> VS_user bindings already written, as part of the virtual scope backfill migration.
- Add regression coverage asserting that a project-scope grant does not resolve onto an entity owned by a member user.
JIRA Issue: BA-7327
Contributor guide
Research direction
Start with RBACWriteOps.add_bulk_members and its _bind_scope_to_member_vs helper to trace each caller and relation kind. Review the virtual scope backfill migration and add regression coverage for project grants on member-owned entities. Done means domain cascades remain, project-to-user bindings are absent, existing bindings are removed, and the regression passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authorization, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100