Re: [PATCH] Why is_admin_of_role() uses ROLERECURSE_MEMBERS rather than ROLERECURSE_PRIVS? - Mailing list pgsql-hackers

From preTham
Subject Re: [PATCH] Why is_admin_of_role() uses ROLERECURSE_MEMBERS rather than ROLERECURSE_PRIVS?
Date
Msg-id CAJUn_kN+Mhbb8fYP5xxQCq1KEziOinM6HgYx4ts_pPDnQ2y1nQ@mail.gmail.com
Whole thread Raw
List pgsql-hackers
Hi,

> create user u1;
> create user u2;
> create user u3;
> create user u4;
> grant u2 to u1 with admin true ;
> grant u3 to u2 with admin true ;
> revoke inherit option for u2 from u1 ;
> set session authorization u1;
> grant u3 to u4;

PostgreSQL calls select_best_admin() internally. If that function returns InvalidOid, I think it means that “The system tried all the possible grantor roles (roles we belong to that have ADMIN OPTION), but none are currently usable.” i.e the system couldn’t find a grantor role in the current context, so it reports: "no possible grantors"

>The "grant u3 to u4;" will report error "no possible grantors" rather than "permission denied to grant role".

> Is this the expected behavior




Again I think a “permission denied” would imply we tried as a specific role, and that role doesn’t have permission. But here, Postgres never even found which role we could be acting as. So from the system’s logic, it’s not a denied action; it’s “no valid takers found to even attempt the action.”


> but the "no possible grantors" error can happen in my test case.

> The main reason is that is_admin_of_role() and select_best_admin() use different role recurse methods.

> I think they should keep consistent, maybe both use ROLERECURSE_PRIVS? Thoughts?














I think ROLERECURSE_MEMBERS traverses membership relationships among roles regardless of whether inheritance or session activation is in play, while ROLERECURSE_PRIVS recursively traverses active privileges. and only consider roles whose privileges are currently usable i.e. those with inherit still true, or roles that are currently SET ROLE’d into.







I believe is_admin_of_role() uses ROLERECURSE_MEMBERS because is_admin_of_role() is not used for permission enforcement and Its purpose is to answer checks like “does A have the ADMIN OPTION for B (anywhere in the membership graph)?” So it needs to see all possible relationships, even if the intermediate memberships are non-inheriting or currently inactive.



If A was once granted B WITH ADMIN OPTION, then regardless of INHERIT, A is “an admin of B” from the system’s metadata perspective. Therefore, it recurses through memberships unconditionally while ignoring session state.

select_best_admin() is called at execution time when we actually run a GRANT or REVOKE command. At that moment, PostgreSQL must know: “Given the roles the current user is effectively using right now, which one is a valid grantor?”. Hence it can only follow active, usable privileges  i.e. it uses ROLERECURSE_PRIVS.


Regards,
Pretham

pgsql-hackers by date:

Previous
From: Xuneng Zhou
Date:
Subject: Re: Implement waiting for wal lsn replay: reloaded
Next
From: Peter Eisentraut
Date:
Subject: Remove MsgType type