Repository navigation
Conversation
Starting from PG16, CREATEROLE is not enough to manage a role, the ADMIN option on it is required. Roles created before a major version upgrade to PG16+ don't have it granted to the privileged role, so it cannot alter, drop or grant them until a superuser patches each one. On PG16+, `GRANT <role> TO <privileged_role> WITH ADMIN OPTION` now runs elevated when the privileged role lacks the ADMIN option on the role. It's not allowed on superusers, reserved roles, reserved memberships, the privileged role, members of those (except members of reserved roles) and predefined roles.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Starting from PostgreSQL 16, the CREATEROLE attribute is no longer enough to manage a role: the ADMIN option on it is required. A role gets ADMIN implicitly on the roles it creates, but not on the ones that existed before.
So after a major version upgrade (e.g. PG15 to PG17), the privileged role has no ADMIN option on the roles the user created on the old version, and it cannot alter, rename, drop or grant them:
The user cannot fix this on their own. Each role has to be patched by a superuser.
Solution
On PG16+, when the privileged role runs
grant legacy_role to privileged_role with admin option;and it lacks the ADMIN option on
legacy_role, supautils runs the grant elevated. After that the privileged role can manage the role as usual.The grant is recorded as done by the bootstrap superuser, which is the same state a role created on PG16+ ends up in.
When it applies
supautils.privileged_role.GRANTwithWITH ADMIN OPTION/WITH ADMIN TRUEand noGRANTED BY.CURRENT_USER,CURRENT_ROLEandSESSION_USERare resolved before elevating, so they don't end up pointing to the superuser.What is excluded
Having ADMIN on a role is as good as being that role, so the grant is not elevated when the granted role is:
pg_*).Members of reserved roles are allowed, so a custom role that was granted e.g.
anoncan still be recovered.In all the excluded cases the statement is left to core and fails with the usual permission error. One excluded role in the statement excludes the whole statement.
There is no new setting, this is enabled whenever
supautils.privileged_roleis configured. The privileged role can already alter non-reserved roles through the elevatedALTER ROLEpath, so this does not give it power over roles it could not already manage.Notes
CREATE ROLE.Testing
Added
test/sql/ge16_self_grant_admin.sql, covering the allowed case, each exclusion, the grantee restrictions, a grant done inside a plpgsql function and a member of the privileged role.Run locally on PG18 only, together with
reserved_roles,reserved_membershipsandge16_privileged_role. Compilation was also checked on PG15. The full suite on the other versions is left to CI.