Skip to content

Fix default privileges by adding FOR ROLE clause#319

Open
gcaracuel wants to merge 1 commit intomovetokube:masterfrom
gcaracuel:fix/default_permissions
Open

Fix default privileges by adding FOR ROLE clause#319
gcaracuel wants to merge 1 commit intomovetokube:masterfrom
gcaracuel:fix/default_permissions

Conversation

@gcaracuel
Copy link
Copy Markdown

@gcaracuel gcaracuel commented Apr 29, 2026

Fixes #318

Root Cause

The operator was executing ALTER DEFAULT PRIVILEGES commands without the FOR ROLE clause:

ALTER DEFAULT PRIVILEGES IN SCHEMA "public" GRANT SELECT ON TABLES TO "mydb-reader";

When FOR ROLE is not specified, PostgreSQL only applies default privileges to objects created by the current user executing the command (in this case, the postgres superuser that the operator connects with).

However, when users are provisioned by the operator:

  1. A user role is created (e.g., myapp-abc123) with LOGIN privilege
  2. The user is granted membership in a group role (e.g., mydb-group for owner, mydb-writer for writer, mydb-reader for reader)
  3. The operator executes ALTER USER "myapp-abc123" SET ROLE "mydb-group" (see postgresuser_controller.go:158)
  4. When this user logs in and creates a table, the table is owned by the group role (mydb-group), not by the postgres superuser

Result: Default privileges don't apply to these newly created tables, causing writer and reader roles to have no access.

Steps to Reproduce

  1. Use a non operator managed user as the user in the operator (e.g., postgres)
  2. Operator creates database with owner/writer/reader roles
  3. User with owner privileges creates a table
  4. User with writer privileges cannot access the table (permission denied)
  5. Same applies to reader users

Solution

Add FOR ROLE clause to ALTER DEFAULT PRIVILEGES commands to specify which roles' object creations should have default privileges applied.

The fix ensures that when the owner role or writer role creates objects (tables, sequences, functions), the reader and writer roles automatically receive appropriate privileges.

Example SQL Generated After Fix

For a database named mydb, the operator now executes:

-- Reader gets SELECT on tables created by owner role
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT SELECT ON TABLES TO "mydb-reader";

-- Reader gets SELECT on tables created by writer role
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-writer" IN SCHEMA public GRANT SELECT ON TABLES TO "mydb-reader";

-- Writer gets full privileges on tables created by owner role
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT SELECT ON TABLES TO "mydb-writer";
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT UPDATE ON TABLES TO "mydb-writer";
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT INSERT ON TABLES TO "mydb-writer";
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT DELETE ON TABLES TO "mydb-writer";
-- (and sequences, functions...)

-- Owner gets ALL privileges on tables created by owner and writer roles
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-group" IN SCHEMA public GRANT ALL ON TABLES TO "mydb-group";
ALTER DEFAULT PRIVILEGES FOR ROLE "mydb-writer" IN SCHEMA public GRANT ALL ON TABLES TO "mydb-group";

Changes Made

  1. SQL Constants (pkg/postgres/database.go:19,21,23)

    • Added FOR ROLE "%s" clause to all three ALTER DEFAULT PRIVILEGES constants
    • Example: ALTER DEFAULT PRIVILEGES FOR ROLE "%s" IN SCHEMA "%s" GRANT %s ON TABLES TO "%s"
  2. Schema Privileges Struct (pkg/postgres/postgres.go:41-49)

    • Added CreatorRole field to PostgresSchemaPrivileges struct
    • This field specifies which role creates the objects (for the FOR ROLE clause)
  3. SetSchemaPrivileges Function (pkg/postgres/database.go:152,165,179)

    • Updated fmt.Sprintf calls to include schemaPrivileges.CreatorRole as the first parameter
    • Applies to tables, sequences, and functions
  4. Controller Reconciliation Loop (internal/controller/postgres_controller.go:235-283)

    • Changed from 3 calls to SetSchemaPrivileges() per schema (one per role) to 6 calls per schema
    • Now loops over creator roles (owner and writer) and sets default privileges for each combination of (recipient role, creator role)
    • Ensures comprehensive coverage for all scenarios where objects might be created

Fixes movetokube#318

Add FOR ROLE clause to ALTER DEFAULT PRIVILEGES commands to ensure
that privileges are applied to objects created by owner and writer
group roles, not just the operator's connection user.

This ensures that when users create tables, sequences, or functions
while operating as their group role (via SET ROLE), the reader and
writer roles automatically receive appropriate permissions.
@gcaracuel gcaracuel marked this pull request as ready for review April 29, 2026 19:50
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.

[bug] Default privileges not applied

1 participant