createuser unexpectedly creates superuser with createdb and createrole

Started by Erik Wienholdover 2 years ago6 messagesgeneral
Jump to latest
#1Erik Wienhold
ewie@ewie.name

I recently created a superuser with createuser on 15.4 and was surprised that
the superuser also has the CREATEDB and CREATEROLE attribute (although redundant
for a superuser). The docs [1]https://www.postgresql.org/docs/15/app-createuser.html even say that --no-createdb and --no-createrole
are the defaults. Those options don't even have an effect when used along with
--superuser. I checked CREATE USER (which I normally use) and it does not
automatically set CREATEDB and CREATEROLE.

$ sudo -u postgres createuser --superuser alice
$ sudo -u postgres createuser --superuser --no-createdb --no-createrole bob
$ sudo -u postgres psql
postgres=# CREATE ROLE carol SUPERUSER;
postgres=# \du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
alice | Superuser, Create role, Create DB | {}
bob | Superuser, Create role, Create DB | {}
carol | Superuser | {}
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

The docs for createuser also state that "there is no effective difference
between creating users via this utility and via other methods for accessing
the server."

The problem I see here is that the behavior is unexpected. Why would superusers
need CREATEDB and CREATEROLE attributes in the first place? Usually when
removing the superuser attribute I may then set CREATEDB and/or CREATEROLE if
the role should still be allowed to perform those operations. For a superuser
that was created by createuser I may also have to remove CREATEDB and CREATEROLE
when removing the SUPERUSER attribute.

I found the commit [2]https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=8ae0d476a9d5667645c5200d8c6831b2fb7a9a36 for this feature but it's unfortunately lacking an
explanation and only includes code comment "Not much point in trying to restrict
a superuser".

My question: are the docs wrong or is it a createuser bug?

I think explicit is better than implicit and fixing createuser would also be in
line with changes such as removing the PUBLIC creation permission on the public
schema in v15 to promote securer designs. Also there's a change [3]https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=1c77873727dfd2e48ab2ece84d1fb1676e95f9a5 that now
explains the security implications of CREATEROLE.

[1]: https://www.postgresql.org/docs/15/app-createuser.html
[2]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=8ae0d476a9d5667645c5200d8c6831b2fb7a9a36
[3]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commitdiff;h=1c77873727dfd2e48ab2ece84d1fb1676e95f9a5

--
Erik

#2Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Erik Wienhold (#1)
Re: createuser unexpectedly creates superuser with createdb and createrole

On Wed, 2023-08-30 at 02:44 +0200, Erik Wienhold wrote:

I recently created a superuser with createuser on 15.4 and was surprised that
the superuser also has the CREATEDB and CREATEROLE attribute (although redundant
for a superuser).  The docs [1] even say that --no-createdb and --no-createrole
are the defaults.  Those options don't even have an effect when used along with
--superuser.  I checked CREATE USER (which I normally use) and it does not
automatically set CREATEDB and CREATEROLE.

        $ sudo -u postgres createuser --superuser alice
        $ sudo -u postgres createuser --superuser --no-createdb --no-createrole bob
        $ sudo -u postgres psql
        postgres=# CREATE ROLE carol SUPERUSER;
        postgres=# \du
                                           List of roles
         Role name |                         Attributes                         | Member of
        -----------+------------------------------------------------------------+-----------
         alice     | Superuser, Create role, Create DB                          | {}
         bob       | Superuser, Create role, Create DB                          | {}
         carol     | Superuser                                                  | {}
         postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

The docs for createuser also state that "there is no effective difference
between creating users via this utility and via other methods for accessing
the server."

The problem I see here is that the behavior is unexpected.

I am somewhat surprised too, but it has been like that since commit 8ae0d476a9 in 2005.

The code is pretty clear about that:

if (superuser == TRI_YES)
{
/* Not much point in trying to restrict a superuser */
createdb = TRI_YES;
createrole = TRI_YES;
}

I would say that changing that long standing behavior would cause more harm than benefit.
First, as the code says, it doesn't make a lot of difference. And who knows, perhaps
someone somewhere creates superusers, later changes them to NOSUPERUSER and expects
CREATEDB and CREATEROLE to be set after that.

If anything, we could add something to the documentation.

Yours,
Laurenz Albe

#3Erik Wienhold
ewie@ewie.name
In reply to: Laurenz Albe (#2)
Re: createuser unexpectedly creates superuser with createdb and createrole

On 30/08/2023 03:21 CEST Laurenz Albe <laurenz.albe@cybertec.at> wrote:

I am somewhat surprised too, but it has been like that since commit 8ae0d476a9
in 2005.

Yeah, unlikely to find out why after 18 years.

The code is pretty clear about that:

if (superuser == TRI_YES)
{
/* Not much point in trying to restrict a superuser */
createdb = TRI_YES;
createrole = TRI_YES;
}

I would say that changing that long standing behavior would cause more harm
than benefit.

Sure, but it sounds like a reasonable change for a future major release.

First, as the code says, it doesn't make a lot of difference. And who knows,
perhaps someone somewhere creates superusers, later changes them to NOSUPERUSER
and expects CREATEDB and CREATEROLE to be set after that.

Just realized that the bootstrap user has all attributes even though not needed
as a superuser. Maybe that's the reason for createuser's behavior. But why
only CREATEDB and CREATEROLE then?

If anything, we could add something to the documentation.

Anyway, I prepared a patch for the docs. But I'm not sure if the description
should still read "There is no effective difference between creating users via
this utility and via other methods for accessing the server."

--
Erik

Attachments:

0001-Document-privileges-createuser-grants-to-superusers.patchtext/x-patch; charset=UTF-8; name=0001-Document-privileges-createuser-grants-to-superusers.patchDownload+7-4
#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Erik Wienhold (#3)
Re: createuser unexpectedly creates superuser with createdb and createrole

Erik Wienhold <ewie@ewie.name> writes:

Anyway, I prepared a patch for the docs.

I think the last hunk of this is plenty sufficient, and the earlier
ones just add noise.

regards, tom lane

#5Erik Wienhold
ewie@ewie.name
In reply to: Tom Lane (#4)
Re: createuser unexpectedly creates superuser with createdb and createrole

On 04/09/2023 03:42 CEST Tom Lane <tgl@sss.pgh.pa.us> wrote:

I think the last hunk of this is plenty sufficient, and the earlier
ones just add noise.

Done.

--
Erik

Attachments:

v2-0001-Document-implied-privileges-of-createuser-superus.patchtext/x-patch; charset=UTF-8; name=v2-0001-Document-implied-privileges-of-createuser-superus.patchDownload+2-2
#6Laurenz Albe
laurenz.albe@cybertec.at
In reply to: Erik Wienhold (#5)
Re: createuser unexpectedly creates superuser with createdb and createrole

On Tue, 2023-09-05 at 00:03 +0200, Erik Wienhold wrote:

On 04/09/2023 03:42 CEST Tom Lane <tgl@sss.pgh.pa.us> wrote:

I think the last hunk of this is plenty sufficient, and the earlier
ones just add noise.

Done.

Looks good to me.

Yours,
Laurenz Albe