Re: role self-revocation

2022-03-28 Thread Robert Haas
On Mon, Mar 28, 2022 at 10:51 AM Stephen Frost  wrote:
> > > > So I propose to commit something like what I posted here:
> > > > http://postgr.es/m/ca+tgmobgek0jraowqvpqhsxcfbdfitxsomoebhmmmhmj4gl...@mail.gmail.com
> > >
> > > +1, although the comments might need some more work.  In particular,
> > > I'm not sure that this bit is well stated:
>
> Also +1 on this.

OK, done using Tom's proposed wording.

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




Re: role self-revocation

2022-03-28 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Thu, Mar 24, 2022 at 1:10 PM Tom Lane  wrote:
> > > However, it might. And if it does, I think it would be best if
> > > removing that exception were the *only* change in this area made by
> > > that release.
> >
> > Good idea, especially since it's getting to be too late to consider
> > anything more invasive anyway.
> 
> I'd say it's definitely too late at this point.

Agreed.

> > > So I propose to commit something like what I posted here:
> > > http://postgr.es/m/ca+tgmobgek0jraowqvpqhsxcfbdfitxsomoebhmmmhmj4gl...@mail.gmail.com
> >
> > +1, although the comments might need some more work.  In particular,
> > I'm not sure that this bit is well stated:

Also +1 on this.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-24 Thread Robert Haas
On Thu, Mar 24, 2022 at 1:10 PM Tom Lane  wrote:
> > However, it might. And if it does, I think it would be best if
> > removing that exception were the *only* change in this area made by
> > that release.
>
> Good idea, especially since it's getting to be too late to consider
> anything more invasive anyway.

I'd say it's definitely too late at this point.

> > So I propose to commit something like what I posted here:
> > http://postgr.es/m/ca+tgmobgek0jraowqvpqhsxcfbdfitxsomoebhmmmhmj4gl...@mail.gmail.com
>
> +1, although the comments might need some more work.  In particular,
> I'm not sure that this bit is well stated:
>
> +* A role cannot have WITH ADMIN OPTION on itself, because that would
> +* imply a membership loop.
>
> We already do consider a role to be a member of itself:
>
> regression=# create role r;
> CREATE ROLE
> regression=# grant r to r;
> ERROR:  role "r" is a member of role "r"
> regression=# grant r to r with admin option;
> ERROR:  role "r" is a member of role "r"
>
> It might be better to just say "By policy, a role cannot have WITH ADMIN
> OPTION on itself".  But if you want to write a defense of that policy,
> this isn't a very good one.

That sentence is present in the current code, along with a bunch of
other sentences, which the patch renders irrelevant. So I just deleted
all of the other stuff and kept the sentence that is still relevant to
the revised code. I think your proposed replacement is an improvement,
but let's be careful not to get sucked into too much of a wordsmithing
exercise in a patch that's here to make a functional change.

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




Re: role self-revocation

2022-03-24 Thread Tom Lane
Robert Haas  writes:
> Notwithstanding the lack of agreement on that point, I believe that
> what we should do for v15 is remove the session user
> self-administration exception. We have pretty much established that it
> was originally introduced in error.

Agreed.

> However, it might. And if it does, I think it would be best if
> removing that exception were the *only* change in this area made by
> that release.

Good idea, especially since it's getting to be too late to consider
anything more invasive anyway.

> So I propose to commit something like what I posted here:
> http://postgr.es/m/ca+tgmobgek0jraowqvpqhsxcfbdfitxsomoebhmmmhmj4gl...@mail.gmail.com

+1, although the comments might need some more work.  In particular,
I'm not sure that this bit is well stated:

+* A role cannot have WITH ADMIN OPTION on itself, because that would
+* imply a membership loop.

We already do consider a role to be a member of itself:

regression=# create role r;
CREATE ROLE
regression=# grant r to r;
ERROR:  role "r" is a member of role "r"
regression=# grant r to r with admin option;
ERROR:  role "r" is a member of role "r"

It might be better to just say "By policy, a role cannot have WITH ADMIN
OPTION on itself".  But if you want to write a defense of that policy,
this isn't a very good one.

regards, tom lane




Re: role self-revocation

2022-03-24 Thread Robert Haas
On Fri, Mar 11, 2022 at 11:51 AM Robert Haas  wrote:
> On Fri, Mar 11, 2022 at 11:34 AM Tom Lane  wrote:
> > Note that either case would also involve making entries in pg_shdepend;
> > although for the case of roles owned by/granted to the bootstrap
> > superuser, we could omit those on the usual grounds that we don't need
> > to record dependencies on pinned objects.
>
> That makes sense to me, but it still doesn't solve the problem of
> agreeing on role ownership vs. WITH ADMIN OPTION vs. something else.

Notwithstanding the lack of agreement on that point, I believe that
what we should do for v15 is remove the session user
self-administration exception. We have pretty much established that it
was originally introduced in error. It later was found to be a
security vulnerability, and that resulted in the exception being
narrowed without removing it altogether. While there are differences
of opinion on what the larger plan here ought to be, nobody's proposal
plan involves retaining that exception. Neither has anyone offered a
plausible use case for the current behavior, so there's no reason to
think that removing it would break anything.

However, it might. And if it does, I think it would be best if
removing that exception were the *only* change in this area made by
that release. If for v16 or v17 or v23 we implement Plan Tom or Plan
Stephen or Plan Robert or something else, and along the way we remove
that self-administration exception, we're going to have a real fire
drill if it turns out that the self-administration exception was
important for some reason we're not seeing right now. If, on the other
hand, we remove that exception in v15, then if anything breaks, it'll
be a lot easier to deal with. Worst case scenario we just revert the
removal of that exception, which will be a very localized change if
nothing else has been done that depends heavily on its having been
removed.

So I propose to commit something like what I posted here:

http://postgr.es/m/ca+tgmobgek0jraowqvpqhsxcfbdfitxsomoebhmmmhmj4gl...@mail.gmail.com

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




Re: role self-revocation

2022-03-14 Thread Mark Dilger



> On Mar 14, 2022, at 7:38 AM, Stephen Frost  wrote:
> 
> So ... do you feel like that's now the case?  Or were you looking for
> more?

I don't have any more questions at the moment.  Thanks!

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-14 Thread Stephen Frost
Greetings,

* Mark Dilger (mark.dil...@enterprisedb.com) wrote:
> > On Mar 11, 2022, at 4:56 PM, Stephen Frost  wrote:
> > First … I outlined a fair bit of further description in the message you 
> > just responded to but neglected to include in your response, which strikes 
> > me as odd that you’re now asking for further explanation.
> 
> >  When it comes to completing the idea of role ownership- I didn’t come up 
> > with that idea nor champion it
> 
> Sorry, not "completing", but "competing".  It seems we're discussing 
> different ways to fix how roles and CREATEROLE work, and we have several 
> ideas competing against each other.  (This differs from *people* competing 
> against each other, as I don't necessarily like the patch I wrote better than 
> I like your idea.)
> 
> > and therefore I’m not really sure how many of the steps are required to 
> > fully support that concept..?
> 
> There are problems that the ownership concepts solve.  I strongly suspect 
> that your proposal could also solve those same problems, and just trying to 
> identify the specific portions of your proposal necessary to do so.

I'm happy to help try to identify those, but it seems we'd need to have
the exact problems that ownership solves defined first.  Robert defined
what he's looking for as:

Robert Haas  wrote:
> Probably easier to just say it again: I want to have users that can
> create roles and then have superuser-like powers with respect to those
> roles. They can freely exercise the privileges of those roles, and
> they can do all the things that a superuser can do but only with
> respect to those roles. They cannot break out to the OS. I think it's
> pretty similar to what you are describing, with a couple of possible
> exceptions. For example, would you imagine that being an admin of a
> login role would let you change that user's password? Because that
> would be desirable behavior from where I sit.

Which sure sounds like it's just about covered in step #1 of what I
outlined before, except that the above description implies that one
can't "get away" from the user who created their role, in which case we
do need step #2 also.

> >  For my part, I would think that those steps necessary to satisfy the spec 
> > would get us pretty darn close to what true folks advocating for role 
> > ownership are asking for
> 
> I have little idea what "true folks" means in this context.  As for 
> "advocating for role ownership", I'm not in that group.  Whether role 
> ownership or something else, I just want some solution to a set of problems, 
> mostly to do with needing superuser to do role management tasks.

... I'm not entirely sure what I meant there either, my hunch is that
'true' was actually just a leftover word from some other framing of that
sentence and I had meant to remove it.  Apologies for that.  What I was
trying to get at there is that steps #1 & #2 are the ones that I view as
getting us closer to spec compliance and that doing so would get us to
where Robert's ask above would be answered.

> > , but that doesn’t include the superuser-only alter role attributes piece.  
> > Is that included in role ownership?  I wouldn’t think so, but some might 
> > argue otherwise, and I don’t know that it is actually useful to divert into 
> > a discussion about what is or isn’t in that.
> 
> Introducing the idea of role ownership doesn't fix that.  But a patch which 
> introduces role ownership is useless unless CREATEROLE is also fixed.  There 
> isn't any point having non-superusers create and own roles if, to do so, they 
> need a privilege which can break into superuser.  But that argument is no 
> different with a patch along the lines of what you are proposing.  CREATEROLE 
> needs fixing either way.

There's a few ways to have the 'CREATEROLE' role attribute be fixed-

- Remove it entirely (replacing with pg_create_role or such)
- Remove its ability to GRANT out rights that the role running it
  doesn't have
- Make it superfluous (leave it as-is, but add in pg_create_role which
  allows a role to create another role but doesn't include the magic
  GRANT whatever-role TO whatever-role that CREATEROLE has)

I agree that we need to do something here to allow roles to create other
roles while not having or being able to trivially get superuser
themselves.

> > If we agree that the role attribute bits are independent
> 
> Yes.

Great.

> > then I think I agree that we need 1 and 2 to get the capabilities that the 
> > folks asking for role ownership want
> 
> Yes.

Ok.

> > as 2 is where we make sure that one admin of a role can’t revoke another 
> > admin’s rights over that role.
> 
> Exactly, so #2 is part of the competing proposal.  (I get the sense you might 
> not see these as competing proposals, but I find that framing useful for 
> deciding which approach to pursue.)

... and is also part of getting us closer to the spec.

> >  Perhaps 2 isn’t strictly necessary in a carefully managed environment 
> > where 

Re: role self-revocation

2022-03-11 Thread Mark Dilger



> On Mar 11, 2022, at 4:56 PM, Stephen Frost  wrote:
> 
> First … I outlined a fair bit of further description in the message you just 
> responded to but neglected to include in your response, which strikes me as 
> odd that you’re now asking for further explanation.



>  When it comes to completing the idea of role ownership- I didn’t come up 
> with that idea nor champion it

Sorry, not "completing", but "competing".  It seems we're discussing different 
ways to fix how roles and CREATEROLE work, and we have several ideas competing 
against each other.  (This differs from *people* competing against each other, 
as I don't necessarily like the patch I wrote better than I like your idea.)

> and therefore I’m not really sure how many of the steps are required to fully 
> support that concept..?

There are problems that the ownership concepts solve.  I strongly suspect that 
your proposal could also solve those same problems, and just trying to identify 
the specific portions of your proposal necessary to do so.

>  For my part, I would think that those steps necessary to satisfy the spec 
> would get us pretty darn close to what true folks advocating for role 
> ownership are asking for

I have little idea what "true folks" means in this context.  As for "advocating 
for role ownership", I'm not in that group.  Whether role ownership or 
something else, I just want some solution to a set of problems, mostly to do 
with needing superuser to do role management tasks.

> , but that doesn’t include the superuser-only alter role attributes piece.  
> Is that included in role ownership?  I wouldn’t think so, but some might 
> argue otherwise, and I don’t know that it is actually useful to divert into a 
> discussion about what is or isn’t in that.

Introducing the idea of role ownership doesn't fix that.  But a patch which 
introduces role ownership is useless unless CREATEROLE is also fixed.  There 
isn't any point having non-superusers create and own roles if, to do so, they 
need a privilege which can break into superuser.  But that argument is no 
different with a patch along the lines of what you are proposing.  CREATEROLE 
needs fixing either way.

> If we agree that the role attribute bits are independent

Yes.

> then I think I agree that we need 1 and 2 to get the capabilities that the 
> folks asking for role ownership want

Yes.

> as 2 is where we make sure that one admin of a role can’t revoke another 
> admin’s rights over that role.

Exactly, so #2 is part of the competing proposal.  (I get the sense you might 
not see these as competing proposals, but I find that framing useful for 
deciding which approach to pursue.)

>  Perhaps 2 isn’t strictly necessary in a carefully managed environment where 
> no one else is given admin rights over the mini-superuser roles, but I’d 
> rather not have folks depending on that.

I think it is necessary, and for the reason you say.

>  I’d still push back though and ask those advocating for this if it meets 
> what they’re asking for.  I got the impression that it did but maybe I 
> misunderstood.
> 
> In terms of exactly how things would work with these changes… I thought I 
> explained it pretty clearly, so it’s kind of hard to answer that further 
> without a specific question to answer.  Did you have something specific in 
> mind?  Perhaps I could answer a specific question and provide more clarity 
> that way.

Your emails contained a lot of "we could do this or that depending on what 
people want, and maybe this other thing, but that isn't really necessary, and 
" which left me unclear on the proposal.  I don't mean to disparage your 
communication style; it's just that when trying to distill technical details, 
high level conversation can be hard to grok.

I have the sense that you aren't going to submit a patch, so I wanted this 
thread to contain enough detail for somebody else to do so.  Thanks.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

On Fri, Mar 11, 2022 at 19:03 Mark Dilger 
wrote:

> > On Mar 11, 2022, at 2:46 PM, Stephen Frost  wrote:
> >
> > I do think that’s reasonable … and believe I suggested it about 3
> messages ago in this thread. ;)  (step #3 I think it was?  Or maybe 4).
>
> Yes, and you mentioned it to me off-list.


Indeed.

I'm soliciting a more concrete specification for what you are proposing.
> To me, that means understanding how the SQL spec behavior that you champion
> translates into specific changes.  You specified some of this in steps #1
> through #5, but I'd like a clearer indication of how many of those (#1
> alone, both #1 and #2, or what?) constitute a competing idea to the idea of
> role ownership, and greater detail about how each of those steps translate
> into specific behavior changes in postgres.  Your initial five-step email
> seems to be claiming that #1 by itself is competitive, but to me it seems
> at least #1 and #2 would be required.


First … I outlined a fair bit of further description in the message you
just responded to but neglected to include in your response, which strikes
me as odd that you’re now asking for further explanation.  When it comes to
completing the idea of role ownership- I didn’t come up with that idea nor
champion it and therefore I’m not really sure how many of the steps are
required to fully support that concept..?  For my part, I would think that
those steps necessary to satisfy the spec would get us pretty darn close to
what true folks advocating for role ownership are asking for, but that
doesn’t include the superuser-only alter role attributes piece.  Is that
included in role ownership?  I wouldn’t think so, but some might argue
otherwise, and I don’t know that it is actually useful to divert into a
discussion about what is or isn’t in that.

If we agree that the role attribute bits are independent then I think I
agree that we need 1 and 2 to get the capabilities that the folks asking
for role ownership want, as 2 is where we make sure that one admin of a
role can’t revoke another admin’s rights over that role.  Perhaps 2 isn’t
strictly necessary in a carefully managed environment where no one else is
given admin rights over the mini-superuser roles, but I’d rather not have
folks depending on that.  I’d still push back though and ask those
advocating for this if it meets what they’re asking for.  I got the
impression that it did but maybe I misunderstood.

In terms of exactly how things would work with these changes… I thought I
explained it pretty clearly, so it’s kind of hard to answer that further
without a specific question to answer.  Did you have something specific in
mind?  Perhaps I could answer a specific question and provide more clarity
that way.

Thanks,

Stephen

>


Re: role self-revocation

2022-03-11 Thread Mark Dilger



> On Mar 11, 2022, at 2:46 PM, Stephen Frost  wrote:
> 
> I do think that’s reasonable … and believe I suggested it about 3 messages 
> ago in this thread. ;)  (step #3 I think it was?  Or maybe 4).

Yes, and you mentioned it to me off-list.

I'm soliciting a more concrete specification for what you are proposing.  To 
me, that means understanding how the SQL spec behavior that you champion 
translates into specific changes.  You specified some of this in steps #1 
through #5, but I'd like a clearer indication of how many of those (#1 alone, 
both #1 and #2, or what?) constitute a competing idea to the idea of role 
ownership, and greater detail about how each of those steps translate into 
specific behavior changes in postgres.  Your initial five-step email seems to 
be claiming that #1 by itself is competitive, but to me it seems at least #1 
and #2 would be required.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

On Fri, Mar 11, 2022 at 12:32 Mark Dilger 
wrote:

>
>
> > On Mar 11, 2022, at 8:48 AM, Stephen Frost  wrote:
> >
> > I agree that it would have an impact on backwards compatibility to
> > change how WITH ADMIN works- but it would also get us more in line with
> > what the SQL standard says for how WITH ADMIN is supposed to work and
> > that seems worth the change to me.
>
> I'm fine with giving up some backwards compatibility to get some SQL
> standard compatibility, as long as we're clear that is what we're doing.
> What you say about the SQL spec isn't great, though, because too much power
> is vested in "ADMIN".  I see "ADMIN" as at least three separate privileges
> together.  Maybe it would be spec compliant to implement "ADMIN" as a
> synonym for a set of separate privileges?


I do think that’s reasonable … and believe I suggested it about 3 messages
ago in this thread. ;)  (step #3 I think it was?  Or maybe 4).

> On Mar 11, 2022, at 8:41 AM, Stephen Frost  wrote:
> >
> > That we aren't discussing the issues with the current GRANT ... WITH
> > ADMIN OPTION and how we deviate from what the spec calls for when it
> > comes to DROP ROLE, which seems to be the largest thing that's
> > 'solved' with this ownership concept, is concerning to me.
>
> Sure, let's discuss that a bit more.  Here is my best interpretation of
> your post about the spec, when applied to postgres with an eye towards not
> doing any more damage than necessary:
>
> > On Mar 10, 2022, at 11:58 AM, Stephen Frost  wrote:
> >
> > let's look at what the spec says:
> >
> > CREATE ROLE
> >  - Who is allowed to run CREATE ROLE is implementation-defined
>
> This should be anyone with membership in pg_create_role.


That could be the case if we wished to go that route. I’d think in such
case we’d then also remove CREATEROLE as otherwise the documentation feels
like it’d be quite confusing.

>  - After creation, this is effictively run:
> >GRANT new_role TO creator_role WITH ADMIN, GRANTOR "_SYSTEM"
>
> This should internally be implemented as three separate privileges, one
> which means you can grant the role, another which means you can drop the
> role, and a third that means you're a member of the role.  That way, they
> can be independently granted and revoked.  We could make "WITH ADMIN" a
> short-hand for "WITH G, D, M" where G, D, and M are whatever we name the
> independent privileges Grant, Drop, and Member-of.


I mean, sure, we can get there, and possibly add more like if you’re
allowed to change or reset that role’s password and other things, but I
don’t see that this piece is required as part of the very first change in
this area.  Further, WITH ADMIN already gives grant and member today, so
you’re saying the only thing this change does that makes “WITH ADMIN” too
powerful is adding DROP to it, yet that’s explicitly what the spec calls
for.  In short, I disagree that moving the DROP ROLE right from CREATEROLE
roles having that across the entire system (excluding superusers) to WITH
ADMIN where the role who has that right can:

A) already become that role and drop all their objects
B) already GRANT that role to some other role

is a big issue.

Splitting G and D helps with backwards compatibility, because it gives
> people who want the traditional postgres "admin" a way to get there, by
> granting "G+M".  Splitting M from G and D makes it simpler to implement the
> "bot" idea, since the bot shouldn't have M.  But it does raise a question
> about always granting G+D+M to the creator, since the bot is the creator
> and we don't want the bot to have M.  This isn't a problem I've invented
> from thin air, mind you, as G+D+M is just the definition of ADMIN per the
> SQL spec, if I've understood you correctly.  So we need to think a bit more
> about the pg_create_role built-in role and whether that needs to be further
> refined to distinguish those who can get membership in roles they create
> vs. those who cannot.  This line of reasoning takes me in the direction of
> what I think you were calling #5 upthread, but you'd have to elaborate on
> that, and how it interacts with the spec, for us to have a useful
> conversation about it.


All that said, as I said before, I’m in favor of splitting things up and so
if you want to do that as part of this initial work, sure. Idk that it’s
absolutely required as part of this but I’m not going to complain if it’s
included either.  I agree that would allow folks to get something similar
to what they could get today if they want.

I agree that the split up helps with the “bot” idea, as we could at least
then create a security definer function that the bot runs and which creates
roles that the bot then has G for but not M or D.  Even better would be to
also provide a way for the “bot” to be able to create roles without the
need for a security definer function where it doesn’t automatically get all
three, and that was indeed what I was thinking about with the template
idea. The 

Re: role self-revocation

2022-03-11 Thread Mark Dilger



> On Mar 11, 2022, at 8:48 AM, Stephen Frost  wrote:
> 
> I agree that it would have an impact on backwards compatibility to
> change how WITH ADMIN works- but it would also get us more in line with
> what the SQL standard says for how WITH ADMIN is supposed to work and
> that seems worth the change to me.

I'm fine with giving up some backwards compatibility to get some SQL standard 
compatibility, as long as we're clear that is what we're doing.  What you say 
about the SQL spec isn't great, though, because too much power is vested in 
"ADMIN".  I see "ADMIN" as at least three separate privileges together.  Maybe 
it would be spec compliant to implement "ADMIN" as a synonym for a set of 
separate privileges? 

> On Mar 11, 2022, at 8:41 AM, Stephen Frost  wrote:
> 
> That we aren't discussing the issues with the current GRANT ... WITH
> ADMIN OPTION and how we deviate from what the spec calls for when it
> comes to DROP ROLE, which seems to be the largest thing that's
> 'solved' with this ownership concept, is concerning to me.

Sure, let's discuss that a bit more.  Here is my best interpretation of your 
post about the spec, when applied to postgres with an eye towards not doing any 
more damage than necessary:

> On Mar 10, 2022, at 11:58 AM, Stephen Frost  wrote:
> 
> let's look at what the spec says:
> 
> CREATE ROLE
>  - Who is allowed to run CREATE ROLE is implementation-defined

This should be anyone with membership in pg_create_role.  

>  - After creation, this is effictively run:
>GRANT new_role TO creator_role WITH ADMIN, GRANTOR "_SYSTEM"

This should internally be implemented as three separate privileges, one which 
means you can grant the role, another which means you can drop the role, and a 
third that means you're a member of the role.  That way, they can be 
independently granted and revoked.  We could make "WITH ADMIN" a short-hand for 
"WITH G, D, M" where G, D, and M are whatever we name the independent 
privileges Grant, Drop, and Member-of.

Splitting G and D helps with backwards compatibility, because it gives people 
who want the traditional postgres "admin" a way to get there, by granting 
"G+M".  Splitting M from G and D makes it simpler to implement the "bot" idea, 
since the bot shouldn't have M.  But it does raise a question about always 
granting G+D+M to the creator, since the bot is the creator and we don't want 
the bot to have M.  This isn't a problem I've invented from thin air, mind you, 
as G+D+M is just the definition of ADMIN per the SQL spec, if I've understood 
you correctly.  So we need to think a bit more about the pg_create_role 
built-in role and whether that needs to be further refined to distinguish those 
who can get membership in roles they create vs. those who cannot.  This line of 
reasoning takes me in the direction of what I think you were calling #5 
upthread, but you'd have to elaborate on that, and how it interacts with the 
spec, for us to have a useful conversation about it.

> DROP ROLE
>  - Any user who has been GRANT'd a role with ADMIN option is able to
>DROP that role.

Change this to "Any role who has D on the role".  That's spec compliant, 
because anyone granted ADMIN necessarily has D.

> GRANT ROLE
>  - No cycles allowed
>  - A role must have ADMIN rights on the role to be able to GRANT it to
>another role.

Change this to "Any role who has G on the role".  That's spec compliant, 
because anyone grant ADMIN necessarily has G.

We should also fix the CREATE ROLE command to require the grantor have G on a 
role in order to give it to the new role as part of the command.  Changing the 
CREATEROLE, CREATEDB, REPLICATION, and BYPASSRLS attributes into 
pg_create_role, pg_create_db, pg_replication, and pg_bypassrls, the creator 
could only give them to the created role if the creator has G on the roles.  If 
we do this, we could keep the historical privilege bits and their syntax 
support for backward compatibility, or we could rip them out, but the decision 
between those two options is independent of the rest of the design.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-11 Thread Robert Haas
On Fri, Mar 11, 2022 at 11:34 AM Tom Lane  wrote:
> Note that either case would also involve making entries in pg_shdepend;
> although for the case of roles owned by/granted to the bootstrap
> superuser, we could omit those on the usual grounds that we don't need
> to record dependencies on pinned objects.

That makes sense to me, but it still doesn't solve the problem of
agreeing on role ownership vs. WITH ADMIN OPTION vs. something else.

I find it ironic (and frustrating) that Mark implemented what I think
is basically what you're arguing for, it got stuck because Stephen
didn't like it, we then said OK so let's try to find out what Stephen
would like, only to have you show up and say that it's right the way
he already had it. I'm not saying that you're wrong, or for that
matter that he's wrong. I'm just saying that if both of you are
absolutely bent on having it the way you want it, either one of you is
going to be sad, or we're not going to make any progress.

Never mind the fact that neither of you seem interested in even giving
a hearing to my preferred way of doing it. :-(

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




Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Fri, Mar 11, 2022 at 11:12 AM Mark Dilger
>  wrote:
> > This issue of how much backwards compatibility breakage we're willing to 
> > tolerate is just as important as questions about how we would want roles to 
> > work in a green-field development project.  The sense I got a year ago, on 
> > this list, was that changing CREATEROLE was acceptable, but changing other 
> > parts of the system, such as how ADMIN OPTION works, would go too far.

That we deviate as far as we do when it comes to the SQL spec is
something that I don't feel like I had a good handle on when discussing
this previously (that the spec doesn't talk about 'admin option' really
but rather 'grantable authorization identifiers' or whatever it is
doesn't help... but still, that's on me, sorry about that).

> > Role ownership did not yet exist, and that was a big motivation in 
> > introducing that concept, because you couldn't credibly say it broke other 
> > existing features.  It introduces the new notion that when a superuser 
> > creates a role, the superuser owns it, which is identical to how things 
> > implicitly work today; and when a CREATEROLE non-superuser creates a role, 
> > that role owns the new role, which is different from how it works today, 
> > arguably breaking CREATEROLE's prior behavior.  *But it doesn't break 
> > anything else*.
> >
> > If we're going to change how ADMIN OPTION works, or how role membership 
> > works, or how inherit/noinherit works, let's first be clear that we are 
> > willing to accept whatever backwards incompatibility that entails.  This is 
> > not a green-field development project.  The constant spinning around with 
> > regard to how much compatibility we need to preserve is giving me vertigo.

I agree that it would have an impact on backwards compatibility to
change how WITH ADMIN works- but it would also get us more in line with
what the SQL standard says for how WITH ADMIN is supposed to work and
that seems worth the change to me.

> On the other hand, changing ADMIN OPTION does have compatibility and
> spec-compliance ramifications. I think Stephen is arguing that we can
> solve this problem while coming closer to the spec, and I think we
> usually consider getting closer to the spec to be a sufficient reason
> for breaking backward compatibility (cf. standard_conforming_strings).

Indeed.

> But I don't know whether he is correct when he argues that the spec
> makes admin option on a role sufficient to drop the role. I've never
> had any luck understanding what the SQL specification is saying about
> any topic.

I'm happy to point you to what the spec says and to discuss it further
if that would be helpful, or to get other folks to comment on it.  I
agree that it's definitely hard to grok at times.  In this particular
case what I'm looking at is, under DROP ROLE / Access Rules, there's
only one sentence:

There shall exist at least one grantable role authorization descriptor
whose role name is R and whose grantee is an enabled authorization
identifier.

A bit of decoding: 'grantable role authorization descriptor' is a GRANT
of a role WITH ADMIN OPTION.  The role name 'R' is the role specified.
The 'grantee' is who that role R was GRANT'd to, and 'enabled
authorization identifier' is basically "has_privs_of_role()" (note that
you can in the spec hvae roles that you're a member of but which are
*not* currently enabled).

Hopefully that helps.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Robert Haas  writes:
> > If we implement the link between the creating role and the created
> > role as role ownership, then we are surely just going to add a
> > rolowner column to pg_authid, and when the role is owned by nobody, I
> > think we should always just store a valid OID in it, rather than
> > sometimes storing 0. It just seems simpler. Any time we would store 0,
> > store the bootstrap superuser's pg_authid.oid value instead. That way
> > the OID is always valid, which probably lets us get by with fewer
> > special cases in the code.

We haven't got any particularly special cases in the code today for what
happens if we run up the role hierarchy to a point that it ends and so
I'm not sure why adding in a whole new concept around role ownership,
which doesn't exist in the spec, would somehow leave us with fewer such
special cases.

> +1.
> 
> Note that either case would also involve making entries in pg_shdepend;
> although for the case of roles owned by/granted to the bootstrap
> superuser, we could omit those on the usual grounds that we don't need
> to record dependencies on pinned objects.

That we aren't discussing the issues with the current GRANT ... WITH
ADMIN OPTION and how we deviate from what the spec calls for when it
comes to DROP ROLE, which seems to be the largest thing that's
'solved' with this ownership concept, is concerning to me.

If we go down the route of adding role ownership, are we going to
document that we explicitly go against the SQL standard when it comes to
how DROP ROLE works?  Or are we going to fix DROP ROLE?  I'd much prefer
the latter, but doing so then largely negates the point of this role
ownership concept.  I don't see how it makes sense to do both.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-11 Thread Robert Haas
On Fri, Mar 11, 2022 at 11:12 AM Mark Dilger
 wrote:
> This issue of how much backwards compatibility breakage we're willing to 
> tolerate is just as important as questions about how we would want roles to 
> work in a green-field development project.  The sense I got a year ago, on 
> this list, was that changing CREATEROLE was acceptable, but changing other 
> parts of the system, such as how ADMIN OPTION works, would go too far.
>
> Role ownership did not yet exist, and that was a big motivation in 
> introducing that concept, because you couldn't credibly say it broke other 
> existing features.  It introduces the new notion that when a superuser 
> creates a role, the superuser owns it, which is identical to how things 
> implicitly work today; and when a CREATEROLE non-superuser creates a role, 
> that role owns the new role, which is different from how it works today, 
> arguably breaking CREATEROLE's prior behavior.  *But it doesn't break 
> anything else*.
>
> If we're going to change how ADMIN OPTION works, or how role membership 
> works, or how inherit/noinherit works, let's first be clear that we are 
> willing to accept whatever backwards incompatibility that entails.  This is 
> not a green-field development project.  The constant spinning around with 
> regard to how much compatibility we need to preserve is giving me vertigo.

I mean, I agree that the backward compatibility ramifications of every
idea need to be considered, but I agree even more that the amount of
spinning around here is pretty insane. My feeling is that neither role
owners nor tenants introduce any real concerns about
backward-compatibility or, for that matter, SQL standards compliance,
nonwithstanding Stephen's argument to the contrary. Every vendor
extends the standard with their own stuff, and we've done that as
well, as we can do it in more places.

On the other hand, changing ADMIN OPTION does have compatibility and
spec-compliance ramifications. I think Stephen is arguing that we can
solve this problem while coming closer to the spec, and I think we
usually consider getting closer to the spec to be a sufficient reason
for breaking backward compatibility (cf. standard_conforming_strings).
But I don't know whether he is correct when he argues that the spec
makes admin option on a role sufficient to drop the role. I've never
had any luck understanding what the SQL specification is saying about
any topic.

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




Re: role self-revocation

2022-03-11 Thread Tom Lane
Robert Haas  writes:
> If we implement the link between the creating role and the created
> role as role ownership, then we are surely just going to add a
> rolowner column to pg_authid, and when the role is owned by nobody, I
> think we should always just store a valid OID in it, rather than
> sometimes storing 0. It just seems simpler. Any time we would store 0,
> store the bootstrap superuser's pg_authid.oid value instead. That way
> the OID is always valid, which probably lets us get by with fewer
> special cases in the code.

+1.

Note that either case would also involve making entries in pg_shdepend;
although for the case of roles owned by/granted to the bootstrap
superuser, we could omit those on the usual grounds that we don't need
to record dependencies on pinned objects.

regards, tom lane




Re: role self-revocation

2022-03-11 Thread Robert Haas
On Fri, Mar 11, 2022 at 10:46 AM Tom Lane  wrote:
> The bootstrap superuser clearly must be a special case in some way.
> I'm not convinced that that means there should be other special
> cases.  Maybe there is a use-case for other "unowned" roles, but in
> exactly what way would that be different from deeming such roles
> to be owned by the bootstrap superuser?

I think that just boils down to how many useless catalog entries you
want to make.

If we implement the link between the creating role and the created
role as role ownership, then we are surely just going to add a
rolowner column to pg_authid, and when the role is owned by nobody, I
think we should always just store a valid OID in it, rather than
sometimes storing 0. It just seems simpler. Any time we would store 0,
store the bootstrap superuser's pg_authid.oid value instead. That way
the OID is always valid, which probably lets us get by with fewer
special cases in the code.

If we implement the link between the creating role and the created
role as an automatically-granted WITH ADMIN OPTION, then we could
choose to put (CREATOR_OID, CREATED_OID, whatever, TRUE) into
pg_auth_members for the creating superuser or, indeed, every superuser
in the system. Or we can leave it out. The result will be exactly the
same. Here, I would favor leaving it out, because extra catalog
entries that don't do anything are usually a thing that we do not
want. See a49d081235997c67e8aab7a523b17e8d1cb93184, for example.

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




Re: role self-revocation

2022-03-11 Thread Mark Dilger



> On Mar 11, 2022, at 7:58 AM, Robert Haas  wrote:
> 
> This kind of thing is always a judgement call. If we were talking
> about breaking 'SELECT * from table', I'm sure it would be hard to
> convince anybody to agree to do that at all, let alone with no
> deprecation period. Fortunately, CREATEROLE is less used, so breaking
> it will inconvenience fewer people.

This issue of how much backwards compatibility breakage we're willing to 
tolerate is just as important as questions about how we would want roles to 
work in a green-field development project.  The sense I got a year ago, on this 
list, was that changing CREATEROLE was acceptable, but changing other parts of 
the system, such as how ADMIN OPTION works, would go too far.

Role ownership did not yet exist, and that was a big motivation in introducing 
that concept, because you couldn't credibly say it broke other existing 
features.  It introduces the new notion that when a superuser creates a role, 
the superuser owns it, which is identical to how things implicitly work today; 
and when a CREATEROLE non-superuser creates a role, that role owns the new 
role, which is different from how it works today, arguably breaking 
CREATEROLE's prior behavior.  *But it doesn't break anything else*.

If we're going to change how ADMIN OPTION works, or how role membership works, 
or how inherit/noinherit works, let's first be clear that we are willing to 
accept whatever backwards incompatibility that entails.  This is not a 
green-field development project.  The constant spinning around with regard to 
how much compatibility we need to preserve is giving me vertigo.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-11 Thread Robert Haas
On Fri, Mar 11, 2022 at 10:37 AM David G. Johnston
 wrote:
> I largely agree and am perfectly fine with going with the majority on this 
> point.  My vote would just fall on the conservative side.  But as so far no 
> one else seems to be overly concerned, nerfing CREATEROLE seems to be the 
> path forward.

This kind of thing is always a judgement call. If we were talking
about breaking 'SELECT * from table', I'm sure it would be hard to
convince anybody to agree to do that at all, let alone with no
deprecation period. Fortunately, CREATEROLE is less used, so breaking
it will inconvenience fewer people. Moreover, unlike 'SELECT * FROM
table', CREATEROLE is kinda broken, and it's less scary to make
changes to behavior that sucks in the first place than it is to make
changes to the behavior of things that are working well. For all of
that, there's no hard-and-fast rule that we couldn't keep the existing
behavior around, introduce a substitute, and eventually drop the old
thing. I'm just not clear that it's really worth it in this case. It'd
certainly be interesting to hear from anyone who is finding some
utility in the current system. It looks pretty crap to me, but it's
easy to bring too much of one's own bias to such judgements.

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




Re: role self-revocation

2022-03-11 Thread Tom Lane
Robert Haas  writes:
> On Fri, Mar 11, 2022 at 10:27 AM Stephen Frost  wrote:
>> I agree that there would be a recorded relationship (that is, one that
>> we write into the catalog and keep around until and unless it's removed
>> by an admin) between creating and created roles and that's probably the
>> default when CREATE ROLE is run but, unlike tables or such objects in
>> the system, I don't agree that we should require this to exist at
>> absolutely all times for every role (what would it be for the bootstrap
>> superuser..?).  At least today, that's distinct from how ownership in
>> the system works.  I also don't believe that this is necessarily an
>> issue for Robert's use-case, as long as there are appropriate
>> restrictions around who is allowed to remove or modify these
>> relationships.

> I agree.

The bootstrap superuser clearly must be a special case in some way.
I'm not convinced that that means there should be other special
cases.  Maybe there is a use-case for other "unowned" roles, but in
exactly what way would that be different from deeming such roles
to be owned by the bootstrap superuser?

regards, tom lane




Re: role self-revocation

2022-03-11 Thread Robert Haas
On Fri, Mar 11, 2022 at 10:27 AM Stephen Frost  wrote:
> I agree that there would be a recorded relationship (that is, one that
> we write into the catalog and keep around until and unless it's removed
> by an admin) between creating and created roles and that's probably the
> default when CREATE ROLE is run but, unlike tables or such objects in
> the system, I don't agree that we should require this to exist at
> absolutely all times for every role (what would it be for the bootstrap
> superuser..?).  At least today, that's distinct from how ownership in
> the system works.  I also don't believe that this is necessarily an
> issue for Robert's use-case, as long as there are appropriate
> restrictions around who is allowed to remove or modify these
> relationships.

I agree.

> > I agree. [ but we need to get consensus ]
>
> Well ... [ how about we do it my way? ]

Repeating the same argument over again isn't necessarily going to help
anything here. I read your argument and I can believe there could be a
solution along those lines, although you haven't addressed my concern
about NOINHERIT. Tom is apparently less convinced, and you know, I
think that's OK. Not everybody has to agree with the way you want to
do it.

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




Re: role self-revocation

2022-03-11 Thread David G. Johnston
On Fri, Mar 11, 2022 at 8:32 AM Stephen Frost  wrote:

>
> Such scripts as will break will still
> break in a pretty clear way with a clear answer as to how to fix them
> and I don't think there's some kind of data corruption or something that
> would happen.
>
>
I largely agree and am perfectly fine with going with the majority on this
point.  My vote would just fall on the conservative side.  But as so far no
one else seems to be overly concerned, nerfing CREATEROLE seems to be the
path forward.

David J.


Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

* David G. Johnston (david.g.johns...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 3:01 PM Robert Haas  wrote:
> 
> > On Thu, Mar 10, 2022 at 4:00 PM David G. Johnston
> >  wrote:
> > > I dislike changing the documented behavior of CREATEROLE to the degree
> > suggested here.  However, there are three choices here, only one of which
> > can be chosen:
> > >
> > > 1. Leave CREATEROLE alone entirely
> > > 2. Make it so CREATEROLE cannot assign membership to the predefined
> > roles or superuser (inheritance included), but leave the rest alone.  This
> > would be the hard-coded version, not the role attribute one.
> > > 3. Make it so CREATEROLE can only assign membership to roles for which
> > it has been made an admin; as well as the other things mentioned
> > >
> > > Moving forward I'd prefer options 1 or 2, leaving the ability to
> > create/alter/drop a role to be vested via predefined roles.
> >
> > It sounds like you prefer a behavior where CREATEROLE gives power over
> > all non-superusers, but that seems pretty limiting to me.
> 
> Doh!  I edited out the part where I made clear I considered options 1 and 2
> as basically being done for a limited period of time while deprecating the
> CREATEROLE attribute altogether in favor of the fine-grained and predefined
> role based permission granting.  I don't want to nerf CREATEROLE as part of
> adding this new feature, instead leave it as close to status quo as
> reasonable so as not to mess up existing setups that make use of it.  We
> can note in the release notes and documentation that we consider CREATEROLE
> to be deprecated and that the new predefined role should be used to give a
> user the ability to create/alter/drop roles, etc...  DBAs should consider
> revoking CREATEROLE from their users and granting them proper memberships
> in the predefined roles and the groups those roles should be administering.

I disagree entirely with the idea that we should push the out however
many years it'd take to get through some deprecation period.  We are
absolutely terrible when it comes to that and what we're talking about
here, at this point anyway, is making changes that get us closer to what
the spec says.  I agree that we can't back-patch these changes, but I
don't think we need a deprecation period.  If we were just getting rid
of CREATEROLE, I don't think we'd have a deprecation period.  If we need
to get rid of CREATEROLE and introduce something new that more-or-less
means the same thing, to make it so that people's scripts break in a
more obvious way, maybe we can consider that, but I don't really think
that's actually the case here.  Such scripts as will break will still
break in a pretty clear way with a clear answer as to how to fix them
and I don't think there's some kind of data corruption or something that
would happen.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-11 Thread David G. Johnston
On Fri, Mar 11, 2022 at 6:55 AM Robert Haas  wrote:

> On Thu, Mar 10, 2022 at 5:14 PM Tom Lane  wrote:
> > This seems reasonable in isolation, but
> >
> > (1) it implies a persistent relationship between creating and created
> > roles.  Whether you want to call that ownership or not, it sure walks
> > and quacks like ownership.
>


> I like my TENANT idea best, but I'm perfectly willing to call
> it ownership as you seem to prefer or WITH ADMIN OPTION as Stephen
> seems to prefer if one of those ideas gains consensus.


If WITH ADMIN OPTION is sufficient to meet our immediate goals I do not see
the benefit of adding an ownership concept where there is not one today.
If added, I'd much rather have it be ownership as to fit in with the rest
of the existing system rather than introduce an entirely new term.


> If Alice creates non-superusers Bob and Charlie, and Charlie creates
> Doug, we need the persistent relationship to know that Charlie is
> allowed to drop Doug and Bob is not
>

The interesting question seems to be whether Alice can drop Doug, not
whether Bob can.

> It's more important
> at this point to get agreement on the principles.
>

What are the principles you want to get agreement on and how do they differ
from what we have in place today?  What are the proposed changes you would
make to enforce the new principles.  Which principles are now obsolete and
what do you want to do about the features that were built to enforce them
(including backward compatibility concerns)?

David J.


Re: role self-revocation

2022-03-11 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 5:14 PM Tom Lane  wrote:
> > This seems reasonable in isolation, but
> >
> > (1) it implies a persistent relationship between creating and created
> > roles.  Whether you want to call that ownership or not, it sure walks
> > and quacks like ownership.

I agree that there would be a recorded relationship (that is, one that
we write into the catalog and keep around until and unless it's removed
by an admin) between creating and created roles and that's probably the
default when CREATE ROLE is run but, unlike tables or such objects in
the system, I don't agree that we should require this to exist at
absolutely all times for every role (what would it be for the bootstrap
superuser..?).  At least today, that's distinct from how ownership in
the system works.  I also don't believe that this is necessarily an
issue for Robert's use-case, as long as there are appropriate
restrictions around who is allowed to remove or modify these
relationships.

> I agree. It's been obvious to me from the beginning that we needed
> such a persistent relationship, and also that it needed to be a
> relationship from which the created role couldn't simply walk away.
> Yet, more than six months after the first discussions of this topic,
> we still don't have any kind of agreement on what that thing should be
> called. I like my TENANT idea best, but I'm perfectly willing to call
> it ownership as you seem to prefer or WITH ADMIN OPTION as Stephen
> seems to prefer if one of those ideas gains consensus. But we've
> managed to waste all hope of making any significant progress here for
> an entire release cycle for lack of ability to agree on spelling. I
> think that's unfair to Mark, who put a lot of work into this area and
> got nothing out of it, and I think it sucks for users of PostgreSQL,
> too.

Well ... one of those actually already exists and also happens to be in
the SQL spec.  I don't necessarily agree that we should absolutely
require that the system always enforce that this relationship exist (I'd
like a superuser to be able to get rid of it and to be able to change it
too if they want) and that seems a bit saner than having the bootstrap
superuser be special in some way here as would seem to otherwise be
required.  I also feel that it would be generally useful to have more
than one of these relationships, if the user wishes, and that's
something that ownership doesn't (directly) support today.  Further,
that's supported and expected by the SQL spec too.  Even if we invented
some concept of ownership of roles, it seems like we should make most of
the other changes discussed here to bring us closer to what the spec
says about CREATE ROLE, DROP ROLE, GRANT, REVOKE, etc.  At that point
though, what's the point of having ownership?

> > (2) it seems exactly contradictory to your later point that
> >
> > > Agree. I also think that it would be a good idea to attribute grants
> > > performed by any superuser to the bootstrap superuser, or leave them
> > > unattributed somehow. Because otherwise dropping superusers becomes a
> > > pain in the tail for no good reason.
> >
> > Either there's a persistent relationship or there's not.  I don't
> > think it's sensible to treat superusers differently here.
> >
> > I think that this argument about the difficulty of dropping superusers
> > may in fact be the motivation for the existing behavior that object-
> > permissions GRANTs done by superusers are attributed to the object
> > owner; something you were unhappy about upthread.
> >
> > In the end these requirements seem mutually contradictory.  Either
> > we can have a persistent ownership relationship or not, but I don't
> > think we can have it apply in some cases and not others without
> > creating worse problems than we solve.  I'm inclined to toss overboard
> > the requirement that superusers need to be an easy thing to drop.
> > Why is that important, anyway?
> 
> Well, I think you're looking at it the wrong way. Compared to getting
> useful functionality, the relative ease of dropping users is
> completely unimportant. I'm happy to surrender it in exchange for
> something else. I just don't see why we should give it up for nothing.
> If Alice creates non-superusers Bob and Charlie, and Charlie creates
> Doug, we need the persistent relationship to know that Charlie is
> allowed to drop Doug and Bob is not. But if Charlie is a superuser
> anyway, then the persistent relationship is of no use. I don't see the
> point of cluttering up the system with such dependencies. Will I do it
> that way, if that's what it takes to get the patch accepted? Sure. But
> I can't imagine any end-user actually liking it.

We need to know that Charlie is allowed to drop Doug and Bob isn't but
that doesn't make it absolutely required that this be tracked
permanently or that Alice can't decide later to make it such that Doug
can't be dropped by Charlie for whatever reason 

Re: role self-revocation

2022-03-11 Thread Robert Haas
On Thu, Mar 10, 2022 at 5:14 PM Tom Lane  wrote:
> This seems reasonable in isolation, but
>
> (1) it implies a persistent relationship between creating and created
> roles.  Whether you want to call that ownership or not, it sure walks
> and quacks like ownership.

I agree. It's been obvious to me from the beginning that we needed
such a persistent relationship, and also that it needed to be a
relationship from which the created role couldn't simply walk away.
Yet, more than six months after the first discussions of this topic,
we still don't have any kind of agreement on what that thing should be
called. I like my TENANT idea best, but I'm perfectly willing to call
it ownership as you seem to prefer or WITH ADMIN OPTION as Stephen
seems to prefer if one of those ideas gains consensus. But we've
managed to waste all hope of making any significant progress here for
an entire release cycle for lack of ability to agree on spelling. I
think that's unfair to Mark, who put a lot of work into this area and
got nothing out of it, and I think it sucks for users of PostgreSQL,
too.

> (2) it seems exactly contradictory to your later point that
>
> > Agree. I also think that it would be a good idea to attribute grants
> > performed by any superuser to the bootstrap superuser, or leave them
> > unattributed somehow. Because otherwise dropping superusers becomes a
> > pain in the tail for no good reason.
>
> Either there's a persistent relationship or there's not.  I don't
> think it's sensible to treat superusers differently here.
>
> I think that this argument about the difficulty of dropping superusers
> may in fact be the motivation for the existing behavior that object-
> permissions GRANTs done by superusers are attributed to the object
> owner; something you were unhappy about upthread.
>
> In the end these requirements seem mutually contradictory.  Either
> we can have a persistent ownership relationship or not, but I don't
> think we can have it apply in some cases and not others without
> creating worse problems than we solve.  I'm inclined to toss overboard
> the requirement that superusers need to be an easy thing to drop.
> Why is that important, anyway?

Well, I think you're looking at it the wrong way. Compared to getting
useful functionality, the relative ease of dropping users is
completely unimportant. I'm happy to surrender it in exchange for
something else. I just don't see why we should give it up for nothing.
If Alice creates non-superusers Bob and Charlie, and Charlie creates
Doug, we need the persistent relationship to know that Charlie is
allowed to drop Doug and Bob is not. But if Charlie is a superuser
anyway, then the persistent relationship is of no use. I don't see the
point of cluttering up the system with such dependencies. Will I do it
that way, if that's what it takes to get the patch accepted? Sure. But
I can't imagine any end-user actually liking it.

> I'm a bit disturbed that parts of this discussion seem to be getting
> conducted with little understanding of the system's existing behaviors.
> We should not be reinventing things we already have perfectly good
> solutions for in the object-privileges domain.

I did wonder whether that might be the existing behavior, but stopping
to check right at that moment didn't seem that important to me. Maybe
I should have taken the time, but it's not like we're writing the
final patch for commit next Tuesday at this point. It's more important
at this point to get agreement on the principles. That said, I do
agree that there have been times when we haven't thought hard enough
about the existing behavior in proposing new behavior. On the third
hand, though, part of the problem here is that neither Stephen nor I
are entirely happy with the existing behavior, if for somewhat
different reasons. It really isn't "perfectly good." On the one hand,
from a purely technical standpoint, a lot of the behavior around roles
in particular seems well below the standard that anyone would consider
committable today. On the other hand, even the parts of the code that
are in reasonable shape from a code quality point of view don't
actually do the things that we think users want done.

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




Re: role self-revocation

2022-03-10 Thread Mark Dilger



> On Mar 10, 2022, at 2:01 PM, Robert Haas  wrote:
> 
> It sounds like you prefer a behavior where CREATEROLE gives power over
> all non-superusers, but that seems pretty limiting to me. Why can't
> someone want to create a user with power over some users but not
> others?

I agree with Robert on this.

Over at [1], I introduced a patch series to (a) change CREATEROLE and (b) 
introduce role ownership.  Part (a) wasn't that controversial.  The patch 
series failed to make it for postgres 15 on account of (b).  The patch didn't 
go quite far enough, but with it applied, this is an example of a min-superuser 
"lord" operating within database "fiefdom":

fiefdom=# -- mini-superuser who can create roles and write all data
fiefdom=# CREATE ROLE lord
fiefdom-# WITH CREATEROLE
fiefdom-# IN ROLE pg_write_all_data;
CREATE ROLE
fiefdom=# 
fiefdom=# -- group which "lord" belongs to
fiefdom=# CREATE GROUP squire
fiefdom-# ROLE lord;
CREATE ROLE
fiefdom=# 
fiefdom=# -- group which "lord" has no connection to
fiefdom=# CREATE GROUP paladin;
CREATE ROLE
fiefdom=# 
fiefdom=# SET SESSION AUTHORIZATION lord;
SET
fiefdom=> 
fiefdom=> -- fail, merely a member of "squire"
fiefdom=> CREATE ROLE peon IN ROLE squire;
ERROR:  must have admin option on role "squire"
fiefdom=> 
fiefdom=> -- fail, no privilege to grant CREATEDB 
fiefdom=> CREATE ROLE peon CREATEDB;
ERROR:  must have createdb privilege to create createdb users
fiefdom=> 
fiefdom=> RESET SESSION AUTHORIZATION;
RESET
fiefdom=# 
fiefdom=# -- grant admin over "squire" to "lord"
fiefdom=# GRANT squire
fiefdom-# TO lord
fiefdom-# WITH ADMIN OPTION;
GRANT ROLE
fiefdom=# 
fiefdom=# SET SESSION AUTHORIZATION lord;
SET
fiefdom=> 
fiefdom=> -- ok, have both "CREATEROLE" and admin option for "squire"
fiefdom=> CREATE ROLE peon IN ROLE squire;
CREATE ROLE
fiefdom=> 
fiefdom=> -- fail, no privilege to grant CREATEDB
fiefdom=> CREATE ROLE peasant CREATEDB IN ROLE squire;
ERROR:  must have createdb privilege to create createdb users
fiefdom=> 
fiefdom=> RESET SESSION AUTHORIZATION;
RESET
fiefdom=# 
fiefdom=# -- Give lord the missing privilege
fiefdom=# GRANT CREATEDB TO lord;
ERROR:  role "createdb" does not exist
fiefdom=# 
fiefdom=# RESET SESSION AUTHORIZATION;
RESET
fiefdom=# 
fiefdom=# -- ok, have "CREATEROLE", "CREATEDB", and admin option for "squire"
fiefdom=# CREATE ROLE peasant CREATEDB IN ROLE squire;
CREATE ROLE

The problem with this is that "lord" needs CREATEDB to grant CREATEDB, but 
really it should need something like grant option on "CREATEDB".  But that's 
hard to do with the existing system, given the way these privilege bits are 
represented.  If we added a few more built-in pg_* roles, such as pg_create_db, 
it would just work.  CREATEROLE itself could be reimagined as pg_create_role, 
and then users could be granted into this role with or without admin option, 
meaning they could/couldn't further give it away.  I think that would be a 
necessary component to Joshua's "bot" use-case, since the bot must itself have 
the privilege to create roles, but shouldn't necessarily be trusted with the 
privilege to create additional roles who have it.

[1] 
https://www.postgresql.org/message-id/53c7df4c-8463-4647-9dfd-779b5e186...@amazon.com

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-10 Thread Tom Lane
Robert Haas  writes:
> Probably easier to just say it again: I want to have users that can
> create roles and then have superuser-like powers with respect to those
> roles. They can freely exercise the privileges of those roles, and
> they can do all the things that a superuser can do but only with
> respect to those roles.

This seems reasonable in isolation, but

(1) it implies a persistent relationship between creating and created
roles.  Whether you want to call that ownership or not, it sure walks
and quacks like ownership.

(2) it seems exactly contradictory to your later point that

> Agree. I also think that it would be a good idea to attribute grants
> performed by any superuser to the bootstrap superuser, or leave them
> unattributed somehow. Because otherwise dropping superusers becomes a
> pain in the tail for no good reason.

Either there's a persistent relationship or there's not.  I don't
think it's sensible to treat superusers differently here.

I think that this argument about the difficulty of dropping superusers
may in fact be the motivation for the existing behavior that object-
permissions GRANTs done by superusers are attributed to the object
owner; something you were unhappy about upthread.

In the end these requirements seem mutually contradictory.  Either
we can have a persistent ownership relationship or not, but I don't
think we can have it apply in some cases and not others without
creating worse problems than we solve.  I'm inclined to toss overboard
the requirement that superusers need to be an easy thing to drop.
Why is that important, anyway?

> We might also need to think carefully about what happens if for
> example the table owner is changed. If bob owns the table and we
> change the owner to mary, but bob's previous grants are still
> attributed to bob, I'm not sure that's going to be very convenient.

That's already handled, is it not?

regression=# create user alice;
CREATE ROLE
regression=# create user bob;
CREATE ROLE
regression=# create user charlie;
CREATE ROLE
regression=# \c - alice
You are now connected to database "regression" as user "alice".
regression=> create table alices_table (f1 int);
CREATE TABLE
regression=> grant select on alices_table to bob;
GRANT
regression=> \c - postgres
You are now connected to database "regression" as user "postgres".
regression=# alter table alices_table owner to charlie;
ALTER TABLE
regression=# \dp alices_table
   Access privileges
 Schema | Name | Type  |Access privileges| Column privileges | 
Policies 
+--+---+-+---+--
 public | alices_table | table | charlie=arwdDxt/charlie+|   | 
|  |   | bob=r/charlie   |   | 
(1 row)

I'm a bit disturbed that parts of this discussion seem to be getting
conducted with little understanding of the system's existing behaviors.
We should not be reinventing things we already have perfectly good
solutions for in the object-privileges domain.

regards, tom lane




Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 3:01 PM Robert Haas  wrote:

> On Thu, Mar 10, 2022 at 4:00 PM David G. Johnston
>  wrote:
> > I dislike changing the documented behavior of CREATEROLE to the degree
> suggested here.  However, there are three choices here, only one of which
> can be chosen:
> >
> > 1. Leave CREATEROLE alone entirely
> > 2. Make it so CREATEROLE cannot assign membership to the predefined
> roles or superuser (inheritance included), but leave the rest alone.  This
> would be the hard-coded version, not the role attribute one.
> > 3. Make it so CREATEROLE can only assign membership to roles for which
> it has been made an admin; as well as the other things mentioned
> >
> > Moving forward I'd prefer options 1 or 2, leaving the ability to
> create/alter/drop a role to be vested via predefined roles.
>
> It sounds like you prefer a behavior where CREATEROLE gives power over
> all non-superusers, but that seems pretty limiting to me.
>

Doh!  I edited out the part where I made clear I considered options 1 and 2
as basically being done for a limited period of time while deprecating the
CREATEROLE attribute altogether in favor of the fine-grained and predefined
role based permission granting.  I don't want to nerf CREATEROLE as part of
adding this new feature, instead leave it as close to status quo as
reasonable so as not to mess up existing setups that make use of it.  We
can note in the release notes and documentation that we consider CREATEROLE
to be deprecated and that the new predefined role should be used to give a
user the ability to create/alter/drop roles, etc...  DBAs should consider
revoking CREATEROLE from their users and granting them proper memberships
in the predefined roles and the groups those roles should be administering.

David J.


Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 5:00 PM Bruce Momjian  wrote:
> On Thu, Mar 10, 2022 at 02:22:05PM -0500, Robert Haas wrote:
> > I mean, I didn't design pg_hba.conf, but I think it's part of the
> > database doing a reasonable thing, not an external system doing a
> > nonsensical thing.
>
> FYI, I think pg_hba.conf gets away with having negative/reject
> permissions only because it is strictly ordered.

I agree.

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




Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 4:00 PM David G. Johnston
 wrote:
> I dislike changing the documented behavior of CREATEROLE to the degree 
> suggested here.  However, there are three choices here, only one of which can 
> be chosen:
>
> 1. Leave CREATEROLE alone entirely
> 2. Make it so CREATEROLE cannot assign membership to the predefined roles or 
> superuser (inheritance included), but leave the rest alone.  This would be 
> the hard-coded version, not the role attribute one.
> 3. Make it so CREATEROLE can only assign membership to roles for which it has 
> been made an admin; as well as the other things mentioned
>
> Moving forward I'd prefer options 1 or 2, leaving the ability to 
> create/alter/drop a role to be vested via predefined roles.

It sounds like you prefer a behavior where CREATEROLE gives power over
all non-superusers, but that seems pretty limiting to me. Why can't
someone want to create a user with power over some users but not
others? For example, the superuser might want to give alice the
ability to set up new users in the accounting department, but NOT give
alice the right to tinker with the backup user (who is not a
superuser, but doesn't have the replication privilege). How would they
accomplish that in your view?

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




Re: role self-revocation

2022-03-10 Thread Bruce Momjian
On Thu, Mar 10, 2022 at 02:22:05PM -0500, Robert Haas wrote:
> I mean, I didn't design pg_hba.conf, but I think it's part of the
> database doing a reasonable thing, not an external system doing a
> nonsensical thing.

FYI, I think pg_hba.conf gets away with having negative/reject
permissions only because it is strictly ordered.

-- 
  Bruce Momjian  https://momjian.us
  EDB  https://enterprisedb.com

  If only the physical world exists, free will is an illusion.





Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 3:41 PM Stephen Frost  wrote:
> > Gosh, I feel like I've spelled that out approximately 463,121 times
> > already. That estimate might be slightly off though; I've been known
> > to make mistakes from time to time
>
> If there's a specific message that details it closely on the lists
> somewhere, I'm happy to go review it.  I admit that I didn't go back and
> look for such.

Probably easier to just say it again: I want to have users that can
create roles and then have superuser-like powers with respect to those
roles. They can freely exercise the privileges of those roles, and
they can do all the things that a superuser can do but only with
respect to those roles. They cannot break out to the OS. I think it's
pretty similar to what you are describing, with a couple of possible
exceptions. For example, would you imagine that being an admin of a
login role would let you change that user's password? Because that
would be desirable behavior from where I sit.

> Errr, just to be clear, ALTER ROLE doesn't exist *in the spec*.  I
> wasn't suggesting that we get rid of it, just that it doesn't exist in
> the spec and therefore the spec doesn't have anything to say about it.

Oh, OK.

> > Basically, in this sketch, ADMIN OPTION on a role involves the ability
> > to DROP it, which means we don't need a separate role owner concept.
>
> Right.  The above doesn't include any specifics about what to do with
> ALTER ROLE, but my thought would be to have it also be under ADMIN
> OPTION rather than under CREATEROLE, as I tried to outline (though not
> very well, I'll admit) below.

This sentence really confused me at first, but I think you're saying
that the right to alter a role would be dependent on having ADMIN
OPTION on the role rather than on having the CREATEROLE attribute.
That seems like a reasonable idea to me.

> > It also involves membership, meaning that you can freely exercise the
> > privileges of the role without SET ROLE. While I'm totally down with
> > having other possible behaviors as options, that particular behavior
> > seems very useful to me, so, sounds great.
>
> Well, yes and no- by default you're right, presuming everything is set
> as inheirited, but I'd wish for us to keep the option of creating roles
> which are noinherit and having that work just as it does today.

Hmm, so if I have membership WITH ADMIN OPTION in a role, but my role
is marked NOINHERIT, that means I can't exercise the privileges of
that role without SET ROLE. But, can I still do other things to that
role, such as dropping it? Given the current coding of
roles_is_member_of(), it seems like I can't. I don't like that, but
then I don't like much of anything about NOINHERIT. Do you have any
suggestions for how this could be improved?

To make this more concrete, suppose the superuser does "CREATE USER
alice CREATEROLE". Alice will have INHERIT, so she'll have control
over any roles she creates. But if she does "CREATE USER bob
CREATEROLE NOINHERIT" then neither she nor Bob will be able to control
the roles bob creates. I'd like to have a way to make it so that
neither Alice nor any other CREATEROLE users she spins up can create
roles over which they no longer have control. Because otherwise people
will do dumb stuff like that and then have to call the superuser to
sort it out, and the superuser won't like that because s/he is a super
busy person.

> > What do you mean by the 'drop role' exception?
>
> 'ability' was probably a better word there.  What I'm talking about is
> changing in DropRole:
>
> to be, more or less:
>
> if (!is_admin_of_role(role))
> ereport(ERROR,
> (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
>  errmsg("permission denied to drop role")));

Sounds good.

> > I don't like removing 'alter role'.
>
> Ditto above but for AlterRole.  Taking it away from users with
> CREATEROLE being able to run those commands on $anyrole and instead
> making it so that the role running DROP ROLE or ALTER ROLE needs to have
> ADMIN on the role they're messing with.  I do think we may also need to
> make some adjustments in terms of what a regular user WITH ADMIN on a
> given role is able to do when it comes to ALTER ROLE, in particular, I
> don't think we'll want to remove the existing is-superuser checks
> against a user settings bypassrls or replication or superuser on some
> other role.  Maybe we can provide a way for a non-superuser to be given
> the ability to set those attributes for roles they create, but that
> would be a separate thing.

This too.

> > > Step #2 is also in-line with the spec: track GRANTORs and care about
> > > them, for everything.  We really should have been doing this all along.
> >
> > There are details to work out here, but in general, I like it.
>
> Cool.  Note that superusers would still be able to do $anything,
> including removing someone's ADMIN rights on a role even if that
> superuser didn't GRANT it (at least, that's my 

Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 12:58 PM Stephen Frost  wrote:

> I don't think we're that far from having all of these though.  To start
> with, we remove from CREATEROLE the random things that it does which go
> beyond what folks tend to expect- remove the whole 'grant any role to
> any other' stuff, remove the 'drop role' exception, remove the
> 'alter role' stuff.  Do make it so that when you create a role, however,
> the above GRANT is effectively done.  Now, for the items above where we
> removed the checks against have_createrole_privilege() we go back and
> add in checks using is_admin_of_role().  Of course, also remove the role
> self-administration bug.
>
> That's step #1, but it gets us more-or-less what you're looking for, I
> think, and brings us a lot closer to what the spec has.
>

That still leaves attribute specification in place: e.g., REPLICATION,
CREATEROLE, CREATEDB, etc... (I see BYPASSRLS already is SUPERUSER only)

I dislike changing the documented behavior of CREATEROLE to the degree
suggested here.  However, there are three choices here, only one of which
can be chosen:

1. Leave CREATEROLE alone entirely
2. Make it so CREATEROLE cannot assign membership to the predefined roles
or superuser (inheritance included), but leave the rest alone.  This would
be the hard-coded version, not the role attribute one.
3. Make it so CREATEROLE can only assign membership to roles for which it
has been made an admin; as well as the other things mentioned

Moving forward I'd prefer options 1 or 2, leaving the ability to
create/alter/drop a role to be vested via predefined roles.

The rest seems fine at an initial glance.

David J.


Re: role self-revocation

2022-03-10 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 2:58 PM Stephen Frost  wrote:
> > It'd be useful to have a better definition of exactly what a
> > 'mini-superuser' is, but at least for the moment when it comes to roles,
> > let's look at what the spec says:
> 
> Gosh, I feel like I've spelled that out approximately 463,121 times
> already. That estimate might be slightly off though; I've been known
> to make mistakes from time to time

If there's a specific message that details it closely on the lists
somewhere, I'm happy to go review it.  I admit that I didn't go back and
look for such.

> > CREATE ROLE
> >   - Who is allowed to run CREATE ROLE is implementation-defined
> >   - After creation, this is effictively run:
> > GRANT new_role TO creator_role WITH ADMIN, GRANTOR "_SYSTEM"
> >
> > DROP ROLE
> >   - Any user who has been GRANT'd a role with ADMIN option is able to
> > DROP that role.
> >
> > GRANT ROLE
> >   - No cycles allowed
> >   - A role must have ADMIN rights on the role to be able to GRANT it to
> > another role.
> >
> > ALTER ROLE
> >   - Doesn't exist
> >
> > This actually looks to me like more-or-less what you're looking for, it
> > just isn't what we have today because CREATEROLE brings along with it a
> > bunch of other stuff, some of which we want and some that we don't, and
> > some things that the SQL spec says ADMIN should be allowed to do (DROP
> > ROLE) we don't allow today.
> 
> The above is mostly fine with me, except for the part about ALTER ROLE
> not existing. I think it's always good to be able to change your mind
> post-CREATE.

Errr, just to be clear, ALTER ROLE doesn't exist *in the spec*.  I
wasn't suggesting that we get rid of it, just that it doesn't exist in
the spec and therefore the spec doesn't have anything to say about it.

> Basically, in this sketch, ADMIN OPTION on a role involves the ability
> to DROP it, which means we don't need a separate role owner concept.

Right.  The above doesn't include any specifics about what to do with
ALTER ROLE, but my thought would be to have it also be under ADMIN
OPTION rather than under CREATEROLE, as I tried to outline (though not
very well, I'll admit) below.

> It also involves membership, meaning that you can freely exercise the
> privileges of the role without SET ROLE. While I'm totally down with
> having other possible behaviors as options, that particular behavior
> seems very useful to me, so, sounds great.

Well, yes and no- by default you're right, presuming everything is set
as inheirited, but I'd wish for us to keep the option of creating roles
which are noinherit and having that work just as it does today.

> > It's also not quite what I want because it requires that membership and
> > ADMIN go together where I'd like to be able to have those be
> > independently GRANT'able- and then some.
> >
> > I don't think we're that far from having all of these though.  To start
> > with, we remove from CREATEROLE the random things that it does which go
> > beyond what folks tend to expect- remove the whole 'grant any role to
> > any other' stuff, remove the 'drop role' exception, remove the
> > 'alter role' stuff.  Do make it so that when you create a role, however,
> > the above GRANT is effectively done.  Now, for the items above where we
> > removed the checks against have_createrole_privilege() we go back and
> > add in checks using is_admin_of_role().  Of course, also remove the role
> > self-administration bug.
> 
> What do you mean by the 'drop role' exception?

'ability' was probably a better word there.  What I'm talking about is
changing in DropRole:

if (!have_createrole_privilege())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 errmsg("permission denied to drop role")));

to be, more or less:

if (!is_admin_of_role(role))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 errmsg("permission denied to drop role")));

> I don't like removing 'alter role'.

Ditto above but for AlterRole.  Taking it away from users with
CREATEROLE being able to run those commands on $anyrole and instead
making it so that the role running DROP ROLE or ALTER ROLE needs to have
ADMIN on the role they're messing with.  I do think we may also need to
make some adjustments in terms of what a regular user WITH ADMIN on a
given role is able to do when it comes to ALTER ROLE, in particular, I
don't think we'll want to remove the existing is-superuser checks
against a user settings bypassrls or replication or superuser on some
other role.  Maybe we can provide a way for a non-superuser to be given
the ability to set those attributes for roles they create, but that
would be a separate thing.

> The rest sounds good.

Great.

> > That's step #1, but it gets us more-or-less what you're looking for, I
> > think, and brings us a lot closer to what the spec has.
> 
> Great.

Awesome.

> > 

Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 2:58 PM Stephen Frost  wrote:
> It'd be useful to have a better definition of exactly what a
> 'mini-superuser' is, but at least for the moment when it comes to roles,
> let's look at what the spec says:

Gosh, I feel like I've spelled that out approximately 463,121 times
already. That estimate might be slightly off though; I've been known
to make mistakes from time to time

> CREATE ROLE
>   - Who is allowed to run CREATE ROLE is implementation-defined
>   - After creation, this is effictively run:
> GRANT new_role TO creator_role WITH ADMIN, GRANTOR "_SYSTEM"
>
> DROP ROLE
>   - Any user who has been GRANT'd a role with ADMIN option is able to
> DROP that role.
>
> GRANT ROLE
>   - No cycles allowed
>   - A role must have ADMIN rights on the role to be able to GRANT it to
> another role.
>
> ALTER ROLE
>   - Doesn't exist
>
> This actually looks to me like more-or-less what you're looking for, it
> just isn't what we have today because CREATEROLE brings along with it a
> bunch of other stuff, some of which we want and some that we don't, and
> some things that the SQL spec says ADMIN should be allowed to do (DROP
> ROLE) we don't allow today.

The above is mostly fine with me, except for the part about ALTER ROLE
not existing. I think it's always good to be able to change your mind
post-CREATE.

Basically, in this sketch, ADMIN OPTION on a role involves the ability
to DROP it, which means we don't need a separate role owner concept.
It also involves membership, meaning that you can freely exercise the
privileges of the role without SET ROLE. While I'm totally down with
having other possible behaviors as options, that particular behavior
seems very useful to me, so, sounds great.

> It's also not quite what I want because it requires that membership and
> ADMIN go together where I'd like to be able to have those be
> independently GRANT'able- and then some.
>
> I don't think we're that far from having all of these though.  To start
> with, we remove from CREATEROLE the random things that it does which go
> beyond what folks tend to expect- remove the whole 'grant any role to
> any other' stuff, remove the 'drop role' exception, remove the
> 'alter role' stuff.  Do make it so that when you create a role, however,
> the above GRANT is effectively done.  Now, for the items above where we
> removed the checks against have_createrole_privilege() we go back and
> add in checks using is_admin_of_role().  Of course, also remove the role
> self-administration bug.

What do you mean by the 'drop role' exception?

I don't like removing 'alter role'.

The rest sounds good.

> That's step #1, but it gets us more-or-less what you're looking for, I
> think, and brings us a lot closer to what the spec has.

Great.

> Step #2 is also in-line with the spec: track GRANTORs and care about
> them, for everything.  We really should have been doing this all along.
> Note that I'm not saying that an owner of a table can't REVOKE some
> right that was GRANT'd on that table, but rather that a user who was
> GRANT'd ADMIN rights on a table and then GRANT'd that right to some
> other user shouldn't have some other user who only has ADMIN rights on
> the table be able to remove that GRANT.  Same goes for roles, meaning
> that you could GRANT rights in a role with ADMIN option and not have to
> be afraid that the role you just gave that to will be able to remove
> *your* ADMIN rights on that role.  In general, I don't think this
> would actually have a very large impact on users because most users
> don't, today, use the ADMIN option much.

There are details to work out here, but in general, I like it.

> Step #3 starts going in the direction of what I'd like to see, which
> would be to break out membership in a role as a separate thing from
> admin rights on that role.  This is also what would help with the 'bot'
> use-case that Joshua (not David Steele, btw) brought up.

Woops, apologies for getting the name wrong. I also said Marc earlier
when I meant Mark, because I work with people named Mark, Marc, and
Marc, and Mark's spelling got outvoted by some distant corner of my
brain.

I think this is a fine long-term direction, with the caveat that
you've not provided enough specifics here for me to really understand
how it would work. I fear the specifics might be hard to get right,
both in terms of making it understandable to users and in terms of
preserving as much backward-compatibility as we can. However, I am not
opposed to the concept.

> Step #4 then breaks the 'admin' option on roles into pieces- a 'drop
> role' right, a 'reset password' right, maybe separate rights for
> different role attributes, etc.  We would likely still keep the
> 'admin_option' column in pg_auth_members and just check that first
> and then check the individual rights (similar to table-level vs.
> column-level privileges) so that we stay in line with the spec's
> expectation here and with what users are used to.


Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 12:45 PM Stephen Frost  wrote:

>
> * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > On Thu, Mar 10, 2022 at 11:05 AM Stephen Frost 
> wrote:
>
Why not just look at the admin_option field of pg_auth_members...?  I
> don't get why that isn't an even more minimal fix than this idea you
> have of adding a column to pg_authid and then propagating around "this
> user could become a superuser" or writing code that has to go check "is
> there some way for this role to become a superuser, either directly or
> through some subset of pg_* roles?"
>

Indeed, maybe I am wrong on the scope of the patch.  But at least for the
explicit attribute it should be no more difficult than changing:

if (grouprole_is_superuser and current_role_is_not_superuser) then error:
to be
if ((grouoprole_is_superuser OR !groupuser_has_adminattr) AND
current_role_is_not_superuser) then error;

I have to imagine that given how fundamental inheritance is to our
permissions system than doing a similar check up the tree wouldn't be
difficult, but I truly don't know with a strong degree of certainty.

Assuming we don't actually rip out CREATEROLE when this change goes in...do
you propose to prohibit a CREATEROLE user from altering the membership
roster of any group which itself is not a member of and also those which it
is a member of but where admin_option is false?

I don't personally have a problem with the current state where CREATEROLE
is an admin for, but not a member of, every non-superuser(-related) role in
the system.  If the consensus is to change that then I suppose this becomes
the minimally invasive fix that accomplishes that goal as well.  It seems
incomplete though, since you still need superuser to create a group and add
the initial WITH ADMIN member to it.  So this seems to work in the "avoid
using superuser" sense if you've also added something that has what
CREATEROLE provides today - admin without membership - but that would have
the benefit of not carrying around all the baggage that CREATEROLE has.


> > I made the observation that being able to manage the membership of a
> group
> > without having the ability to create new users seems like a half a loaf
> of
> > a feature.  That's it.  I would presume that any redesign of the
> > permissions system here would address this adequately.
>
> If the new design ideas that are being thrown around don't address what
> you're thinking they should, it'd be great to point that out.
>

I mean, you need a Create Role permission in some form, even if it's
deprecating the attribute and making it a predefined role.  I picked this
thread up because it seemed like a limited scope that I could get my head
around with the time I have, with the main goal to try to understand this
aspect of the system better.  I haven't gone and looked into the main
thread yet.

David J.


Re: role self-revocation

2022-03-10 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> But that's not to say that we couldn't decide to do something else
> instead, and that other thing might well be better. Do you want to
> sketch out a full proposal, even just what the syntax would look like,
> and share that here? And if you could explain how I could use it to
> create the mini-superusers that I'm trying to get out of this thing,
> even better.

It'd be useful to have a better definition of exactly what a
'mini-superuser' is, but at least for the moment when it comes to roles,
let's look at what the spec says:

CREATE ROLE
  - Who is allowed to run CREATE ROLE is implementation-defined
  - After creation, this is effictively run:
GRANT new_role TO creator_role WITH ADMIN, GRANTOR "_SYSTEM"

DROP ROLE
  - Any user who has been GRANT'd a role with ADMIN option is able to
DROP that role.

GRANT ROLE
  - No cycles allowed
  - A role must have ADMIN rights on the role to be able to GRANT it to
another role.

ALTER ROLE
  - Doesn't exist

This actually looks to me like more-or-less what you're looking for, it
just isn't what we have today because CREATEROLE brings along with it a
bunch of other stuff, some of which we want and some that we don't, and
some things that the SQL spec says ADMIN should be allowed to do (DROP
ROLE) we don't allow today.

It's also not quite what I want because it requires that membership and
ADMIN go together where I'd like to be able to have those be
independently GRANT'able- and then some.

I don't think we're that far from having all of these though.  To start
with, we remove from CREATEROLE the random things that it does which go
beyond what folks tend to expect- remove the whole 'grant any role to
any other' stuff, remove the 'drop role' exception, remove the
'alter role' stuff.  Do make it so that when you create a role, however,
the above GRANT is effectively done.  Now, for the items above where we
removed the checks against have_createrole_privilege() we go back and
add in checks using is_admin_of_role().  Of course, also remove the role
self-administration bug.

That's step #1, but it gets us more-or-less what you're looking for, I
think, and brings us a lot closer to what the spec has.

Step #2 is also in-line with the spec: track GRANTORs and care about
them, for everything.  We really should have been doing this all along.
Note that I'm not saying that an owner of a table can't REVOKE some
right that was GRANT'd on that table, but rather that a user who was
GRANT'd ADMIN rights on a table and then GRANT'd that right to some
other user shouldn't have some other user who only has ADMIN rights on
the table be able to remove that GRANT.  Same goes for roles, meaning
that you could GRANT rights in a role with ADMIN option and not have to
be afraid that the role you just gave that to will be able to remove
*your* ADMIN rights on that role.  In general, I don't think this
would actually have a very large impact on users because most users
don't, today, use the ADMIN option much.

Step #3 starts going in the direction of what I'd like to see, which
would be to break out membership in a role as a separate thing from
admin rights on that role.  This is also what would help with the 'bot'
use-case that Joshua (not David Steele, btw) brought up.

Step #4 then breaks the 'admin' option on roles into pieces- a 'drop
role' right, a 'reset password' right, maybe separate rights for
different role attributes, etc.  We would likely still keep the
'admin_option' column in pg_auth_members and just check that first
and then check the individual rights (similar to table-level vs.
column-level privileges) so that we stay in line with the spec's
expectation here and with what users are used to.

In some hyptothetical world, there's even a later step #5 which allows
us to define user profiles and then grant the ability for a user to
create a role with a certain profile (but not any arbitrary profile),
thus making things like the 'bot' even more constrained in terms of
what it's able to do (maybe it can then create a role that's a member of
a role without itself being a member of that role or explicitly having
admin rights in that role, as an example).

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-10 Thread Stephen Frost
Greetings,

* David G. Johnston (david.g.johns...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 11:05 AM Stephen Frost  wrote:
> > * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > > On Thu, Mar 10, 2022 at 9:19 AM Stephen Frost  wrote:
> > > > * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > > > > On Thu, Mar 10, 2022 at 7:46 AM Robert Haas  
> > > > > wrote:
> >
> > > The only indirect way for a role to become superuser is to have been
> > > granted membership in a superuser group, then SET ROLE.  Non-superusers
> > > cannot do this.  If a superuser does this I consider the outcome to be no
> > > different than if they go and do:
> >
> > A non-superuser absolutely can be GRANT'd membership in a superuser role
> > and then SET ROLE to that user thus becoming a superuser.
> 
> A non-superuser cannot grant a non-superuser membership in a superuser
> role.  A superuser granting a user membership in a superuser role makes
> that user a superuser.  This seems sane.
> 
> If a superuser grants a non-superuser membership in a superuser role then
> today a non-superuser can grant a user membership in that intermediate
> role, thus having a non-superuser make another user a superuser.  This is
> arguably a bug that needs to be fixed.
> 
> My desired fix is to just require the superuser to mark (or have it marked
> by default ideally) the role inheriting superuser and put the
> responsibility on the superuser.  I agree this is not ideal, but it is
> probably quick and low risk.
> 
> I'll let someone else describe the details of the alternative option.  I
> suspect it will end up being a better option in terms of design.  But
> depending on time and risk even knowing that we want the better design
> eventually doesn't preclude getting the easier fix in now.
> 
> > No, what should matter is if the role doing the GRANT has admin rights
> > on pg_read_all_stats, or on the postgres role.  That also happens to be
> > what the spec says.
> 
> Yes, and superusers implicitly have that right, while CREATEROLE users
> implicitly have that right on the pg_* role but not on superuser roles.  I
> just want to plug that hole and include the pg_* roles (or any role for
> that matter) in being able to be denied implied ADMIN rights for
> non-superusers.

CREATEROLE users implicitly have that right on *all non-superuser
roles*.  Not just the pg_* ones, which is why the pg_* ones aren't any
different in this regard.

> > Today a non-superuser cannot "grant postgres to someuser;"
> >
> > No, but a role can be created like 'admin', which a superuser GRANT's
> > 'postgres' to and then that role can be GRANT'd to anyone by anyone who
> > has CREATEROLE rights.  That's not sane.
> 
> I agree.  And I've suggested a minimal fix, adding an attribute to the role
> that prohibits non-superusers from granting it to others, that removes the
> insane behavior.

I disagree that this is a minimal fix as I don't see it as a fix to the
actual issue, which is the ability for CREATEROLE users to GRANT role
membership to all non-superuser roles on the system.  CREATEROLE
shouldn't be allowing that.

> I'm on board for a hard-coded fix as well - if a superuser is in the
> membership chain of a role then non-superusers cannot grant membership in
> that role to others.

Why not just look at the admin_option field of pg_auth_members...?  I
don't get why that isn't an even more minimal fix than this idea you
have of adding a column to pg_authid and then propagating around "this
user could become a superuser" or writing code that has to go check "is
there some way for this role to become a superuser, either directly or
through some subset of pg_* roles?"

> Neither of those really solves the pg_* roles problem.  We still need to
> indicate that they are somehow special.  Whether it is a nice matrix or
> roles and permissions or a simple attribute that makes them behave like
> they are superuser roles.

I disagree that they should be considered special when it comes to role
membership and management.  They're just roles, like any other.

> > I disagree entirely with the idea that we must have some roles who can
> > only ever be administered by a superuser.
> 
> I don't think this is a must have.  I think that since we do have it today
> that fixes that leverage the status quo in order to be done more easily are
> perfectly valid solutions.

We have a half-way-implemented attempt at this, not something that's
actually effective, and therefore I don't agree that we really have it
today or that we should keep it.  I'd much prefer to throw out nearly
everything in the system that's doing an explicit check of "does this
role have a superuser bit set on it?"

> >   If anything, we should be
> > moving away (as we have, in fact, been doing), from anything being the
> > exclusive purview of the superuser.
> >
> 
> I totally agree.

Great.

> > > In particular, this means CREATEROLE roles cannot assign membership in
> > the
> > > marked roles; just 

Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 11:05 AM Stephen Frost  wrote:

> Greetings,
>
> * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > On Thu, Mar 10, 2022 at 9:19 AM Stephen Frost 
> wrote:
> > > * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > > > On Thu, Mar 10, 2022 at 7:46 AM Robert Haas 
> > > wrote:
>
> > The only indirect way for a role to become superuser is to have been
> > granted membership in a superuser group, then SET ROLE.  Non-superusers
> > cannot do this.  If a superuser does this I consider the outcome to be no
> > different than if they go and do:
>
> A non-superuser absolutely can be GRANT'd membership in a superuser role
> and then SET ROLE to that user thus becoming a superuser.


A non-superuser cannot grant a non-superuser membership in a superuser
role.  A superuser granting a user membership in a superuser role makes
that user a superuser.  This seems sane.

If a superuser grants a non-superuser membership in a superuser role then
today a non-superuser can grant a user membership in that intermediate
role, thus having a non-superuser make another user a superuser.  This is
arguably a bug that needs to be fixed.

My desired fix is to just require the superuser to mark (or have it marked
by default ideally) the role inheriting superuser and put the
responsibility on the superuser.  I agree this is not ideal, but it is
probably quick and low risk.

I'll let someone else describe the details of the alternative option.  I
suspect it will end up being a better option in terms of design.  But
depending on time and risk even knowing that we want the better design
eventually doesn't preclude getting the easier fix in now.


> No, what should matter is if the role doing the GRANT has admin rights
> on pg_read_all_stats, or on the postgres role.  That also happens to be
> what the spec says.
>

Yes, and superusers implicitly have that right, while CREATEROLE users
implicitly have that right on the pg_* role but not on superuser roles.  I
just want to plug that hole and include the pg_* roles (or any role for
that matter) in being able to be denied implied ADMIN rights for
non-superusers.


> Today a non-superuser cannot "grant postgres to someuser;"
>
> No, but a role can be created like 'admin', which a superuser GRANT's
> 'postgres' to and then that role can be GRANT'd to anyone by anyone who
> has CREATEROLE rights.  That's not sane.
>

I agree.  And I've suggested a minimal fix, adding an attribute to the role
that prohibits non-superusers from granting it to others, that removes the
insane behavior.

I'm on board for a hard-coded fix as well - if a superuser is in the
membership chain of a role then non-superusers cannot grant membership in
that role to others.

Neither of those really solves the pg_* roles problem.  We still need to
indicate that they are somehow special.  Whether it is a nice matrix or
roles and permissions or a simple attribute that makes them behave like
they are superuser roles.


>
> I disagree entirely with the idea that we must have some roles who can
> only ever be administered by a superuser.


I don't think this is a must have.  I think that since we do have it today
that fixes that leverage the status quo in order to be done more easily are
perfectly valid solutions.



>   If anything, we should be
> moving away (as we have, in fact, been doing), from anything being the
> exclusive purview of the superuser.
>

I totally agree.


>
> > In particular, this means CREATEROLE roles cannot assign membership in
> the
> > marked roles; just like they cannot assign membership in superuser roles
> > today.
>
> I disagree with the idea that we need to mark some roles as only being
> able to be modified by the superuser- why invent this?


Because CREATEUSER is a thing and people want to prevent roles with that
attribute from assigning membership to the predefined superuser-aspect
roles.  If I've misunderstood that desire and the scope of delegation given
by the superuser to CREATEUSER roles is acceptable, then no change here is
needed.

What you
> seem to be arguing for here is to rip out the ADMIN functionality, which
> is defined by spec and not even exclusively by PG, and replace it with a
> single per-role flag that says if that role can only be modified by
> superusers.


I made the observation that being able to manage the membership of a group
without having the ability to create new users seems like a half a loaf of
a feature.  That's it.  I would presume that any redesign of the
permissions system here would address this adequately.

 The
>
short answer is that it's not- which is why we have documented
> CREATEROLE as being 'superuser light'.  The goal here is to get rid of
> that.
>

Now you tell me.  Robert should have led with that goal upfront.

>
> Yes, we're talking about a new feature- one intended to replace the
> broken way that CREATEROLE works, which your proposal doesn't.
>
>
That is correct, I was trying to figure out minimally 

Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 2:05 PM Peter Eisentraut
 wrote:
> On 09.03.22 14:02, Robert Haas wrote:
> > On Wed, Mar 9, 2022 at 7:55 AM Peter Eisentraut
> >  wrote:
> >> Do we have subtractive permissions today?
> >
> > Not in the GRANT/REVOKE sense, I think, but you can put a user in a
> > group and then mention that group in pg_hba.conf. And that line might
> > be "reject" or whatever.
>
> Well, you can always build an external system that looks at roles and
> does nonsensical things with it.  But the privilege system itself seems
> to be additive only.  Personally, I agree with the argument that there
> should not be any subtractive permissions.  The mental model where
> permissions are sort of keys to doors or boxes just doesn't work for that.

I mean, I didn't design pg_hba.conf, but I think it's part of the
database doing a reasonable thing, not an external system doing a
nonsensical thing.

I am not sure that I (or anyone) would endorse a system where you can
say something like GRANT NOT SELECT ON TABLE foo TO bar, essentially
putting a negative ACL into the system dictating that, regardless of
any other grants that may exist, foo should not be able to SELECT from
that table. But I think it's reasonable to use groups as a way of
referencing a defined collection of users for some purpose. The
pg_hba.conf thing is an example of that. You put all the users that
you want to be treated in a certain way for authentication purposes
into a group, and then you mention the group in the file, and it just
works. I don't find that an unreasonable design at all. We could've
created some other kind of grouping mechanism for such purposes that
is separate from the role system, but we didn't choose to do that. I
don't know if that was the absolute best possible decision or not, but
it doesn't seem like an especially bad choice.

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




Re: role self-revocation

2022-03-10 Thread Peter Eisentraut

On 09.03.22 14:02, Robert Haas wrote:

On Wed, Mar 9, 2022 at 7:55 AM Peter Eisentraut
 wrote:

Do we have subtractive permissions today?


Not in the GRANT/REVOKE sense, I think, but you can put a user in a
group and then mention that group in pg_hba.conf. And that line might
be "reject" or whatever.


Well, you can always build an external system that looks at roles and 
does nonsensical things with it.  But the privilege system itself seems 
to be additive only.  Personally, I agree with the argument that there 
should not be any subtractive permissions.  The mental model where 
permissions are sort of keys to doors or boxes just doesn't work for that.






Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 12:26 PM Joshua Brindle
 wrote:
> Ownership implies DAC, the ability to grant others rights to an
> object. It's not "kooky" to see roles as owned objects, but it isn't
> required either. For example most objects on a UNIX system are owned
> and subject to DAC but users aren't.

I have no issue with anything you write in this paragraph.

> Stephen's, and now my, issue with ownership is that, since it implies
> DAC, most checks will be bypassed for the owner. We would both prefer
> for everyone to be subject to the grants, including whoever created
> the role.

That sounds like MAC, which is usually something that sits on top of
DAC and is enforced in addition to DAC, not a reason for DAC to not
exist.

> Rather, we'd like to see a "creators of roles get this set of grants
> against the role by default" and "as a superuser I can revoke grants
> from creators against roles they created"

If you create a table, you own it. You get a set of default
permissions on the table which can be revoked either by you or by
someone else, and you also have certain intrinsic rights over the
object as owner which cannot be revoked - including the ability to
re-grant yourself any previously-revoked permissions. I am not against
the idea of trying to clean things up so that everything you can do
with a table is a revocable privilege and you can be the owner without
having any rights at all, including the right to give yourself other
rights back, but I cannot believe that the idea of removing table
ownership as a concept would ever gain consensus on this list.
Therefore, I also do not think it is reasonable to say that we
shouldn't introduce a similar concept for object types that don't have
it yet, such as roles.

But that's not to say that we couldn't decide to do something else
instead, and that other thing might well be better. Do you want to
sketch out a full proposal, even just what the syntax would look like,
and share that here? And if you could explain how I could use it to
create the mini-superusers that I'm trying to get out of this thing,
even better.

Thanks,

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




Re: role self-revocation

2022-03-10 Thread Stephen Frost
Greetings,

* David G. Johnston (david.g.johns...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 9:19 AM Stephen Frost  wrote:
> > * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > > On Thu, Mar 10, 2022 at 7:46 AM Robert Haas 
> > wrote:
> > > > On Wed, Mar 9, 2022 at 4:31 PM Tom Lane  wrote:
> > > > > I don't think we need syntax to describe it.  As I just said in my
> > > > > other reply, we have a perfectly good precedent for this already
> > > > > in ordinary object permissions.  That is: an object owner always,
> > > > > implicitly, has GRANT OPTION for all the object's privileges, even
> > > > > if she revoked the corresponding plain privilege from herself.
> > > > >
> > > > > Yeah, this does mean that we're effectively deciding that the creator
> > > > > of a role is its owner.  What's the problem with that?
> > > >
> > > > I don't think that's entirely the wrong concept, but it doesn't make a
> > > > lot of sense in a world where the creator has to be a superuser. If
> > > > alice, bob, and charlie are superusers who take turns creating new
> > > > users, and then we let charlie go due to budget cuts, forcing alice
> > > > and bob to change the owner of all the users he created to some other
> > > > superuser as a condition of dropping his account is a waste of
> > > > everyone's time. They can do exactly the same things to every account
> > > > on the system after we change the role owner as before.
> > >
> > > Then maybe we should just implement the idea that if a superuser would
> > > become the owner we instead substitute in the bootstrap user.  Or give
> > the
> > > DBA the choice whether they want to retain knowledge of specific roles -
> > > and thus are willing to accept the "waste of time".
> >
> > This doesn't strike me as going in the right direction.  Falling back to
> > the bootstrap superuser is generally a hack and not a great one.  I'll
> > also point out that the SQL spec hasn't got a concept of role ownership
> > either.
> >
> > > > But wait, I hear you cry, what about CREATEROLE? Well, CREATEROLE is
> > > > generally agreed to be broken right now, and if you don't agree with
> > > > that, consider that it can grant pg_execute_server_programs to a
> > > > newly-created account and then explain to me how it's functionally
> > > > different from superuser.
> > >
> > > CREATEROLE has long been defined as basically having "with admin option"
> > on
> > > every role in the system.  The failure to special-case the roles that
> > grant
> > > different aspects of superuser-ness to its members doesn't make
> > CREATEROLE
> > > itself broken, it makes the implementation of pg_execute_server_programs
> > > broken.  Only superusers should be considered to have with admin option
> > on
> > > these roles. They can delegate through the usual membership+admin
> > mechanism
> > > to a CREATEROLE role if they desire.
> >
> > No, CREATEROLE having admin option on every role in the system is broken
> > and always has been.  It's not just an issue for predefined roles like
> > pg_execute_server_program,
> 
> 
> 
> > it's an issue for any role that could become
> > a superuser either directly or indirectly and that extends beyond the
> > predefined ones.
> 
> 
> The only indirect way for a role to become superuser is to have been
> granted membership in a superuser group, then SET ROLE.  Non-superusers
> cannot do this.  If a superuser does this I consider the outcome to be no
> different than if they go and do:

A non-superuser absolutely can be GRANT'd membership in a superuser role
and then SET ROLE to that user thus becoming a superuser.  Giving users
a regular role to log in as and then membership in a role that can
become a superuser is akin to having a sudoers group in Unix and is good
practice, not something that everyone should have to be super-dooper
careful to not do, lest a CREATEROLE user be able to leverage that.

> SET allow_system_table_mods TO true;
> DROP pg_catalog.pg_class;

I don't equate these in the least.

> In short, having a CREATEROLE user issuing:
> GRANT pg_read_all_stats TO davidj;
> should result in the same outcome as them issuing:
> GRANT postgres TO davidj;
> -- ERROR:  must be superuser to alter superusers

No, what should matter is if the role doing the GRANT has admin rights
on pg_read_all_stats, or on the postgres role.  That also happens to be
what the spec says.

> Superusers can break their system and we don't go to great effort to stop
> them.  I see no difference here, so arguments of this nature aren't all
> that compelling to me.

That you don't feel they're compelling don't make them somehow not real,
nor even particularly uncommon, nor do I view ignoring that possibility
as somehow creating a strong authentication system.

> CREATEROLE shouldn't be
> > the determining factor in the question of if a role can GRANT a
> > predefined (or any other role) to some other role- that should be
> > governed by the admin option on that role, and that should 

Re: role self-revocation

2022-03-10 Thread Joshua Brindle
On Thu, Mar 10, 2022 at 12:11 PM Robert Haas  wrote:
>
> On Thu, Mar 10, 2022 at 11:19 AM Stephen Frost  wrote:
> > I disagree that ownership is needed that's not what the spec calls for
> > either.  What we need is more flexibility when it comes to the
> > relationships which are allowed to be created between roles and what
> > privileges come with them.  To that end, I'd argue that we should be
> > extending pg_auth_members, first by separating out membership itself
> > into an explicitly tracked attribute (instead of being implicit in the
> > existance of a row in the table) and then adding on what other
> > privileges we see fit to add, such as the ability to DROP a role.  We
> > do need to remove the ability for a role who hasn't been explicitly
> > given the admin right on another role to modify that role's membership
> > too, as was originally proposed here.  This also seems to more closely
> > follow the spec's expectation, something that role ownership doesn't.
>
> I do not have a problem with more fine-grained kinds of authorization
> even though I think there are syntactic issues to work out, but I
> strongly disagree with the idea that we can't or shouldn't also have
> role ownership. Marc invented it. Now Tom has invented it
> independently. All sorts of other objects have it already. Trying to
> make it out like this is some kind of kooky idea is not believable.
> Yeah, it's not the most sophisticated or elegant model and that's why
> it's good for us to also have other things, but for simple cases it is
> easy to understand and works great.

Ownership implies DAC, the ability to grant others rights to an
object. It's not "kooky" to see roles as owned objects, but it isn't
required either. For example most objects on a UNIX system are owned
and subject to DAC but users aren't.

Stephen's, and now my, issue with ownership is that, since it implies
DAC, most checks will be bypassed for the owner. We would both prefer
for everyone to be subject to the grants, including whoever created
the role.

Rather, we'd like to see a "creators of roles get this set of grants
against the role by default" and "as a superuser I can revoke grants
from creators against roles they created"




Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 9:19 AM Stephen Frost  wrote:

> Greetings,
>
> * David G. Johnston (david.g.johns...@gmail.com) wrote:
> > On Thu, Mar 10, 2022 at 7:46 AM Robert Haas 
> wrote:
> > > On Wed, Mar 9, 2022 at 4:31 PM Tom Lane  wrote:
> > > > I don't think we need syntax to describe it.  As I just said in my
> > > > other reply, we have a perfectly good precedent for this already
> > > > in ordinary object permissions.  That is: an object owner always,
> > > > implicitly, has GRANT OPTION for all the object's privileges, even
> > > > if she revoked the corresponding plain privilege from herself.
> > > >
> > > > Yeah, this does mean that we're effectively deciding that the creator
> > > > of a role is its owner.  What's the problem with that?
> > >
> > > I don't think that's entirely the wrong concept, but it doesn't make a
> > > lot of sense in a world where the creator has to be a superuser. If
> > > alice, bob, and charlie are superusers who take turns creating new
> > > users, and then we let charlie go due to budget cuts, forcing alice
> > > and bob to change the owner of all the users he created to some other
> > > superuser as a condition of dropping his account is a waste of
> > > everyone's time. They can do exactly the same things to every account
> > > on the system after we change the role owner as before.
> >
> > Then maybe we should just implement the idea that if a superuser would
> > become the owner we instead substitute in the bootstrap user.  Or give
> the
> > DBA the choice whether they want to retain knowledge of specific roles -
> > and thus are willing to accept the "waste of time".
>
> This doesn't strike me as going in the right direction.  Falling back to
> the bootstrap superuser is generally a hack and not a great one.  I'll
> also point out that the SQL spec hasn't got a concept of role ownership
> either.
>
> > > But wait, I hear you cry, what about CREATEROLE? Well, CREATEROLE is
> > > generally agreed to be broken right now, and if you don't agree with
> > > that, consider that it can grant pg_execute_server_programs to a
> > > newly-created account and then explain to me how it's functionally
> > > different from superuser.
> >
> > CREATEROLE has long been defined as basically having "with admin option"
> on
> > every role in the system.  The failure to special-case the roles that
> grant
> > different aspects of superuser-ness to its members doesn't make
> CREATEROLE
> > itself broken, it makes the implementation of pg_execute_server_programs
> > broken.  Only superusers should be considered to have with admin option
> on
> > these roles. They can delegate through the usual membership+admin
> mechanism
> > to a CREATEROLE role if they desire.
>
> No, CREATEROLE having admin option on every role in the system is broken
> and always has been.  It's not just an issue for predefined roles like
> pg_execute_server_program,



> it's an issue for any role that could become
> a superuser either directly or indirectly and that extends beyond the
> predefined ones.


The only indirect way for a role to become superuser is to have been
granted membership in a superuser group, then SET ROLE.  Non-superusers
cannot do this.  If a superuser does this I consider the outcome to be no
different than if they go and do:

SET allow_system_table_mods TO true;
DROP pg_catalog.pg_class;

In short, having a CREATEROLE user issuing:
GRANT pg_read_all_stats TO davidj;
should result in the same outcome as them issuing:
GRANT postgres TO davidj;
-- ERROR:  must be superuser to alter superusers

Superusers can break their system and we don't go to great effort to stop
them.  I see no difference here, so arguments of this nature aren't all
that compelling to me.

CREATEROLE shouldn't be
> the determining factor in the question of if a role can GRANT a
> predefined (or any other role) to some other role- that should be
> governed by the admin option on that role, and that should work exactly
> the same for predefined roles as it does for any other.
>

Never granting the CREATEROLE attribute to anyone will give you this
outcome today.



> ADMIN option
> without membership isn't something the catalogs today can understand
>

Today, they don't need to in order for the system to function within its
existing design specs.


> > ALTER ROLE pg_superuser WITH [NO] ADMIN;
> >
> > Then adding a role membership including the WITH ADMIN OPTION can be
> > rejected, as can the non-superuser situation.  Setting WITH NO ADMIN
> should
> > fail if any existing members have admin.  You must be a superuser to
> > execute WITH ADMIN (maybe WITH NO ADMIN as well...).  And possibly even a
> > new pg_* role that grants this ability (and maybe some others) for use
> by a
> > backup/restore user.
>
> I'm not following this in general or how it helps.  Surely we don't want
> to limit WITH ADMIN to superusers.


Today a non-superuser cannot "grant postgres to someuser;"

The point of this attribute is to allow the 

Re: role self-revocation

2022-03-10 Thread Robert Haas
On Thu, Mar 10, 2022 at 11:19 AM Stephen Frost  wrote:
> I disagree that ownership is needed that's not what the spec calls for
> either.  What we need is more flexibility when it comes to the
> relationships which are allowed to be created between roles and what
> privileges come with them.  To that end, I'd argue that we should be
> extending pg_auth_members, first by separating out membership itself
> into an explicitly tracked attribute (instead of being implicit in the
> existance of a row in the table) and then adding on what other
> privileges we see fit to add, such as the ability to DROP a role.  We
> do need to remove the ability for a role who hasn't been explicitly
> given the admin right on another role to modify that role's membership
> too, as was originally proposed here.  This also seems to more closely
> follow the spec's expectation, something that role ownership doesn't.

I do not have a problem with more fine-grained kinds of authorization
even though I think there are syntactic issues to work out, but I
strongly disagree with the idea that we can't or shouldn't also have
role ownership. Marc invented it. Now Tom has invented it
independently. All sorts of other objects have it already. Trying to
make it out like this is some kind of kooky idea is not believable.
Yeah, it's not the most sophisticated or elegant model and that's why
it's good for us to also have other things, but for simple cases it is
easy to understand and works great.

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




Re: role self-revocation

2022-03-10 Thread Mark Dilger



> On Mar 10, 2022, at 7:56 AM, David G. Johnston  
> wrote:
> 
> 
> I want that because I want mini-superusers, where alice can administer
> the users that alice creates just as if she were a superuser,
> including having their permissions implicitly and dropping them when
> she wants them gone, but where alice cannot break out to the operating
> system as a true superuser could do.
> 
> CREATEROLE (once the pg_* with admin rules are fixed) + Ownership and rules 
> restricting interfering with another role's objects (unless superuser) seems 
> to handle this.

What if one of alice's subordinates also owns roles?  Can alice interfere with 
*that* role's objects?  I don't see that a simple rule restricting roles from 
interfering with another role's objects is quite enough.  That raises the 
question of whether role ownership is transitive, and whether we need a concept 
similar to inherit/noinherit for ownership.

There is also the problem that CREATEROLE currently allows a set of privileges 
to be granted to created roles, and that set of privileges is hard-coded.  
You've suggested changing the hard-coded rules to remove pg_* roles from the 
list of grantable privileges, but that's still an inflexible set of hardcoded 
privileges.  Wouldn't it make more sense for the grantor to need GRANT OPTION 
on any privilege they give to roles they create?

> the bot can stand up
> accounts, can grant them membership in a defined set of groups, but
> cannot exercise the privileges of those accounts (or hack superuser
> either).
> 
> The bot should be provided a security definer procedure that encapsulates all 
> of this rather than us trying to hack the permission system.  This isn't a 
> user permission concern, it is an unauthorized privilege escalation concern.  
> Anyone with the bot's credentials can trivially overcome the third 
> restriction by creating a role with the desired membership and then logging 
> in as that role - and there is nothing the system can do to prevent that 
> while also allowing the other two permissions.

Doesn't this assume password authentication?  If the server uses ldap 
authentication, for example, wouldn't the bot need valid ldap credentials for 
at least one user for this attack to work?  And if CREATEROLE has been made 
more configurable, wouldn't the bot only be able to grant that ldap user the 
limited set of privileges that the bot's database user has been granted ADMIN 
OPTION for?

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-10 Thread Stephen Frost
Greetings,

* David G. Johnston (david.g.johns...@gmail.com) wrote:
> On Thu, Mar 10, 2022 at 7:46 AM Robert Haas  wrote:
> > On Wed, Mar 9, 2022 at 4:31 PM Tom Lane  wrote:
> > > I don't think we need syntax to describe it.  As I just said in my
> > > other reply, we have a perfectly good precedent for this already
> > > in ordinary object permissions.  That is: an object owner always,
> > > implicitly, has GRANT OPTION for all the object's privileges, even
> > > if she revoked the corresponding plain privilege from herself.
> > >
> > > Yeah, this does mean that we're effectively deciding that the creator
> > > of a role is its owner.  What's the problem with that?
> >
> > I don't think that's entirely the wrong concept, but it doesn't make a
> > lot of sense in a world where the creator has to be a superuser. If
> > alice, bob, and charlie are superusers who take turns creating new
> > users, and then we let charlie go due to budget cuts, forcing alice
> > and bob to change the owner of all the users he created to some other
> > superuser as a condition of dropping his account is a waste of
> > everyone's time. They can do exactly the same things to every account
> > on the system after we change the role owner as before.
> 
> Then maybe we should just implement the idea that if a superuser would
> become the owner we instead substitute in the bootstrap user.  Or give the
> DBA the choice whether they want to retain knowledge of specific roles -
> and thus are willing to accept the "waste of time".

This doesn't strike me as going in the right direction.  Falling back to
the bootstrap superuser is generally a hack and not a great one.  I'll
also point out that the SQL spec hasn't got a concept of role ownership
either.

> > But wait, I hear you cry, what about CREATEROLE? Well, CREATEROLE is
> > generally agreed to be broken right now, and if you don't agree with
> > that, consider that it can grant pg_execute_server_programs to a
> > newly-created account and then explain to me how it's functionally
> > different from superuser.
> 
> CREATEROLE has long been defined as basically having "with admin option" on
> every role in the system.  The failure to special-case the roles that grant
> different aspects of superuser-ness to its members doesn't make CREATEROLE
> itself broken, it makes the implementation of pg_execute_server_programs
> broken.  Only superusers should be considered to have with admin option on
> these roles. They can delegate through the usual membership+admin mechanism
> to a CREATEROLE role if they desire.

No, CREATEROLE having admin option on every role in the system is broken
and always has been.  It's not just an issue for predefined roles like
pg_execute_server_program, it's an issue for any role that could become
a superuser either directly or indirectly and that extends beyond the
predefined ones.  As this issue with CREATEROLE existed way before
predefined roles were added to PG, claiming that it's an issue with
predefined roles doesn't make a bit of sense.

> > The whole area needs a rethink. I believe
> > everyone involved in the discussion on the other threads agrees that
> > some reform of CREATEROLE is necessary, and more generally with the
> > idea that it's useful for non-superusers to be able to create roles.
> 
> As the documentation says, using SUPERUSER for day-to-day administration is
> contrary to good security practices.  Role management is considered to be a
> day-to-day administration activity.  I agree with this principle.  It was
> designed to neither be a superuser nor grant superuser, so removing the
> ability to grant the pg_* role memberships remains consistent with its
> original intent.

That would not be sufficient to make CREATEROLE safe.  Far, far from it.

> > I want that because I want mini-superusers, where alice can administer
> > the users that alice creates just as if she were a superuser,
> > including having their permissions implicitly and dropping them when
> > she wants them gone, but where alice cannot break out to the operating
> > system as a true superuser could do.
> 
> CREATEROLE (once the pg_* with admin rules are fixed) + Ownership and rules
> restricting interfering with another role's objects (unless superuser)
> seems to handle this.

This is not sufficient- roles can be not-superuser themselves but have
the ability to become superuser if GRANT'd a superuser role and
therefore we can't have a system where CREATEROLE allows arbitrary
GRANT'ing of roles to each other.  I'm a bit confused too as anything
where we are curtailing what CREATEROLE roles are able to do in a manner
that means they're only able to modify some subset of roles should
equally apply to predefined roles too- that is, CREATEROLE shouldn't be
the determining factor in the question of if a role can GRANT a
predefined (or any other role) to some other role- that should be
governed by the admin option on that role, and that should work exactly
the same for 

Re: role self-revocation

2022-03-10 Thread David G. Johnston
On Thu, Mar 10, 2022 at 7:46 AM Robert Haas  wrote:

> On Wed, Mar 9, 2022 at 4:31 PM Tom Lane  wrote:
> > I don't think we need syntax to describe it.  As I just said in my
> > other reply, we have a perfectly good precedent for this already
> > in ordinary object permissions.  That is: an object owner always,
> > implicitly, has GRANT OPTION for all the object's privileges, even
> > if she revoked the corresponding plain privilege from herself.
> >
> > Yeah, this does mean that we're effectively deciding that the creator
> > of a role is its owner.  What's the problem with that?
>
> I don't think that's entirely the wrong concept, but it doesn't make a
> lot of sense in a world where the creator has to be a superuser. If
> alice, bob, and charlie are superusers who take turns creating new
> users, and then we let charlie go due to budget cuts, forcing alice
> and bob to change the owner of all the users he created to some other
> superuser as a condition of dropping his account is a waste of
> everyone's time. They can do exactly the same things to every account
> on the system after we change the role owner as before.
>

Then maybe we should just implement the idea that if a superuser would
become the owner we instead substitute in the bootstrap user.  Or give the
DBA the choice whether they want to retain knowledge of specific roles -
and thus are willing to accept the "waste of time".


> But wait, I hear you cry, what about CREATEROLE? Well, CREATEROLE is
> generally agreed to be broken right now, and if you don't agree with
> that, consider that it can grant pg_execute_server_programs to a
> newly-created account and then explain to me how it's functionally
> different from superuser.


CREATEROLE has long been defined as basically having "with admin option" on
every role in the system.  The failure to special-case the roles that grant
different aspects of superuser-ness to its members doesn't make CREATEROLE
itself broken, it makes the implementation of pg_execute_server_programs
broken.  Only superusers should be considered to have with admin option on
these roles. They can delegate through the usual membership+admin mechanism
to a CREATEROLE role if they desire.


> The whole area needs a rethink. I believe
> everyone involved in the discussion on the other threads agrees that
> some reform of CREATEROLE is necessary, and more generally with the
> idea that it's useful for non-superusers to be able to create roles.
>

As the documentation says, using SUPERUSER for day-to-day administration is
contrary to good security practices.  Role management is considered to be a
day-to-day administration activity.  I agree with this principle.  It was
designed to neither be a superuser nor grant superuser, so removing the
ability to grant the pg_* role memberships remains consistent with its
original intent.


> I want that because I want mini-superusers, where alice can administer
> the users that alice creates just as if she were a superuser,
> including having their permissions implicitly and dropping them when
> she wants them gone, but where alice cannot break out to the operating
> system as a true superuser could do.


CREATEROLE (once the pg_* with admin rules are fixed) + Ownership and rules
restricting interfering with another role's objects (unless superuser)
seems to handle this.


> the bot can stand up
> accounts, can grant them membership in a defined set of groups, but
> cannot exercise the privileges of those accounts (or hack superuser
> either).


The bot should be provided a security definer procedure that encapsulates
all of this rather than us trying to hack the permission system.  This
isn't a user permission concern, it is an unauthorized privilege escalation
concern.  Anyone with the bot's credentials can trivially overcome the
third restriction by creating a role with the desired membership and then
logging in as that role - and there is nothing the system can do to prevent
that while also allowing the other two permissions.


> And that's why I'm not sure it's really the right idea to say that we
> don't need syntax for this admin-without-member concept.


We already have this syntax in the form of CREATEROLE.  But we do need a
fix, just on the group side.  We need a way to define a group as having no
ADMINS.

ALTER ROLE pg_superuser WITH [NO] ADMIN;

Then adding a role membership including the WITH ADMIN OPTION can be
rejected, as can the non-superuser situation.  Setting WITH NO ADMIN should
fail if any existing members have admin.  You must be a superuser to
execute WITH ADMIN (maybe WITH NO ADMIN as well...).  And possibly even a
new pg_* role that grants this ability (and maybe some others) for use by a
backup/restore user.

Or just special-case pg_* roles.

The advantage of exposing this to the DBA is that they can then package
pg_* roles into a custom group and still have the benefit of superuser only
administration.  In the special-case implementation the presence of a 

Re: role self-revocation

2022-03-10 Thread Robert Haas
On Wed, Mar 9, 2022 at 4:31 PM Tom Lane  wrote:
> I don't think we need syntax to describe it.  As I just said in my
> other reply, we have a perfectly good precedent for this already
> in ordinary object permissions.  That is: an object owner always,
> implicitly, has GRANT OPTION for all the object's privileges, even
> if she revoked the corresponding plain privilege from herself.
>
> Yeah, this does mean that we're effectively deciding that the creator
> of a role is its owner.  What's the problem with that?

I don't think that's entirely the wrong concept, but it doesn't make a
lot of sense in a world where the creator has to be a superuser. If
alice, bob, and charlie are superusers who take turns creating new
users, and then we let charlie go due to budget cuts, forcing alice
and bob to change the owner of all the users he created to some other
superuser as a condition of dropping his account is a waste of
everyone's time. They can do exactly the same things to every account
on the system after we change the role owner as before.

But wait, I hear you cry, what about CREATEROLE? Well, CREATEROLE is
generally agreed to be broken right now, and if you don't agree with
that, consider that it can grant pg_execute_server_programs to a
newly-created account and then explain to me how it's functionally
different from superuser. The whole area needs a rethink. I believe
everyone involved in the discussion on the other threads agrees that
some reform of CREATEROLE is necessary, and more generally with the
idea that it's useful for non-superusers to be able to create roles.
But the reasons why people want that vary.

I want that because I want mini-superusers, where alice can administer
the users that alice creates just as if she were a superuser,
including having their permissions implicitly and dropping them when
she wants them gone, but where alice cannot break out to the operating
system as a true superuser could do. I want this because the lack of
meaningful privilege separation that led to CVE-2019-9193 being filed
spuriously is a very real problem. It's a thing a lot of people want,
and I want to give it to them. David Steele, on the other hand, wants
to build a user-creating bot that can create accounts but otherwise
conforms to the principle of least privilege: the bot can stand up
accounts, can grant them membership in a defined set of groups, but
cannot exercise the privileges of those accounts (or hack superuser
either). Other people may well want other things.

And that's why I'm not sure it's really the right idea to say that we
don't need syntax for this admin-without-member concept. If we just
want to bolt role ownership onto the existing framework without really
changing anything else, we can do that without extra syntax and, as
you say here, make it an implicit property of role ownership. But I
don't see that as has having much value; we just end up with a bunch
of superuser owners. Whatever. Now Stephen made the argument that we
ought to actually have admin-without-member as a first class concept,
something that could be assigned to arbitrary users. Actually, I think
he wanted it even more fine grained with that. And I think that could
make the concept a lot more useful, but then it needs some kind of
understandable syntax.

There's a lot of moving parts here. It's not just about coming up with
something that sounds generally logical, but about creating a system
that has some real-world utility.

> > But do we really have to solve this problem before we can clean up
> > this session exception?
>
> I think we need a plan for where we're going.  I don't see "clean up
> the session exception" as an end in itself; it's part of re-examining
> how all of this ought to work.  I don't say that we have to have a
> complete patch right away, only that we need a coherent end goal.

I'd like to have a plan, too, but if this behavior is accidental, I
still think we can remove it without making big decisions about future
direction. The perfect is the enemy of the good.

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




Re: role self-revocation

2022-03-09 Thread Tom Lane
"David G. Johnston"  writes:
> So CREATE ROLE will assign ownership of AND membership in the newly created
> role to the session_user

I would NOT have it automatically assign membership in the new role,
even though the SQL spec says so.  We've not done that historically
and it doesn't seem desirable.  In particular, it's *really* not
desirable for a user (role with LOGIN).

> I'm fine with this.  It does introduce an OWNER concept to roles and so at
> minimum we need to add:
> ALTER ROLE foo OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER |
> SESSION_USER }

Agreed.

regards, tom lane




Re: role self-revocation

2022-03-09 Thread David G. Johnston
On Wed, Mar 9, 2022 at 2:31 PM Tom Lane  wrote:

> Robert Haas  writes:
> > Well, the problem is that as far as I can see, the admin option is an
> > optional feature of membership. You can grant someone membership
> > without admin option, or with admin option, but you can't grant them
> > the admin option without membership, just like you can't purchase an
> > upgrade to first class without the underlying plane ticket. What would
> > the syntax look even like for this? GRANT foo TO bar WITH ADMIN OPTION
> > BUT WITHOUT MEMBERSHIP? Yikes.
>
> I don't think we need syntax to describe it.  As I just said in my
> other reply, we have a perfectly good precedent for this already
> in ordinary object permissions.  That is: an object owner always,
> implicitly, has GRANT OPTION for all the object's privileges, even
> if she revoked the corresponding plain privilege from herself.
>

So CREATE ROLE will assign ownership of AND membership in the newly created
role to the session_user UNLESS the OWNER clause is present in which case
the named role, so long as the session_user can SET ROLE to the named role,
becomes the owner & member.  Subsequent to that the owner can issue: REVOKE
new_role FROM role_name where role_name is again the session_user role or
one that can be SET ROLE to.


> Yeah, this does mean that we're effectively deciding that the creator
> of a role is its owner.  What's the problem with that?
>

I'm fine with this.  It does introduce an OWNER concept to roles and so at
minimum we need to add:

ALTER ROLE foo OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER |
SESSION_USER }

And similar for CREATE ROLE
And keep the USER alias commands in sync.
GROUP commands are only present for backward compatibility and so don't get
updated with new features by design.

Obviously a superuser can change ownership.

Playing with table ownership I find this behavior:
-- superuser
CREATE ROLE tblowner;
CREATE TABLE tblowner_test (id serial primary key);
ALTER TABLE tblowner_test OWNER TO tblowner;

CREATE ROLE boss;
GRANT boss TO tblowner;

SET SESSION AUTHORIZATION tblowner;
ALTER TABLE tblowner_test OWNER TO boss; --works

So tblowner can push their ownership attribute to any group they are a
member of.  Is that the behavior we want for roles as well?

David J.


Re: role self-revocation

2022-03-09 Thread Tom Lane
Robert Haas  writes:
> Well, the problem is that as far as I can see, the admin option is an
> optional feature of membership. You can grant someone membership
> without admin option, or with admin option, but you can't grant them
> the admin option without membership, just like you can't purchase an
> upgrade to first class without the underlying plane ticket. What would
> the syntax look even like for this? GRANT foo TO bar WITH ADMIN OPTION
> BUT WITHOUT MEMBERSHIP? Yikes.

I don't think we need syntax to describe it.  As I just said in my
other reply, we have a perfectly good precedent for this already
in ordinary object permissions.  That is: an object owner always,
implicitly, has GRANT OPTION for all the object's privileges, even
if she revoked the corresponding plain privilege from herself.

Yeah, this does mean that we're effectively deciding that the creator
of a role is its owner.  What's the problem with that?

> But do we really have to solve this problem before we can clean up
> this session exception?

I think we need a plan for where we're going.  I don't see "clean up
the session exception" as an end in itself; it's part of re-examining
how all of this ought to work.  I don't say that we have to have a
complete patch right away, only that we need a coherent end goal.

regards, tom lane




Re: role self-revocation

2022-03-09 Thread Tom Lane
I wrote:
> This seems like a reasonable answer to me too: the creating role has admin
> option implicitly, and can then choose to grant that to other roles.
> Obviously some work needs to be done to make that happen (and we should
> see whether the SQL spec has some different idea).

Ah, here we go: it's buried under CREATE ROLE.  SQL:2021 12.4  saith that when role A executes CREATE ROLE ,
then

1) A grantable role authorization descriptor is created whose role name
is , whose grantor is "_SYSTEM", and whose grantee is A.

Since nobody is _SYSTEM, this grant can't be deleted except by dropping
the new role (or, maybe, dropping A?).  So that has nearly the same
end result as "the creating role has admin option implicitly".  The main
difference I can see is that it also means the creating role is a *member*
implicitly, which is something I'd argue we don't want to enforce.  This
is analogous to the way we let an object owner revoke her own ordinary
permissions, which the SQL model doesn't allow since those permissions
were granted to her by _SYSTEM.

regards, tom lane




Re: role self-revocation

2022-03-09 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Wed, Mar 9, 2022 at 4:01 PM Tom Lane  wrote:
> > > In my opinion, the right to
> > > administer a role - regardless of whether or not it is a login role -
> > > most naturally vests in the role that created it, or something in that
> > > direction at least, if not that exact thing.
> >
> > This seems like a reasonable answer to me too: the creating role has admin
> > option implicitly, and can then choose to grant that to other roles.
> > Obviously some work needs to be done to make that happen (and we should
> > see whether the SQL spec has some different idea).
> 
> Well, the problem is that as far as I can see, the admin option is an
> optional feature of membership. You can grant someone membership
> without admin option, or with admin option, but you can't grant them
> the admin option without membership, just like you can't purchase an
> upgrade to first class without the underlying plane ticket. What would
> the syntax look even like for this? GRANT foo TO bar WITH ADMIN OPTION
> BUT WITHOUT MEMBERSHIP? Yikes.

I've been meaning to reply to your other email regarding this, but I
don't really agree that the syntax ends up being so terrible or
difficult to deal with, considering we have these same general things
for ALTER ROLE already and there hasn't been all that much complaining.
That is, we have LOGIN and NOLOGIN, CREATEROLE and NOCREATEROLE, and we
could have MEMBERSHIP and NOMEMBERSHIP pretty easily here if we wanted
to.

> But do we really have to solve this problem before we can clean up
> this session exception? I hope not, because I think that's a much
> bigger can of worms than this is.

I do believe we can deal with the above independently and at a later
time and go ahead and clean up the session excepton bit without dealing
with the above at the same time.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-09 Thread Stephen Frost
Greetings,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Robert Haas  writes:
> > On Mar 7, 2022, at 12:16 PM, Tom Lane  wrote:
> > tgl> Having said that, one thing that I find fishy is that it's not clear
> > tgl> where the admin privilege for a role originates.  After "CREATE ROLE
> > tgl> alice", alice has no members, therefore none that have admin privilege,
> > tgl> therefore the only way that the first member could be added is via
> > tgl> superuser deus ex machina.  This does not seem clean.
> 
> > I agree with that, but I don't think it's a sufficient reason for
> > keeping the self-admin exception, because the same problem exists for
> > non-login roles. I don't even think it's the right idea conceptually
> > to suppose that the power to administer a role originates from the
> > role itself.
> 
> Actually, that's the same thing I was trying to say.  But if it doesn't
> originate from the role itself, where does it originate from?
> 
> > In my opinion, the right to
> > administer a role - regardless of whether or not it is a login role -
> > most naturally vests in the role that created it, or something in that
> > direction at least, if not that exact thing.
> 
> This seems like a reasonable answer to me too: the creating role has admin
> option implicitly, and can then choose to grant that to other roles.

I agree that this has some appeal, but it's not desirable in all cases
and so I wouldn't want it to be fully baked into the system ala the role
'owner' concept.

> Obviously some work needs to be done to make that happen (and we should
> see whether the SQL spec has some different idea).

Agreed on this, though I don't recall it having much to say on it.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-09 Thread Robert Haas
On Wed, Mar 9, 2022 at 4:01 PM Tom Lane  wrote:
> > In my opinion, the right to
> > administer a role - regardless of whether or not it is a login role -
> > most naturally vests in the role that created it, or something in that
> > direction at least, if not that exact thing.
>
> This seems like a reasonable answer to me too: the creating role has admin
> option implicitly, and can then choose to grant that to other roles.
> Obviously some work needs to be done to make that happen (and we should
> see whether the SQL spec has some different idea).

Well, the problem is that as far as I can see, the admin option is an
optional feature of membership. You can grant someone membership
without admin option, or with admin option, but you can't grant them
the admin option without membership, just like you can't purchase an
upgrade to first class without the underlying plane ticket. What would
the syntax look even like for this? GRANT foo TO bar WITH ADMIN OPTION
BUT WITHOUT MEMBERSHIP? Yikes.

But do we really have to solve this problem before we can clean up
this session exception? I hope not, because I think that's a much
bigger can of worms than this is.

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




Re: role self-revocation

2022-03-09 Thread Tom Lane
Robert Haas  writes:
> On Mar 7, 2022, at 12:16 PM, Tom Lane  wrote:
> tgl> Having said that, one thing that I find fishy is that it's not clear
> tgl> where the admin privilege for a role originates.  After "CREATE ROLE
> tgl> alice", alice has no members, therefore none that have admin privilege,
> tgl> therefore the only way that the first member could be added is via
> tgl> superuser deus ex machina.  This does not seem clean.

> I agree with that, but I don't think it's a sufficient reason for
> keeping the self-admin exception, because the same problem exists for
> non-login roles. I don't even think it's the right idea conceptually
> to suppose that the power to administer a role originates from the
> role itself.

Actually, that's the same thing I was trying to say.  But if it doesn't
originate from the role itself, where does it originate from?

> In my opinion, the right to
> administer a role - regardless of whether or not it is a login role -
> most naturally vests in the role that created it, or something in that
> direction at least, if not that exact thing.

This seems like a reasonable answer to me too: the creating role has admin
option implicitly, and can then choose to grant that to other roles.
Obviously some work needs to be done to make that happen (and we should
see whether the SQL spec has some different idea).

regards, tom lane




Re: role self-revocation

2022-03-09 Thread Robert Haas
On Mon, Mar 7, 2022 at 11:14 PM Mark Dilger
 wrote:
> > On Mar 7, 2022, at 12:16 PM, Tom Lane  wrote:
> > What would be
> > lost if we drop it?
>
> I looked into this a bit.  Removing that bit of code, the only regression 
> test changes for "check-world" are the expected ones, with nothing else 
> breaking.  Running installcheck+pg_upgrade to the patched version of HEAD 
> from each of versions 11, 12, 13 and 14 doesn't turn up anything untoward.

I looked into this a bit, too. I attach a draft patch for removing the
self-admin exception.

I found that having is_admin_of_role() return true matters in three
ways: (1) It lets you grant membership in the role to some other role.
(2) It lets you revoke membership in the role from some other role.
(3) It changes the return value of pg_role_aclcheck(), which is used
in the implementation of various SQL-callable functions all invoked
via the name pg_has_role(). We've mostly been discussing (2) as an
issue, but (1) and (3) are pretty interesting too. Regarding (3),
there is a comment in the code indicating that Noah considered the
self-admin exception something of a wart as far as pg_has_role() is
concerned. As to (1), I discovered that today you can do this:

rhaas=# create user foo;
CREATE ROLE
rhaas=# create user bar;
CREATE ROLE
rhaas=# \q
[rhaas ~]$ psql -U foo rhaas
psql (15devel)
Type "help" for help.

rhaas=> grant foo to bar with admin option;
GRANT ROLE

I don't know why I didn't realize that before. It's a natural result
of treating the logged-in user as if they had admin option. But it's
weird that you can't even be granted WITH ADMIN OPTION on your own
login role, but at the same time without having it you can grant it to
someone else!

I believe there are three other points worth some consideration here.

First, in the course of my investigation I re-discovered what Tom
already did a good job articulating:

tgl> Having said that, one thing that I find fishy is that it's not clear
tgl> where the admin privilege for a role originates.  After "CREATE ROLE
tgl> alice", alice has no members, therefore none that have admin privilege,
tgl> therefore the only way that the first member could be added is via
tgl> superuser deus ex machina.  This does not seem clean.

I agree with that, but I don't think it's a sufficient reason for
keeping the self-admin exception, because the same problem exists for
non-login roles. I don't even think it's the right idea conceptually
to suppose that the power to administer a role originates from the
role itself. If that were so, then it would be inherited by all
members of the role along with all the rest of the role's privileges,
which is so clearly not right that we've already prohibited a role
from having WITH ADMIN OPTION on itself. In my opinion, the right to
administer a role - regardless of whether or not it is a login role -
most naturally vests in the role that created it, or something in that
direction at least, if not that exact thing. Today, that means the
superuser or a CREATEROLE user who could hack superuser if they
wished. In the future, I hope for other alternatives, as recently
argued on other threads. But we need not resolve the question of how
that should work exactly in order to agree (as I hope we do) that
doubling down on the self-administration exception is not the answer.

Second, it occured to me to wonder what implications a change like
this might have for dump and restore. If privilege restoration somehow
relied on this behavior, then we'd have a problem. But I don't think
it does, because (a) pg_dump can SET ROLE but can't change the session
user without reconnecting, so it's unclear how we could be relying on
it; (b) it wouldn't work for non-login roles, and it's unlikely that
we would treat login and non-login roles different in terms of
restoring privileges, and (c) when I execute the example shown above
and then run pg_dump, there's no attempt to change the current user,
it just dumps "GRANT foo TO bar WITH ADMIN OPTION GRANTED BY foo".

Third, it occurred to me to wonder whether some users might be using
and relying upon this behavior. It's certainly possible, and it does
suck that we'd be removing it without providing a workable substitute.
But it's probably not a LOT of users because most people who have
commented on this topic on this mailing list seem to find granting
membership in a login role a super-weird thing to do, because a lot of
people really seem to want every role to be a user or a group, and a
login role with members feels like it's blurring that line. I'm
inclined to think that the small number of people who may be unhappy
is an acceptable price to pay for removing this wart, but it's a
judgement call and if someone has information to suggest that I'm
wrong, it'd be good to hear about that.

Thanks,

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


remove-self-admin.patch
Description: Binary data


Re: role self-revocation

2022-03-09 Thread Robert Haas
On Wed, Mar 9, 2022 at 7:55 AM Peter Eisentraut
 wrote:
> Do we have subtractive permissions today?

Not in the GRANT/REVOKE sense, I think, but you can put a user in a
group and then mention that group in pg_hba.conf. And that line might
be "reject" or whatever.

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




Re: role self-revocation

2022-03-09 Thread Peter Eisentraut

On 07.03.22 19:18, Robert Haas wrote:

That all said, permissions SHOULD BE strictly additive.  If boss doesn't want 
to be a member of pg_read_all_files allowing them to revoke themself from that 
role seems like it should be acceptable.  If there is fear in allowing someone 
to revoke (not add) themselves as a member of a different role that suggests we 
have a design issue in another feature of the system.  Today, they neither 
grant nor revoke, and the self-revocation doesn't seem that important to add.

I disagree with this on principle, and I also think that's not how it
works today. On the general principle, I do not see a compelling
reason why we should have two systems for maintaining groups of users,
one of which is used for additive things and one of which is used for
subtractive things.


Do we have subtractive permissions today?





Re: role self-revocation

2022-03-07 Thread Mark Dilger


> On Mar 7, 2022, at 12:16 PM, Tom Lane  wrote:
> 
> What would be
> lost if we drop it?

I looked into this a bit.  Removing that bit of code, the only regression test 
changes for "check-world" are the expected ones, with nothing else breaking.  
Running installcheck+pg_upgrade to the patched version of HEAD from each of 
versions 11, 12, 13 and 14 doesn't turn up anything untoward.  The change I 
used (for reference) is attached:



v1-0001-WIP-Removing-role-self-administration.patch.WIP
Description: Binary data


—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company





Re: role self-revocation

2022-03-07 Thread David G. Johnston
On Mon, Mar 7, 2022 at 1:16 PM Tom Lane  wrote:

> Based on Robert's archaeological dig, it now seems that the fact that
> we have any such behavior at all was just a mistake.  What would be
> lost if we drop it?
>

Probably nothing that couldn't be replaced, and with a better model, but I
do have a concern that there are setups in the wild inadvertently using
this behavior.  Enough so that I would vote to change it but include a
migration GUC to restore the current behavior, probably with a deprecation
warning.  Kinda depends on the post-change dump/restore mechanics.  But
just tearing it out wouldn't seem extraordinary for us.


>
> Having said that, one thing that I find fishy is that it's not clear
> where the admin privilege for a role originates.


I do not see a problem with there being no inherent admin privilege for a
role.  A superuser or CREATEROLE user holds admin privilege on all roles in
the cluster.  They can delegate the privilege to administer a role to yet
another role in the system.  The necessitates creating two roles - the one
being administered and the one being delegated to.  I don't see a benefit
to saving which specific superuser or CREATEROLE user "owns" the role that
is to be administered.  Not unless non-owner CREATEROLE users are prevented
from exercising admin privileges on the role.  That all said, I'd accept
the choice to include such ownership information as a requirement for
meeting the auditing needs of DBAs.  But I would argue that such auditing
probably needs to be external to the working system - the fact that
ownership can be changed reduces the benefit of an in-database value.

> If we recorded

which user created the role, we could act as though that user has
> admin privilege (whether or not it's a member).


I suppose we could record the current owner of a role but that seems
unnecessary.  I dislike using the "created" concept by virtue of the fact
that, for routines, "security definer" implies creator but it actually
means "security owner".

David J.


Re: role self-revocation

2022-03-07 Thread Tom Lane
Mark Dilger  writes:
>> On Mar 7, 2022, at 12:01 PM, Robert Haas  wrote:
>> 
>> It's been pointed out upthread that this would have undesirable
>> security implications, because the admin option would be inherited,
>> and the implicit permission isn't.

> Right, but with a reflexive self-admin-option, we could document that it 
> works in a non-inherited way.  We'd just be saying the current hard-coded 
> behavior is an option which can be revoked rather than something you're stuck 
> with.

After reflection, I think that role self-admin is probably a bad idea that
we should stay away from.  It could perhaps be reasonable given some other
system design and/or syntax than what SQL gives us, but we're dealing in
SQL.  It doesn't make sense to GRANT a role to itself, and therefore it
likewise doesn't make sense to GRANT WITH ADMIN OPTION.

Based on Robert's archaeological dig, it now seems that the fact that
we have any such behavior at all was just a mistake.  What would be
lost if we drop it?

Having said that, one thing that I find fishy is that it's not clear
where the admin privilege for a role originates.  After "CREATE ROLE
alice", alice has no members, therefore none that have admin privilege,
therefore the only way that the first member could be added is via
superuser deus ex machina.  This does not seem clean.  If we recorded
which user created the role, we could act as though that user has
admin privilege (whether or not it's a member).  Perhaps I'm
reinventing something that was already discussed upthread.  I wonder
what the SQL spec has to say on this point, too.

regards, tom lane




Re: role self-revocation

2022-03-07 Thread Mark Dilger



> On Mar 7, 2022, at 12:03 PM, Mark Dilger  wrote:
> 
> Right, but with a reflexive self-admin-option, we could document that it 
> works in a non-inherited way.  We'd just be saying the current hard-coded 
> behavior is an option which can be revoked rather than something you're stuck 
> with.

We could also say that the default is to not have admin option on yourself, 
with that being something grantable, but that is a larger change from the 
historical behavior and might have more consequences for dump/restore, etc.

My concern about just nuking self-admin is that there may be sites which use 
self-admin and we'd be leaving them without a simple work-around after upgrade, 
because they couldn't restore the behavior by executing a grant.  They'd have 
to more fundamentally restructure their role relationships to not depend on 
self-admin, something which might be harder for them to do.  Perhaps nobody is 
using self-admin, or very few people are using it, and I'm being overly 
concerned.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-07 Thread Mark Dilger



> On Mar 7, 2022, at 12:01 PM, Robert Haas  wrote:
> 
> It's been pointed out upthread that this would have undesirable
> security implications, because the admin option would be inherited,
> and the implicit permission isn't.

Right, but with a reflexive self-admin-option, we could document that it works 
in a non-inherited way.  We'd just be saying the current hard-coded behavior is 
an option which can be revoked rather than something you're stuck with.

—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-07 Thread Robert Haas
On Mon, Mar 7, 2022 at 2:59 PM Mark Dilger  wrote:
> This test failure is just a manifestation of the intended change, but 
> assuming we make no other changes, the error message would clearly need to be 
> updated, because it suggests the role should have admin_option on itself, a 
> situation which is not currently supported.

It's been pointed out upthread that this would have undesirable
security implications, because the admin option would be inherited,
and the implicit permission isn't.

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




Re: role self-revocation

2022-03-07 Thread Mark Dilger



> On Mar 7, 2022, at 10:28 AM, Tom Lane  wrote:
> 
> Does anything interesting break if you do just take it out?

 SET SESSION AUTHORIZATION regress_priv_group2;
 GRANT regress_priv_group2 TO regress_priv_user5; -- ok: a role can self-admin
-NOTICE:  role "regress_priv_user5" is already a member of role 
"regress_priv_group2"
+ERROR:  must have admin option on role "regress_priv_group2"

This test failure is just a manifestation of the intended change, but assuming 
we make no other changes, the error message would clearly need to be updated, 
because it suggests the role should have admin_option on itself, a situation 
which is not currently supported.

Perhaps we should support that, though, by adding a reflexive aclitem[] to 
pg_authid (meaning it tracks which privileges a role has on itself) with 
tracking of who granted it, so that revocation can be handled properly.  The 
aclitem could start out null, meaning the role has by default the traditional 
limited self-admin which the code comments discuss:

/*
 * A role can admin itself when it matches the session user and we're
 * outside any security-restricted operation, SECURITY DEFINER or
 * similar context.  SQL-standard roles cannot self-admin.  However,
 * SQL-standard users are distinct from roles, and they are not
 * grantable like roles: PostgreSQL's role-user duality extends the
 * standard.  Checking for a session user match has the effect of
 * letting a role self-admin only when it's conspicuously behaving
 * like a user.  Note that allowing self-admin under a mere SET ROLE
 * would make WITH ADMIN OPTION largely irrelevant; any member could
 * SET ROLE to issue the otherwise-forbidden command.
 *
 * Withholding self-admin in a security-restricted operation prevents
 * object owners from harnessing the session user identity during
 * administrative maintenance.  Suppose Alice owns a database, has
 * issued "GRANT alice TO bob", and runs a daily ANALYZE.  Bob creates
 * an alice-owned SECURITY DEFINER function that issues "REVOKE alice
 * FROM carol".  If he creates an expression index calling that
 * function, Alice will attempt the REVOKE during each ANALYZE.
 * Checking InSecurityRestrictedOperation() thwarts that attack.
 *
 * Withholding self-admin in SECURITY DEFINER functions makes their
 * behavior independent of the calling user.  There's no security or
 * SQL-standard-conformance need for that restriction, though.
 *
 * A role cannot have actual WITH ADMIN OPTION on itself, because that
 * would imply a membership loop.  Therefore, we're done either way.
 */

For non-null aclitem[], we could support REVOKE ADMIN OPTION FOR joe FROM joe, 
and for explicit re-grants, we could track who granted it, such that further 
revocations could properly refuse if the revoker doesn't have sufficient 
privileges vis-a-vis the role that granted it in the first place.

I have not yet tried to implement this, and might quickly hit problems with the 
idea, but will take a stab at a proof-of-concept patch unless you suggest a 
better approach.

Thoughts?


—
Mark Dilger
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company







Re: role self-revocation

2022-03-07 Thread Robert Haas
On Mon, Mar 7, 2022 at 2:29 PM David G. Johnston
 wrote:
> You mean the one that was based upon your "ooops"...I discounted that 
> immediately because members cannot revoke their own membership in a group 
> unless they were given WITH ADMIN OPTION on that group.

Oh, hmm. That example might be backwards from the case I'm talking about.

> The mere fact that the pg_hba.conf concern raised there hasn't been reported 
> as a live issue suggests the lack of any meaningful design flaw here.

Not really. The system is full of old bugs, just as all software
system are, and the particular role self-administration behavior that
is at issue here appears to be something that was accidentally
introduced 16 years years ago in a commit that did something else and
never scrutinized from a design perspective since then.

Personally, I've been shocked by the degree to which this entire area
seems to be full of design flaws and half-baked code. I mean, just the
fact that the pg_auth_members.grantor can be left pointing to a role
OID that no longer exists is pretty crazy, right? I don't think anyone
today would consider something with that kind of wart committable.

> That isn't to say that having a LOGIN role get an automatic temporary WITH 
> ADMIN OPTION on itself is a good thing - but there isn't any privilege 
> escalation vector here to be squashed.  There is just a "DBAs should treat 
> LOGIN roles as leaf nodes" expectation in which case there would be no 
> superuser granted memberships to be removed.

Well, we may not have found one yet, but that doesn't prove none
exists. In any case, if we can agree that it's not necessarily a
desirable behavior, that's good enough for me.

(I still disagree with the idea that LOGIN roles have to be leaf
nodes. We could have a system where that's true, but that's not how
the system we actually have is designed.)

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




Re: role self-revocation

2022-03-07 Thread David G. Johnston
On Mon, Mar 7, 2022 at 11:18 AM Robert Haas  wrote:

> In terms of how
>
things work today, see Joshua Brindle's email about the use of groups
> in pg_hba.conf. That is an excellent example of how removing oneself
> from a group could enable one to bypass security restrictions intended
> by the DBA.
>
>
You mean the one that was based upon your "ooops"...I discounted that
immediately because members cannot revoke their own membership in a group
unless they were given WITH ADMIN OPTION on that group.

The mere fact that the pg_hba.conf concern raised there hasn't been
reported as a live issue suggests the lack of any meaningful design flaw
here.

That isn't to say that having a LOGIN role get an automatic temporary WITH
ADMIN OPTION on itself is a good thing - but there isn't any privilege
escalation vector here to be squashed.  There is just a "DBAs should treat
LOGIN roles as leaf nodes" expectation in which case there would be no
superuser granted memberships to be removed.

David J.


Re: role self-revocation

2022-03-07 Thread Stephen Frost
Greetings,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Stephen Frost  writes:
> > I'm not quite following this bit.  Where would SET ROLE come into play
> > when we're talking about old dump scripts and how the commands in those
> > scripts might be interpreted by newer versions of PG..?
> 
> No, the concern there is the other way around: what if you take a
> script made by newer pg_dump and try to load it into an older server
> that doesn't have the GRANTED BY option?

Wow.  No, I really don't think I can agree that we need to care about
this.

> We're accustomed to saying that that doesn't work if you use a
> database feature that didn't exist in the old server, but
> privilege grants are hardly that.  I don't want us to change the
> pg_dump output in such a way that the grants can't be restored at all
> to an older server, just because of a syntax choice that we could
> make backwards-compatibly instead of not-backwards-compatibly.

GRANTED BY is clearly such a feature that exists in the newer version
and doesn't exist in the older and I can't agree that we should
complicate things for ourselves and bend over backwards to try and make
it work to take a dump from a newer version of PG and make it work on
random older versions.

Folks are also able to exclude privileges from dumps if they want to.

Where do we document that we are going to put in effort to make these
kinds of things work?  What other guarantees are we supposed to be
providing regarding using output from a newer pg_dump against older
servers?  What about newer custom format dumps?  Surely you're not
suggesting that we need to back-patch support for them to released
versions of pg_restore.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-07 Thread Robert Haas
On Mon, Mar 7, 2022 at 1:58 PM Tom Lane  wrote:
> Stephen Frost  writes:
> > I'm not quite following this bit.  Where would SET ROLE come into play
> > when we're talking about old dump scripts and how the commands in those
> > scripts might be interpreted by newer versions of PG..?
>
> No, the concern there is the other way around: what if you take a
> script made by newer pg_dump and try to load it into an older server
> that doesn't have the GRANTED BY option?
>
> We're accustomed to saying that that doesn't work if you use a
> database feature that didn't exist in the old server, but
> privilege grants are hardly that.  I don't want us to change the
> pg_dump output in such a way that the grants can't be restored at all
> to an older server, just because of a syntax choice that we could
> make backwards-compatibly instead of not-backwards-compatibly.

Are you absolutely positive that it's that simple? I mean, what if the
SET ROLE command has other side effects, or if the GRANT command
behaves differently in some way as a result of the SET ROLE having
been done? I feel like a solution that involves explicitly specifying
the behavior that we want (i.e. GRANTED BY) is likely to be more
reliable and more secure than a solution which involves absorbing a
key value from a session property (i.e. the role established by SET
ROLE). Even if we decide that SET ROLE is the way to go for
compatibility reasons, I would personally say that it's an inferior
hack only worth accepting for that reason than a truly desirable
design.

See CVE-2018-1058 for an example of what I'm talking about. The
prevailing search_path turned out to affect not only the creation
schema, as intended, but also the resolution of references to other
objects mentioned in the CREATE COMMAND, as not intended. I don't see
a similar hazard here, but I'm worried that there might be one.
Declarative syntax is a very powerful tool for avoiding those kinds of
mishaps, and I think we should make as much use of it as we can.

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




Re: role self-revocation

2022-03-07 Thread Stephen Frost
Greetings,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Stephen Frost  writes:
> > * Tom Lane (t...@sss.pgh.pa.us) wrote:
> >> Agreed, this is not something to move on quickly.  We might want
> >> to think about adjusting pg_dump to use explicit GRANTED BY
> >> options in GRANT/REVOKE a release or two before making incompatible
> >> changes.
> 
> > I'm with Robert on this though- folks should know already that they need
> > to use the pg_dump of the version of PG that they want to move to and
> > not try to re-use older pg_dump output with newer versions, for a number
> > of reasons and this is just another.
> 
> Yeah, in an ideal world you'd do that, but our users don't always have
> the luxury of living in an ideal world.  Sometimes all you've got is
> an old pg_dump file.  Perhaps this behavior wouldn't mess things up
> enough to make the restored database unusable, but we need to think
> about (and test) that case while we're considering changes.

I agree it's something to consider and deal with if we're able to do so
sanely, but I disagree that we should be beholden to old dump files when
considering how to move the project forward.  Further, they can surely
build and install the version of PG that goes with that dump file in a
great many cases and then dump the data out using a newer version of
pg_dump.  For 5 years they could do that with a completely supported
version of PG, but we've recently agreed to make an effort to do more
here by supporting the building of even older versions on modern
systems.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-07 Thread Tom Lane
Stephen Frost  writes:
> I'm not quite following this bit.  Where would SET ROLE come into play
> when we're talking about old dump scripts and how the commands in those
> scripts might be interpreted by newer versions of PG..?

No, the concern there is the other way around: what if you take a
script made by newer pg_dump and try to load it into an older server
that doesn't have the GRANTED BY option?

We're accustomed to saying that that doesn't work if you use a
database feature that didn't exist in the old server, but
privilege grants are hardly that.  I don't want us to change the
pg_dump output in such a way that the grants can't be restored at all
to an older server, just because of a syntax choice that we could
make backwards-compatibly instead of not-backwards-compatibly.

regards, tom lane




Re: role self-revocation

2022-03-07 Thread Tom Lane
Stephen Frost  writes:
> * Tom Lane (t...@sss.pgh.pa.us) wrote:
>> Agreed, this is not something to move on quickly.  We might want
>> to think about adjusting pg_dump to use explicit GRANTED BY
>> options in GRANT/REVOKE a release or two before making incompatible
>> changes.

> I'm with Robert on this though- folks should know already that they need
> to use the pg_dump of the version of PG that they want to move to and
> not try to re-use older pg_dump output with newer versions, for a number
> of reasons and this is just another.

Yeah, in an ideal world you'd do that, but our users don't always have
the luxury of living in an ideal world.  Sometimes all you've got is
an old pg_dump file.  Perhaps this behavior wouldn't mess things up
enough to make the restored database unusable, but we need to think
about (and test) that case while we're considering changes.

regards, tom lane




Re: role self-revocation

2022-03-07 Thread Stephen Frost
Greetings,

* Robert Haas (robertmh...@gmail.com) wrote:
> On Sun, Mar 6, 2022 at 11:34 AM Tom Lane  wrote:
> > I was thinking the former ... however, after a bit of experimentation
> > I see that we accept "grant foo to bar granted by baz" a VERY long
> > way back, but the "granted by" option for object privileges is
> > (a) pretty new and (b) apparently restrictively implemented:
> >
> > regression=# grant delete on alices_table to bob granted by alice;
> > ERROR:  grantor must be current user
> >
> > That's ... surprising.  I guess whoever put that in was only
> > interested in pro-forma SQL syntax compliance and not in making
> > a usable feature.
> 
> It appears so: 
> https://www.postgresql.org/message-id/2073b6a9-7f79-5a00-5f26-cd19589a52c7%402ndquadrant.com
> 
> It doesn't seem like that would be hard to fix. Maybe we should just do that.

Yeah, that seems like something that should be fixed.  Superusers should
be allowed to set GRANTED BY to whatever they feel like, and I'd argue
that a role who wants a GRANT to actually be GRANTED BY some other role
they're a member of should also be allowed to (as they could anyway by
doing a SET ROLE), provided that role also has the privileges to do the
GRANT itself, of course.

> > So if we decide to extend this change into object privileges
> > it would be advisable to use SET ROLE, else we'd be giving up
> > an awful lot of backwards compatibility in dump scripts.
> > But if we're only talking about role grants then I think
> > GRANTED BY would work fine.
> 
> OK.

I'm not quite following this bit.  Where would SET ROLE come into play
when we're talking about old dump scripts and how the commands in those
scripts might be interpreted by newer versions of PG..?

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-07 Thread David G. Johnston
On Mon, Mar 7, 2022 at 11:18 AM Robert Haas  wrote:

> On Sun, Mar 6, 2022 at 11:01 PM David G. Johnston
>  wrote:
> > The example, which you moved here, then attempts to demonstrate this
> "fact" but gets it wrong.  Boss became a member of peon so if you want to
> demonstrate self-administration of a role's membership in a different group
> you have to login as boss, not peon.  Doing that, and then revoking peon
> from boss, yields "ERROR: must have admin option on role "peon"".
>
> This doesn't seem to me to be making a constructive argument. I showed
> an example with certain names demonstrating a certain behavior that I
> find problematic.


Whether you choose the wording of the original thread:

"This is because we allow 'self administration' of roles, meaning that
they can decide what other roles they are a member of."

https://www.postgresql.org/message-id/flat/20211005025746.GN20998%40tamriel.snowman.net

Or you quote at the top of this one:

> The ability of a role to revoke itself from some other role is just
> something we need to accept as being a change that needs to be made,

This example:

rhaas=# create user boss;
CREATE ROLE
rhaas=# create user peon;
CREATE ROLE
rhaas=# grant peon to boss;
GRANT ROLE
rhaas=# \c - peon
You are now connected to database "rhaas" as user "peon".
rhaas=> revoke peon from boss; -- i don't like being bossed around!
REVOKE ROLE

Fails to demonstrate the boss "can revoke itself from peon" / "boss can
decide what other roles they are a member of."

You are logged in as peon when you do the revoke, not boss, so the extent
of what "boss" can or cannot do has not been shown.

boss is a member of peon, not the other way around.  That the wording
"grant peon to boss" makes you think otherwise is unfortunate.

David J.


Re: role self-revocation

2022-03-07 Thread Stephen Frost
Greetings,

* Tom Lane (t...@sss.pgh.pa.us) wrote:
> Robert Haas  writes:
> > 1. What should be the exact rule for whether A can remove a grant made
> > by B? Is it has_privs_of_role()? is_member_of_role()? Something else?
> 
> No strong opinion here, but I'd lean slightly to the more restrictive
> option.
> 
> > 2. What happens if the same GRANT is enacted by multiple users? For
> > example, suppose peon does "GRANT peon to boss" and then the superuser
> > does the same thing afterwards, or vice versa? One design would be to
> > try to track those as two separate grants, but I'm not sure if we want
> > to add that much complexity, since that's not how we do it now and it
> > would, for example, implicate the choice of PK on the pg_auth_members
> > table.
> 
> As you note later, we *do* track such grants separately in ordinary
> ACLs, and I believe this is clearly required by the SQL spec.

Agreed.

> It says (for privileges on objects):
> 
> Each privilege is represented by a privilege descriptor.
> A privilege descriptor contains:
> — The identification of the object on which the privilege is granted.
> — The  of the grantor of the privilege.
>   ^^^
> — The  of the grantee of the privilege.
> — Identification of the action that the privilege allows.
> — An indication of whether or not the privilege is grantable.
> — An indication of whether or not the privilege has the WITH HIERARCHY 
> OPTION specified.
> 
> Further down (4.42.3 in SQL:2021), the granting of roles is described,
> and that says:
> 
> Each role authorization is described by a role authorization descriptor.
> A role authorization descriptor includes:
> — The role name of the role.
> — The authorization identifier of the grantor.
>   
> — The authorization identifier of the grantee.
> — An indication of whether or not the role authorization is grantable.
> 
> If we are not tracking the grantors of role authorizations,
> then we are doing it wrong and we ought to fix that.

Yup, and as noted elsewhere, we are tracking it but not properly dealing
with dependencies nor are we considering the grantor when REVOKE is run.

Looking at the spec for REVOKE is quite useful when trying to understand
how this is all supposed to work (and, admittedly, isn't something I did
enough of when I did the original work on roles... sorry about that, was
early on).  In particular, a REVOKE only works when it finds something
to revoke/remove, and part of that search includes basically "was it the
current role who was the grantor?"

The specific language here being: A role authorization descriptor is
said to be identified if it defines the grant of any of the specified
roles revoked to grantee with grantor A.

Basically, a role authorization descriptor isn't identified unless it's
one that this user/role had previously granted.

> > 3. What happens if a user is dropped after being recorded as a
> > grantor?
> 
> Should work the same as it does now for ordinary ACLs, ie, you
> gotta drop the grant first.

Agreed.

> > 4. Should we apply this rule to other types of grants, rather than
> > just to role membership?
> 
> I am not sure about the reasoning behind the existing rule that
> superuser-granted privileges are recorded as being granted by the
> object owner.  It does feel more like a wart than something we want.
> It might have been a hack to deal with the lack of GRANTED BY
> options in GRANT/REVOKE back in the day.

Yeah, that doesn't seem right and isn't great.

> Changing it could have some bad compatibility consequences though.
> In particular, I believe it would break existing pg_dump files,
> in that after restore all privileges would be attributed to the
> restoring superuser, and there'd be no very easy way to clean that
> up.

Ugh, that's pretty grotty, certainly.

> > Please note that it is not really my intention to try to shove
> > anything into v15 here.
> 
> Agreed, this is not something to move on quickly.  We might want
> to think about adjusting pg_dump to use explicit GRANTED BY
> options in GRANT/REVOKE a release or two before making incompatible
> changes.

I'm with Robert on this though- folks should know already that they need
to use the pg_dump of the version of PG that they want to move to and
not try to re-use older pg_dump output with newer versions, for a number
of reasons and this is just another.

Thanks,

Stephen


signature.asc
Description: PGP signature


Re: role self-revocation

2022-03-07 Thread Robert Haas
On Mon, Mar 7, 2022 at 1:28 PM Tom Lane  wrote:
> Ugh, I think you are right.  It's been a long time of course, but it sure
> looks like that was copied-and-pasted without recognizing that it was
> wrong in this function because of the need to check the admin_option flag.
> And then in the later security discussion we didn't realize that the
> problematic behavior was a flat-out thinko, so we narrowed it as much as
> we could instead of just taking it out.
>
> Does anything interesting break if you do just take it out?

That is an excellent question, but I haven't had time yet to
investigate the matter.

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




Re: role self-revocation

2022-03-07 Thread Tom Lane
Robert Haas  writes:
> It appears to me that the actual behavior of having is_admin_of_role()
> return true when member == role dates to
> f9fd1764615ed5d85fab703b0ffb0c323fe7dfd5 (Tom Lane, 2005). If I'm not
> reading this code wrong, prior to that commit, it seems to me that we
> only searched the roles that were members of that role, directly or
> indirectly, and you had to have admin_option on the last hop of the
> membership chain in order to get a "true" result. But that commit,
> among other changes, made member == role a special case, but the
> comment just says /* Fast path for simple case */ which makes it
> appear that it wasn't thought to be a behavior change at all, but it
> looks to me like it was. Am I confused?

Ugh, I think you are right.  It's been a long time of course, but it sure
looks like that was copied-and-pasted without recognizing that it was
wrong in this function because of the need to check the admin_option flag.
And then in the later security discussion we didn't realize that the
problematic behavior was a flat-out thinko, so we narrowed it as much as
we could instead of just taking it out.

Does anything interesting break if you do just take it out?

regards, tom lane




Re: role self-revocation

2022-03-07 Thread Robert Haas
On Sun, Mar 6, 2022 at 11:01 PM David G. Johnston
 wrote:
> The example, which you moved here, then attempts to demonstrate this "fact" 
> but gets it wrong.  Boss became a member of peon so if you want to 
> demonstrate self-administration of a role's membership in a different group 
> you have to login as boss, not peon.  Doing that, and then revoking peon from 
> boss, yields "ERROR: must have admin option on role "peon"".

This doesn't seem to me to be making a constructive argument. I showed
an example with certain names demonstrating a certain behavior that I
find problematic. You don't have to think it's problematic, and you
can show other examples that demonstrate things you want to show. But
please don't tell me that when I literally cut and paste the output
from my terminal into an email window, what I'm showing is somehow
counterfactual. The behavior as it exists today is surely a fact, and
an easily demonstrable one at that. It's not a "fact'" in quotes, and
it doesn't "get it wrong". It is the actual behavior and the example
with the names I picked demonstrates precisely what I want to
demonstrate. When you say that I should have chosen a different
example or used different identifier names or talked about it in
different way, *that* is an opinion. I believe that you are wholly
entitled to that opinion, even if (as in this case) I disagree, but I
believe that it is not right at all to make it sound as if I don't
have the right to pick the examples I care about, or as if terminal
output is not a factual representation of how things work today.

> So no, without "WITH ADMIN OPTION" a role cannot decide what other roles they 
> are a member of.

It clearly can in some limited cases, because I showed an example
demonstrating *exactly that thing*.

> I don't necessarily have an issue changing self-administration but if the 
> motivating concern is that all these new pg_* roles we are creating are 
> something a normal user can opt-out of/revoke that simply isn't the case 
> today, unless they are added to the pg_* role WITH ADMIN OPTION.

I agree with this, but that's not my concern, because that's a
different use case from the one that I complained about. Since the
session user exception only applies to login roles, the problem that
I'm talking about only occurs when a login role is granted to some
other role.

> That all said, permissions SHOULD BE strictly additive.  If boss doesn't want 
> to be a member of pg_read_all_files allowing them to revoke themself from 
> that role seems like it should be acceptable.  If there is fear in allowing 
> someone to revoke (not add) themselves as a member of a different role that 
> suggests we have a design issue in another feature of the system.  Today, 
> they neither grant nor revoke, and the self-revocation doesn't seem that 
> important to add.

I disagree with this on principle, and I also think that's not how it
works today. On the general principle, I do not see a compelling
reason why we should have two systems for maintaining groups of users,
one of which is used for additive things and one of which is used for
subtractive things. That is a lot of extra machinery for little gain,
especially given how close we are to having it sorted out so that the
same mechanism can serve both purposes. It presently appears to me
that if we either remove the session user exception OR do the
grantor-tracking thing discussed earlier, we can get to a place where
the same facility can be used for either purpose. That would, I think,
be a significant step forward over the status quo. In terms of how
things work today, see Joshua Brindle's email about the use of groups
in pg_hba.conf. That is an excellent example of how removing oneself
from a group could enable one to bypass security restrictions intended
by the DBA.

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




Re: role self-revocation

2022-03-07 Thread Robert Haas
On Mon, Mar 7, 2022 at 11:04 AM Tom Lane  wrote:
> > Is there some use case for the behavior described in that last
> > sentence?
>
> Good question.  You might try figuring out when that text was added
> and then see if there's relevant discussion in the archives.

Apparently the permission used to be broader, and commit
fea164a72a7bfd50d77ba5fb418d357f8f2bb7d0 (February 2014, Noah,
CVE-2014-0060) restricted it by requiring that (a) the user had to be
the logged-in user, rather than an identity assumed via SET ROLE (so
maybe my bogus example from before would have worked in 2013) and (b)
that we're not in a security-restricted operation at the time.

Interestingly, it appears to me that the behavior wasn't documented
prior to that commit. The previous text read simply:

If WITH ADMIN OPTION is specified, the member can
in turn grant membership in the role to others, and revoke membership
in the role as well.  Without the admin option, ordinary users cannot do
that.

That doesn't give any hint that self-administration is a special case.

I reviewed the (private) discussion of this vulnerability on the
pgsql-security mailing list where various approaches were considered.
I think it's safe to share a few broad details about that conversation
publicly now, since it was many years ago and the fix has long since
been published. There was discussion of making this
self-administration behavior something that could be turned off, but
such a change was deemed too large for the back-branches. There was no
discussion that I could find about removing the behavior altogether.
It was noted that having a special case for this was different than
granting WITH ADMIN OPTION because WITH ADMIN OPTION is inherited and
being logged in as a certain user is not.

It appears to me that the actual behavior of having is_admin_of_role()
return true when member == role dates to
f9fd1764615ed5d85fab703b0ffb0c323fe7dfd5 (Tom Lane, 2005). If I'm not
reading this code wrong, prior to that commit, it seems to me that we
only searched the roles that were members of that role, directly or
indirectly, and you had to have admin_option on the last hop of the
membership chain in order to get a "true" result. But that commit,
among other changes, made member == role a special case, but the
comment just says /* Fast path for simple case */ which makes it
appear that it wasn't thought to be a behavior change at all, but it
looks to me like it was. Am I confused?

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




Re: role self-revocation

2022-03-07 Thread David G. Johnston
On Mon, Mar 7, 2022 at 9:04 AM Tom Lane  wrote:

> Just looking at it now, without having done any historical research,
>
I wonder why it is that we don't attach significance to WITH ADMIN
> OPTION being granted to the role itself.  It seems like the second
> part of that sentence is effectively saying that a role DOES have
> admin option on itself, contradicting the first part.
>
>
WITH ADMIN OPTION is inheritable which is really bad if the group has WITH
ADMIN OPTION on itself.  The session_user exception temporarily grants WITH
ADMIN OPTION to the group but it is done in such a way so that it is not
inheritable.

There is no possible way to even assign WITH ADMIN OPTION on a role to
itself since pg_auth_members doesn't record a self-relationship and
admin_option only exists there.

David J.

P.S. Feature request; modify \du+ to show which "Member of" roles a given
role has the WITH ADMIN OPTION privilege on.


Re: role self-revocation

2022-03-07 Thread Tom Lane
Robert Haas  writes:
> Hmm. I think the real issue is what David Johnson calls the session
> user exception. I hadn't quite understood how that played into this.
> According to the documentation: "If WITH ADMIN OPTION is specified,
> the member can in turn grant membership in the role to others, and
> revoke membership in the role as well. Without the admin option,
> ordinary users cannot do that. A role is not considered to hold WITH
> ADMIN OPTION on itself, but it may grant or revoke membership in
> itself from a database session where the session user matches the
> role."

> Is there some use case for the behavior described in that last
> sentence?

Good question.  You might try figuring out when that text was added
and then see if there's relevant discussion in the archives.

Just looking at it now, without having done any historical research,
I wonder why it is that we don't attach significance to WITH ADMIN
OPTION being granted to the role itself.  It seems like the second
part of that sentence is effectively saying that a role DOES have
admin option on itself, contradicting the first part.

regards, tom lane




Re: role self-revocation

2022-03-07 Thread David G. Johnston
On Mon, Mar 7, 2022 at 8:37 AM Robert Haas  wrote:

> A role is not considered to hold WITH
> ADMIN OPTION on itself, but it may grant or revoke membership in
> itself from a database session where the session user matches the
> role."
>
> Is there some use case for the behavior described in that last
> sentence?


I can imagine, in particular combined with CREATEROLE, that this allows for
any user to delegate their personal permissions to a separate newly created
user.  Like an assistant.  I'm not all that sure whether CREATEROLE is
presently safe enough to give to a normal user in order to make this use
case work but it seems reasonable.

I would be concerned about changing the behavior at this point.  But I
would be in favor of at least removing the hard-coded exception and linking
it to a role attribute.  That attribute can default to "SELFADMIN" to match
the existing behavior but then "NOSELFADMIN" would exist to disable that
behavior on the per-role basis.  Still tied to session_user as opposed to
current_user.

David J.

P.S.

create role selfadmin admin selfadmin; -- ERROR: role "selfadmin" is a
member of role "selfadmin"

create role selfadmin;
grant selfadmin to selfadmin with admin option; -- ERROR: role "selfadmin"
is a member of role "selfadmin"

The error message seems odd.  I tried this because instead of a "SELFADMIN"
attribute adding a role to itself WITH ADMIN OPTION could be defined to
have the same effect.  You cannot change WITH ADMIN OPTION independently of
the adding of the role to the group.


Re: role self-revocation

2022-03-07 Thread Robert Haas
On Sun, Mar 6, 2022 at 2:09 PM David G. Johnston
 wrote:
> So, do we really want to treat every single login role as a potential group 
> by keeping the session_user exception?

I think that we DO want to continue to treat login roles as
potentially grantable privileges. That feels fundamentally useful to
me. The superuser is essentially granted the privileges of all users
on the system, and has all the rights they have, including the right
to drop tables owned by those users as if they were the owner of those
tables. If it's useful for the superuser to implicitly have the rights
of all users on the system, why should it not be useful for some
non-superuser to implicitly have the rights of some other users on the
system? I think it pretty clearly is. If one of my colleagues leaves
the company, the DBA can say "grant jdoe to rhaas" and let me mess
around with this stuff. Or, the DBA can grant me the privileges of all
my direct reports even when they're not leaving so that I can sort out
anything I need to do without superuser involvement. That all seems
cool and OK to me.

Now I think it is fair to say that we could have chosen a different
design, and MAYBE that would have been better. Nobody forced us to
conflate users and groups into a unified thing called roles, and I
think there's pretty good evidence that it's confusing and
counterintuitive in some ways. There's also no intrinsic reason why
the superuser has to be able to directly exercise the privileges of
every role rather than, say, having a way to become any given role.
But at this point, those design decisions are pretty well baked into
the system design, and I don't really think it's likely that we want
to change them. To put that another way, just because you don't like
the idea of granting one login role to another login role, that
doesn't mean that the feature doesn't exist, and as long as that
feature does exist, trying to make it work better or differently is
fair game.

But I think that's separate from your other question about whether we
should remove the session user exception. That looks tempting to me at
first glance, because we have exchanged several hundred, and it really
feels more like several million, emails on this list about how much of
a problem it is that an unprivileged user can just log in and run a
REVOKE. It breaks the idea that the people WITH ADMIN OPTION on a role
are the ones who control membership in that role. Joshua Brindle's
note upthread about the interaction of this with pg_hba.conf is
another example of that, and I think there are more. Any idea that a
role is a general-purpose way of designating a group of users for some
security critical purpose is threatened if people can make changes to
the membership of that group without being specifically authorized to
do so.

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




Re: role self-revocation

2022-03-07 Thread Robert Haas
On Sun, Mar 6, 2022 at 11:53 AM Tom Lane  wrote:
> Really?
>
> regression=# grant admin to joe;
> GRANT ROLE
> regression=# grant admin to sally;
> GRANT ROLE
> regression=# \c - joe
> You are now connected to database "regression" as user "joe".
> regression=> revoke admin from sally;
> ERROR:  must have admin option on role "admin"
> regression=> set role admin;
> SET
> regression=> revoke admin from sally;
> ERROR:  must have admin option on role "admin"

Oops. I stand corrected.

> I think there is an issue here around exactly what the admin option
> means, but if it doesn't grant you the ability to remove grants
> made by other people, it's pretty hard to see what it's for.

Hmm. I think the real issue is what David Johnson calls the session
user exception. I hadn't quite understood how that played into this.
According to the documentation: "If WITH ADMIN OPTION is specified,
the member can in turn grant membership in the role to others, and
revoke membership in the role as well. Without the admin option,
ordinary users cannot do that. A role is not considered to hold WITH
ADMIN OPTION on itself, but it may grant or revoke membership in
itself from a database session where the session user matches the
role."

Is there some use case for the behavior described in that last
sentence? If that exception is the only case in which an unprivileged
user can revoke a grant made by someone else, then getting rid of it
seems pretty appealing from where I sit. I can't speak to the
standards compliance end of things, but it doesn't intrinsically seem
bothersome that having "WITH ADMIN OPTION" on a role lets you control
who has membership in said role. And certainly it's not bothersome
that the superuser can change whatever they want. The problem here is
just that a user with NO special privileges on any role, including
their own, can make changes that more privileged users might not like.

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




Re: role self-revocation

2022-03-07 Thread Robert Haas
On Sun, Mar 6, 2022 at 11:34 AM Tom Lane  wrote:
> I was thinking the former ... however, after a bit of experimentation
> I see that we accept "grant foo to bar granted by baz" a VERY long
> way back, but the "granted by" option for object privileges is
> (a) pretty new and (b) apparently restrictively implemented:
>
> regression=# grant delete on alices_table to bob granted by alice;
> ERROR:  grantor must be current user
>
> That's ... surprising.  I guess whoever put that in was only
> interested in pro-forma SQL syntax compliance and not in making
> a usable feature.

It appears so: 
https://www.postgresql.org/message-id/2073b6a9-7f79-5a00-5f26-cd19589a52c7%402ndquadrant.com

It doesn't seem like that would be hard to fix. Maybe we should just do that.

> So if we decide to extend this change into object privileges
> it would be advisable to use SET ROLE, else we'd be giving up
> an awful lot of backwards compatibility in dump scripts.
> But if we're only talking about role grants then I think
> GRANTED BY would work fine.

OK.

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




Re: role self-revocation

2022-03-06 Thread David G. Johnston
On Sun, Mar 6, 2022 at 8:19 AM Robert Haas  wrote:

> The choice of names in my example wasn't accidental. If the granted
> role is a login role, then the superuser's intention was to vest the
> privileges of that role in some other role, and it is surely not right
> for that role to be able to decide that it doesn't want it's
> privileges to be so granted. That's why I chose the name "peon".


 >> rhaas [as peon] => revoke peon from boss; -- i don't like being bossed
around!

Well, the peon is not getting bossed around, the boss is getting peoned
around and the peon has decided that they like boss too much and don't need
to do that anymore.

When you grant a group "to" a role you place the role under the group - and
inheritance flows downward.

In the original thread Stephen wrote:

"This is because we allow 'self administration' of roles, meaning that
they can decide what other roles they are a member of.:

The example, which you moved here, then attempts to demonstrate this "fact"
but gets it wrong.  Boss became a member of peon so if you want to
demonstrate self-administration of a role's membership in a different group
you have to login as boss, not peon.  Doing that, and then revoking peon
from boss, yields "ERROR: must have admin option on role "peon"".

So no, without "WITH ADMIN OPTION" a role cannot decide what other roles
they are a member of.

I don't necessarily have an issue changing self-administration but if the
motivating concern is that all these new pg_* roles we are creating are
something a normal user can opt-out of/revoke that simply isn't the case
today, unless they are added to the pg_* role WITH ADMIN OPTION.

That all said, permissions SHOULD BE strictly additive.  If boss doesn't
want to be a member of pg_read_all_files allowing them to revoke themself
from that role seems like it should be acceptable.  If there is fear in
allowing someone to revoke (not add) themselves as a member of a different
role that suggests we have a design issue in another feature of the
system.  Today, they neither grant nor revoke, and the self-revocation
doesn't seem that important to add.

David J.


Re: role self-revocation

2022-03-06 Thread David G. Johnston
On Sun, Mar 6, 2022 at 9:53 AM Tom Lane  wrote:

> Robert Haas  writes:
> > ... Suppose the superuser grants "admin" to both "joe" and "sally".
> > Now "joe" can SET ROLE to "admin" and revoke it from "sally", and the
> > superuser has no tool to prevent this.
>
> Really?
>
> regression=# grant admin to joe;
> GRANT ROLE
> regression=# grant admin to sally;
> GRANT ROLE
> regression=# \c - joe
> You are now connected to database "regression" as user "joe".
> regression=> revoke admin from sally;
> ERROR:  must have admin option on role "admin"
> regression=> set role admin;
> SET
> regression=> revoke admin from sally;
> ERROR:  must have admin option on role "admin"
>
> I think there is an issue here around exactly what the admin option
> means, but if it doesn't grant you the ability to remove grants
> made by other people, it's pretty hard to see what it's for.
>
>
Precisely.

The current system, with the session_user exception, basically guides a
superuser to define two kinds of roles.

Groups: No login, permission grants
Users: Login, inherits permissions from groups, can manage group membership
if given WITH ADMIN OPTION.

The original example using only users is not all that compelling to me.
IMO, DBAs should not be setting up their system that way.

Two questions remain:

1. Are we willing to get rid of the session_user exception?

2. Do we want to track who the grantor is for role membership grants and
institute a requirement that non-superusers can only revoke the grants that
they personally made?

I'm personally in favor of getting rid of the session_user exception, which
nicely prevents the problem at the beginning of this thread and further
encourages the DBA to define groups and roles with a greater
separation-of-concerns design.  WITH ADMIN OPTION is sufficient.

I think tracking grantor information for role membership would allow for
greater auditing capabilities and a better degree of control in the
permissions system.

In short, I am in favor of both options.  The grantor tracking seems to be
headed for acceptance.

So, do we really want to treat every single login role as a potential group
by keeping the session_user exception?

David J.


Re: role self-revocation

2022-03-06 Thread Tom Lane
Robert Haas  writes:
> ... Suppose the superuser grants "admin" to both "joe" and "sally".
> Now "joe" can SET ROLE to "admin" and revoke it from "sally", and the
> superuser has no tool to prevent this.

Really?

regression=# grant admin to joe;
GRANT ROLE
regression=# grant admin to sally;
GRANT ROLE
regression=# \c - joe
You are now connected to database "regression" as user "joe".
regression=> revoke admin from sally;
ERROR:  must have admin option on role "admin"
regression=> set role admin;
SET
regression=> revoke admin from sally;
ERROR:  must have admin option on role "admin"

I think there is an issue here around exactly what the admin option
means, but if it doesn't grant you the ability to remove grants
made by other people, it's pretty hard to see what it's for.

regards, tom lane




Re: role self-revocation

2022-03-06 Thread Joshua Brindle
On Sun, Mar 6, 2022 at 10:19 AM Robert Haas  wrote:
>
> On Fri, Mar 4, 2022 at 5:20 PM David G. Johnston
>  wrote:
> > I think I disagree.  Or, at least, the superuser has full control of 
> > dictating how role membership is modified and that seems sufficient.
>
> The point is that the superuser DOES NOT have full control. The
> superuser cannot prevent relatively low-privileged users from undoing
> things that the superuser did intentionally and doesn't want reversed.
>
> The choice of names in my example wasn't accidental. If the granted
> role is a login role, then the superuser's intention was to vest the
> privileges of that role in some other role, and it is surely not right
> for that role to be able to decide that it doesn't want it's
> privileges to be so granted. That's why I chose the name "peon". In
> your example, where you chose the name "admin", the situation is less
> clear. If we imagine the granted role as a container for a bundle of
> privileges, giving it the ability to administer itself feels more
> reasonable. However, I am very much unconvinced that it's correct even
> there. Suppose the superuser grants "admin" to both "joe" and "sally".
> Now "joe" can SET ROLE to "admin" and revoke it from "sally", and the
> superuser has no tool to prevent this.
>
> Now you can imagine a situation where the superuser is totally OK with
> either "joe" or "sally" having the ability to lock the other one out,
> but I don't think it's right to say that this will be true in all
> cases.
>

Another example here is usage of groups in pg_hba.conf, if the admin
has a group of users with stronger authentication requirements: e.g.,

hostssl all +certonlyusers all cert map=certmap clientcert=1

and one can remove their membership, they can change their
authentication requirements.




Re: role self-revocation

2022-03-06 Thread Tom Lane
Robert Haas  writes:
> On Fri, Mar 4, 2022 at 4:34 PM Tom Lane  wrote:
>> Agreed, this is not something to move on quickly.  We might want
>> to think about adjusting pg_dump to use explicit GRANTED BY
>> options in GRANT/REVOKE a release or two before making incompatible
>> changes.

> Uggh. I really want to make some meaningful progress here before the
> heat death of the universe, and I'm not sure that this manner of
> proceeding is really going in that direction. That said, I do entirely
> see your point. Are you thinking we'd actually add a GRANTED BY clause
> to GRANT/REVOKE, vs. just wrapping it in SET ROLE incantations of some
> sort?

I was thinking the former ... however, after a bit of experimentation
I see that we accept "grant foo to bar granted by baz" a VERY long
way back, but the "granted by" option for object privileges is
(a) pretty new and (b) apparently restrictively implemented:

regression=# grant delete on alices_table to bob granted by alice;
ERROR:  grantor must be current user

That's ... surprising.  I guess whoever put that in was only
interested in pro-forma SQL syntax compliance and not in making
a usable feature.

So if we decide to extend this change into object privileges
it would be advisable to use SET ROLE, else we'd be giving up
an awful lot of backwards compatibility in dump scripts.
But if we're only talking about role grants then I think
GRANTED BY would work fine.

regards, tom lane




Re: role self-revocation

2022-03-06 Thread Robert Haas
On Fri, Mar 4, 2022 at 4:34 PM Tom Lane  wrote:
> If we are not tracking the grantors of role authorizations,
> then we are doing it wrong and we ought to fix that.

Hmm, so maybe that's the place to start. We are tracking it in the
sense that we record an OID in the catalog, but nothing that happens
after that makes a lot of sense.

> > 3. What happens if a user is dropped after being recorded as a
> > grantor?
>
> Should work the same as it does now for ordinary ACLs, ie, you
> gotta drop the grant first.

OK, that makes sense to me.

> Changing it could have some bad compatibility consequences though.
> In particular, I believe it would break existing pg_dump files,
> in that after restore all privileges would be attributed to the
> restoring superuser, and there'd be no very easy way to clean that
> up.

I kind of wonder whether we ought to attribute all privileges granted
by any superuser to the bootstrap superuser. That doesn't seem to have
any meaningful downside, and it could avoid a lot of annoying
dependencies that serve no real purpose.

> Agreed, this is not something to move on quickly.  We might want
> to think about adjusting pg_dump to use explicit GRANTED BY
> options in GRANT/REVOKE a release or two before making incompatible
> changes.

Uggh. I really want to make some meaningful progress here before the
heat death of the universe, and I'm not sure that this manner of
proceeding is really going in that direction. That said, I do entirely
see your point. Are you thinking we'd actually add a GRANTED BY clause
to GRANT/REVOKE, vs. just wrapping it in SET ROLE incantations of some
sort?

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




Re: role self-revocation

2022-03-06 Thread Robert Haas
On Fri, Mar 4, 2022 at 5:20 PM David G. Johnston
 wrote:
> I think I disagree.  Or, at least, the superuser has full control of 
> dictating how role membership is modified and that seems sufficient.

The point is that the superuser DOES NOT have full control. The
superuser cannot prevent relatively low-privileged users from undoing
things that the superuser did intentionally and doesn't want reversed.

The choice of names in my example wasn't accidental. If the granted
role is a login role, then the superuser's intention was to vest the
privileges of that role in some other role, and it is surely not right
for that role to be able to decide that it doesn't want it's
privileges to be so granted. That's why I chose the name "peon". In
your example, where you chose the name "admin", the situation is less
clear. If we imagine the granted role as a container for a bundle of
privileges, giving it the ability to administer itself feels more
reasonable. However, I am very much unconvinced that it's correct even
there. Suppose the superuser grants "admin" to both "joe" and "sally".
Now "joe" can SET ROLE to "admin" and revoke it from "sally", and the
superuser has no tool to prevent this.

Now you can imagine a situation where the superuser is totally OK with
either "joe" or "sally" having the ability to lock the other one out,
but I don't think it's right to say that this will be true in all
cases.

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




Re: role self-revocation

2022-03-04 Thread David G. Johnston
On Fri, Mar 4, 2022 at 1:50 PM Robert Haas  wrote:

> On Mon, Feb 28, 2022 at 2:09 PM Stephen Frost  wrote:
> > The ability of a role to revoke itself from some other role is just
> > something we need to accept as being a change that needs to be made, and
> > I do believe that such a change is supported by the standard, in that a
> > REVOKE will only work if you have the right to make it as the user who
> > performed the GRANT in the first place.
>
> First, a quick overview of the
> issue for those who have not followed the earlier threads in their
> grueling entirety:
>
> rhaas=# create user boss;
> CREATE ROLE
> rhaas=# create user peon;
> CREATE ROLE
> rhaas=# grant peon to boss;
> GRANT ROLE
> rhaas=# \c - peon
> You are now connected to database "rhaas" as user "peon".
> rhaas=> revoke peon from boss; -- i don't like being bossed around!
> REVOKE ROLE
>
>
The wording for this example is hurting my brain.
GRANT admin TO joe;
\c admin
REVOKE admin FROM joe;

> I argue (and Stephen seems to agree) that the peon shouldn't be able
> to undo the superuser's GRANT.


I think I disagree.  Or, at least, the superuser has full control of
dictating how role membership is modified and that seems sufficient.

The example above works because of:

"A role is not considered to hold WITH ADMIN OPTION on itself, but it may
grant or revoke membership in itself from a database session where the
session user matches the role."

If a superuser doesn't want "admin" to modify its own membership then they
can prevent anyone but a superuser from being able to have a session_user
of "admin".  If that happens then the only way a non-superuser can modify
group membership is by being added to said group WITH ADMIN OPTION.

Now, if two people and a superuser are all doing membership management on
the same group, and we want to add permission checks and multiple grants as
tools, instead of having them just communicate with each other, then by all
means let us do so.  In that case, in answer to questions 2 and 3, we
should indeed track which session_user made the grant and only allow the
same session_user or the superuser to revoke it (we'd want to stop
"ignoring" the GRANTED BY clause of REVOKE ROLE FROM so the superuser at
least could remove grants made via WITH ADMIN OPTION).

4. Should we apply this rule to other types of grants, rather than
> just to role membership? Why or why not? Consider this:
>


> The fact that the accountant may not be not in favor
> of the auditor seeing what the accountant is doing with the money is
> precisely the reason why we have auditors.

[...]

> However, when the superuser
> performs the GRANT as in the above example, the grantor is recorded as
> the table owner, not the superuser! So if we really want role
> membersip and other kinds of grants to behave in the same way, we have
> our work cut out for us here.
>

Yes, this particular choice seems unfortunate, but also not something that
I think it is necessarily mandatory for us to improve.  If the accountant
is the owner then yes they get to decide permissions.  In the presence of
an auditor role either you trust the accountant role to keep the
permissions in place or you define a superior authority to both the auditor
and accountant to be the owner.  Or let the superuser manage everything by
witholding login and WITH ADMIN OPTION privileges from the ownership role.


If we do extend role membership tracking I suppose the design question is
whether the new role grantor dependency tracking will have a superuser be
the recorded grantor instead of some owner.  Given that roles don't
presently have an owner concept, consistency with existing permissions in
this manner would be trickier.  Because of this, I would probably leave
role grantor tracking at the session_user level while database objects
continue to emanate from the object owner.  The global vs database
differences seem like a sufficient theoretical justification for the
difference in implementation.

David J.


Re: role self-revocation

2022-03-04 Thread Tom Lane
Robert Haas  writes:
> 1. What should be the exact rule for whether A can remove a grant made
> by B? Is it has_privs_of_role()? is_member_of_role()? Something else?

No strong opinion here, but I'd lean slightly to the more restrictive
option.

> 2. What happens if the same GRANT is enacted by multiple users? For
> example, suppose peon does "GRANT peon to boss" and then the superuser
> does the same thing afterwards, or vice versa? One design would be to
> try to track those as two separate grants, but I'm not sure if we want
> to add that much complexity, since that's not how we do it now and it
> would, for example, implicate the choice of PK on the pg_auth_members
> table.

As you note later, we *do* track such grants separately in ordinary
ACLs, and I believe this is clearly required by the SQL spec.
It says (for privileges on objects):

Each privilege is represented by a privilege descriptor.
A privilege descriptor contains:
— The identification of the object on which the privilege is granted.
— The  of the grantor of the privilege.
  ^^^
— The  of the grantee of the privilege.
— Identification of the action that the privilege allows.
— An indication of whether or not the privilege is grantable.
— An indication of whether or not the privilege has the WITH HIERARCHY 
OPTION specified.

Further down (4.42.3 in SQL:2021), the granting of roles is described,
and that says:

Each role authorization is described by a role authorization descriptor.
A role authorization descriptor includes:
— The role name of the role.
— The authorization identifier of the grantor.
  
— The authorization identifier of the grantee.
— An indication of whether or not the role authorization is grantable.

If we are not tracking the grantors of role authorizations,
then we are doing it wrong and we ought to fix that.

> 3. What happens if a user is dropped after being recorded as a
> grantor?

Should work the same as it does now for ordinary ACLs, ie, you
gotta drop the grant first.

> 4. Should we apply this rule to other types of grants, rather than
> just to role membership?

I am not sure about the reasoning behind the existing rule that
superuser-granted privileges are recorded as being granted by the
object owner.  It does feel more like a wart than something we want.
It might have been a hack to deal with the lack of GRANTED BY
options in GRANT/REVOKE back in the day.

Changing it could have some bad compatibility consequences though.
In particular, I believe it would break existing pg_dump files,
in that after restore all privileges would be attributed to the
restoring superuser, and there'd be no very easy way to clean that
up.

> Please note that it is not really my intention to try to shove
> anything into v15 here.

Agreed, this is not something to move on quickly.  We might want
to think about adjusting pg_dump to use explicit GRANTED BY
options in GRANT/REVOKE a release or two before making incompatible
changes.

regards, tom lane