Skip to content

fix(grants): experimental fix for cross-namespace role revocation#349

Draft
mahlunar wants to merge 2 commits intomasterfrom
fix/cross-namespace-role-revocation
Draft

fix(grants): experimental fix for cross-namespace role revocation#349
mahlunar wants to merge 2 commits intomasterfrom
fix/cross-namespace-role-revocation

Conversation

@mahlunar
Copy link
Member

Problem

When the same PostgreSQL username has PostgreSQLUser resources in multiple namespaces that share a host, each namespace reconciles independently and revokes roles granted by the others. The result is intermittent access loss — whichever namespace reconciled last wins.

Root cause: SyncUser computes accesses from the current namespace only, then passes those to rolesDiff, which revokes any _read/_readwrite role not in that list.

The bug is reproduced (and documented) in:

  • pkg/postgres/cross_namespace_revoke_test.go — proves rolesDiff revokes cross-namespace roles
  • pkg/grants/cross_namespace_revoke_test.go — proves groupAccesses produces disjoint role sets per namespace

Approach

Before calling setRolesOnHosts, merge database schemas from all other PostgreSQLUser resources with the same spec.name (but different namespace) that target the same host. This expands the expected role set seen by rolesDiff to include all namespaces — so nothing gets revoked.

Constraint: only merge for hosts the current namespace already connects to. No new connections are opened.

Changes

  • pkg/kube/kube.goPostgreSQLUsers: cluster-wide user listing
  • pkg/grants/grants.goAllUsers: drop namespace param (always cluster-wide)
  • pkg/grants/sync.gomergeSiblingAccesses + call from SyncUser
  • cmd/main.go — wire AllUsers
  • Test fixtures anonymised (no real hostnames, usernames, or database names)
  • TestCrossNamespaceRevocation_MergeFixPreventsRevocation verifies the fix

Discussion points

  • Should a failed AllUsers listing block the reconciliation rather than proceeding silently?
  • The controller needs cluster-wide list RBAC on postgresqlusers — RBAC manifests not updated yet
  • Performance: every SyncUser call now issues an extra cluster-wide list; acceptable?

🤖 Generated with Claude Code

mahlunar and others added 2 commits March 12, 2026 08:15
When the same PostgreSQL user has PostgreSQLUser resources in multiple
namespaces pointing to the same host, each reconciliation revokes roles
granted by other namespaces because it only computes expected roles from
its own namespace's databases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge sibling-namespace accesses before diffing so rolesDiff sees the
full expected role set across all namespaces sharing the same PostgreSQL
username and host. Without this, each namespace independently revokes
roles granted by the others.

Changes:
- kube.PostgreSQLUsers: cluster-wide user listing
- Granter.AllUsers: drop namespace param (always cluster-wide)
- SyncUser: call mergeSiblingAccesses after groupAccesses
- mergeSiblingAccesses: expand accesses with sibling namespaces, but
  only for hosts the current namespace already connects to
- Wire AllUsers in cmd/main.go
- Anonymise test fixtures (no real hostnames, usernames, or db names)
- Add TestCrossNamespaceRevocation_MergeFixPreventsRevocation

WIP: experimental — needs discussion before merging.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the patch label Mar 12, 2026
@mahlunar mahlunar requested a review from kvlunar March 12, 2026 09:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant