Re: Why is_admin_of_role() use ROLERECURSE_MEMBERS rather thanROLERECURSE_PRIVS?

From: Robert Haas <robertmhaas(at)gmail(dot)com>
To: Nathan Bossart <nathandbossart(at)gmail(dot)com>
Cc: preTham <prezza672(at)gmail(dot)com>, cca5507 <cca5507(at)qq(dot)com>, Chao Li <li(dot)evan(dot)chao(at)gmail(dot)com>, pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Why is_admin_of_role() use ROLERECURSE_MEMBERS rather thanROLERECURSE_PRIVS?
Date: 2026-04-13 20:43:39
Message-ID: CA+Tgmoa01Uu49=tYaMPisrVvHC1VukmuWsyOcfdWidEoi+jhXg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Mon, Mar 16, 2026 at 5:19 PM Nathan Bossart <nathandbossart(at)gmail(dot)com> wrote:
> This was added by commit ce6b672e44, which first took effect in v16. IIUC
> earlier versions simply check is_admin_of_role() and mark the grantor as
> the current role, at least when adding members. I haven't found any other
> e-mails or documentation about this.

Thanks, Nathan, for pointing me to this thread.

> Changing is_admin_of_role() to use ROLERECURSE_PRIVS would make things more
> restrictive (e.g., the DROP ROLE in the test fails), which has the
> potential to break existing scripts. But it does seem intuitive that if
> you don't INHERIT a roles privileges, you don't inherit its ADMIN rights
> either.

I've been viewing ROLERECURSE_MEMBERS vs. ROLERECURSE_PRIVS vs.
ROLERECURSE_SETROLE as somewhat orthogonal to ADMIN vs. MEMBER. Look
at pg_role_aclcheck(): it tests is_member_of_role(), which uses
ROLERECURSE_MEMBERS, for ACL_CREATE. So it seems like it would be
surprising if when checking ACL_GRANT_OPTION_FOR(ACL_CREATE), it
switched to using ROLERECURSE_PRIVS. On the other hand,
check_role_grantor() checks has_privs_of_role(), which I strongly
suspect is why select_best_admin(), called just after that check, uses
ROLERECURSE_PRIVS.

But I think my mental model here is actually a bit incoherent for
ADMIN. We get into this problem because
check_role_membership_authorization() decides whether you're allowed
to tinker with a role using is_admin_of_role(), which searches with
ROLERECURSE_MEMBERS, and then we call AddRoleMems() which calls
check_role_grantor() which calls select_best_admin(), which uses a
ROLERECURSE_PRIVS search and it expects that to succeed.

I'm pretty strongly disinclined to change the meaning of
is_admin_of_role() in released code. That affects more than this call
site. When this code was under development, one of the use cases that
was booted was a user management bot who should be able to run ALTER
ROLE but should not automatically exercise the privilege of any
created roles. If we standardize on ROLERECURSE_PRIVS, that use case
doesn't work any more. You now have to inherit a role's privileges or
AlterRole() will fail.

One idea could be that non-membership changes to roles continue to
work as they do today, but membership changes use ROLERECURSE_PRIVS.
So we'd have is_admin_of_role() and inherits_admin_privs_for_role()
and be careful to use the right one in each case. This seems a little
weird, but I'm not sure what would be better.

--
Robert Haas
EDB: http://www.enterprisedb.com

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Lakshmi N 2026-04-13 20:49:12 Re: Show VIRTUAL keyword for virtual generated columns in pg_dump and psql
Previous Message Lakshmi N 2026-04-13 20:33:11 [PATCH] Fix missing pfree(flags.data) in overexplain_debug