Skip to content

Fix CustomRole grants not persisting (SET ROLE to table owner)#360

Merged
tmablunar merged 1 commit intomasterfrom
set-role
Apr 15, 2026
Merged

Fix CustomRole grants not persisting (SET ROLE to table owner)#360
tmablunar merged 1 commit intomasterfrom
set-role

Conversation

@tmablunar
Copy link
Copy Markdown
Contributor

@tmablunar tmablunar commented Apr 15, 2026

Summary

  • SyncDatabaseGrants and RevokeAllDatabaseGrants ran GRANT/REVOKE as iam_creator, which does not own the tables (service users like transactionrepo do). PostgreSQL requires the table owner to issue grants, so all grants silently failed.
  • Added SET ROLE <owner> before each GRANT/REVOKE statement and RESET ROLE after, matching the pattern used by the PostgreSQLDatabase controller's execAsf/prependSetRole.
  • Added schemaOwnerMap() and tableOwnerMap() helpers to bulk-query object ownership from pg_namespace and pg_tables.

Test plan

  • Added TestSyncDatabaseGrants_grantsViaSetRoleToTableOwner — verifies GRANT and REVOKE succeed when connection user is a member of the table owner (SET only, no INHERIT)
  • Added TestRevokeAllDatabaseGrants_viaSetRole — verifies RevokeAllDatabaseGrants works via SET ROLE
  • Verified new tests fail without the fix (grants skipped with "permission denied") and pass with the fix
  • All 23 existing CustomRole integration tests still pass

The key to making the test realistic was GRANT serviceUser TO controllerUser WITH SET TRUE, INHERIT FALSE. This mirrors production where iam_creator can SET ROLE to service users (via rds_superuser) but doesn't inherit their ownership privileges. Without INHERIT FALSE, PostgreSQL 18 lets members exercise all owner privileges including granting, which would mask the bug.

🤖 Generated with Claude Code


Note

Medium Risk
Touches database privilege management logic and changes how SQL is executed (SET ROLE), which can impact access control behavior if owner detection or role membership is misconfigured.

Overview
Ensures SyncDatabaseGrants applies and removes schema/table privileges by first resolving schema/table owners and wrapping each GRANT/REVOKE (including schema USAGE) in SET ROLE <owner> ... RESET ROLE, so the controller can manage privileges on objects it doesn’t directly own.

Updates RevokeAllDatabaseGrants to revoke table privileges under all unique table owners in a schema (not just the schema owner), and adds integration tests covering SET ROLE behavior with INHERIT FALSE membership to match production.

Reviewed by Cursor Bugbot for commit 03332c8. Configure here.

* Fix CustomRole grants not persisting by adding SET ROLE to table owner

SyncDatabaseGrants and RevokeAllDatabaseGrants ran GRANT/REVOKE as
iam_creator, which does not own the tables (service users do). PostgreSQL
requires the table owner to issue grants. Added SET ROLE <owner> before
each GRANT/REVOKE statement, matching the pattern used by the
PostgreSQLDatabase controller's execAsf/prependSetRole.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Handle mixed-ownership schemas in RevokeAllDatabaseGrants

Iterate over unique table owners per schema instead of only the schema
owner, so bulk REVOKE covers tables regardless of which role owns them.
Also fix revoke test to use INHERIT FALSE, matching production behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tmablunar tmablunar requested a review from a team as a code owner April 15, 2026 09:25
@tmablunar tmablunar changed the title Fix CustomRole grants not persisting (SET ROLE to table owner) (#358) Fix CustomRole grants not persisting (SET ROLE to table owner) Apr 15, 2026
@tmablunar tmablunar merged commit 2e21599 into master Apr 15, 2026
6 checks passed
@tmablunar tmablunar deleted the set-role branch April 15, 2026 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants