allowing for control over SET ROLE - Mailing list pgsql-hackers
From | Robert Haas |
---|---|
Subject | allowing for control over SET ROLE |
Date | |
Msg-id | CA+Tgmob+zDSRS6JXYrgq0NWdzCXuTNzT5eK54Dn2hhgt17nm8A@mail.gmail.com Whole thread Raw |
Responses |
Re: allowing for control over SET ROLE
Re: allowing for control over SET ROLE Re: allowing for control over SET ROLE Re: allowing for control over SET ROLE Re: allowing for control over SET ROLE |
List | pgsql-hackers |
Hi, There are two ways in which a role can exercise the privileges of some other role which has been granted to it. First, it can implicitly inherit the privileges of the granted role. Second, it can assume the identity of the granted role using the SET ROLE command. It is possible to control the former behavior, but not the latter. In v15 and prior release, we had a role-level [NO]INHERIT property which controlled whether a role automatically inherited the privileges of any role granted to it. This was all-or-nothing. Beginning in e3ce2de09d814f8770b2e3b3c152b7671bcdb83f, the inheritance behavior of role-grants can be overridden for individual grants, so that some grants are inherited and others are not. However, there is no similar facility for controlling whether a role can SET ROLE to some other role of which it is a member. At present, if role A is a member of role B, then A can SET ROLE B, and that's it. In some circumstances, it may be desirable to control this behavior. For example, if we GRANT pg_read_all_settings TO seer, we do want the seer to be able to read all the settings, else we would not have granted the role. But we might not want the seer to be able to do this: You are now connected to database "rhaas" as user "seer". rhaas=> set role pg_read_all_settings; SET rhaas=> create table artifact (a int); CREATE TABLE rhaas=> \d List of relations Schema | Name | Type | Owner --------+----------+-------+---------------------- public | artifact | table | pg_read_all_settings (1 row) I have attached a rather small patch which makes it possible to control this behavior: You are now connected to database "rhaas" as user "rhaas". rhaas=# grant pg_read_all_settings to seer with set false; GRANT ROLE rhaas=# \c - seer You are now connected to database "rhaas" as user "seer". rhaas=> set role pg_read_all_settings; ERROR: permission denied to set role "pg_read_all_settings" I think that this behavior is generally useful, and not just for the predefined roles that we ship as part of PostgreSQL. I don't think it's too hard to imagine someone wanting to use some locally created role as a container for privileges but not wanting the users who possess this role to run around creating new objects owned by it. To some extent that can be controlled by making sure the role in question doesn't have any excess privileges, but that's not really sufficient: all you need is one schema anywhere in the system that grants CREATE to PUBLIC. You could avoid creating such a schema, which might be a good idea for other reasons anyway, but it feels like approaching the problem from the wrong end. What you really want is to allow the users to inherit the privileges of the role but not use SET ROLE to become that role, so that's what this patch lets you do. There's one other kind of case in which this sort of thing might be somewhat useful, although it's more dubious. Suppose you have an oncall group where you regularly add and remove members according to who is on call. Naturally, you have an on-call bot which performs this task automatically. The on-call bot has the ability to manage memberships in the oncall group, but should not have the ability to access any of its privileges, either by inheritance or via SET ROLE. This patch KIND OF lets you accomplish this: rhaas=# create role oncall; CREATE ROLE rhaas=# create role oncallbot login; CREATE ROLE rhaas=# grant oncall to oncallbot with inherit false, set false, admin true; GRANT ROLE rhaas=# create role anna; CREATE ROLE rhaas=# create role eliza; CREATE ROLE rhaas=# \c - oncallbot You are now connected to database "rhaas" as user "oncallbot". rhaas=> grant oncall to anna; GRANT ROLE rhaas=> revoke oncall from anna; REVOKE ROLE rhaas=> grant oncall to eliza; GRANT ROLE rhaas=> set role oncall; ERROR: permission denied to set role "oncall" The problem here is that if a nasty evil hacker takes over the oncallbot role, nothing whatsoever prevents them from executing "grant oncall to oncallbot with set true" after which they can then "SET ROLE oncall" using the privileges they just granted themselves. And even if under some theory we blocked that, they could still maliciously grant the sought-after on-call privileges to some other role i.e. "grant oncall to accomplice". It's fundamentally difficult to allow people to administer a set of privileges without giving them the ability to usurp those privileges, and I wouldn't like to pretend that this patch is in any way sufficient to accomplish such a thing. Nevertheless, I think there's some chance it might be useful to someone building such a system, in combination with other safeguards. Or maybe not: this isn't the main reason I'm interested in this, and it's just an added benefit if it turns out that someone can do something like this with it. In order to apply this patch, we'd need to reach a conclusion about the matters mentioned in http://postgr.es/m/CA+TgmobhEYYnW9vrHvoLvD8ODsPBJuU9CbK6tms6Owd70hFMTw@mail.gmail.com -- and thinking about this patch might shed some light on what we'd want to do over there. -- Robert Haas EDB: http://www.enterprisedb.com
Attachment
pgsql-hackers by date: