Thread: Bug in handling default privileges inside extension update scripts

Bug in handling default privileges inside extension update scripts

From
Mats Kindahl
Date:
Hi everybody!

Not sure if I should send this to pgsql-hackers as well, but starting here to not send it wider than necessary.

TL;DR; When assigning default privileges to schemas used by an extension, privileges dumped for configuration tables before and after an update of the extension can be different.

Longer explanation:

I think there is a bug in the handling of "initprivs" for extensions
that drop and create tables during an update. To reproduce this
behavior, it is necessary to have an extension that grants some
privileges to configuration tables created by the extension. (I have a
simple version of an extension in
https://github.com/mkindahl/pg_examples that can be used to reproduce
the problem.)

The problem occurs when the user grants privileges on the
configuration tables for the extension to a new role and want to set
default privileges for the role on both the current and future
configuration tables. As a simple concrete example, suppose that the
user want to add a dedicated role (say "reader") for backing up the
database using "pg_dump", with all configuration tables of the
extension(s) as well. I would argue that a user can expect the
following:

* To be able to read the configuration tables, "reader" need to have
  SELECT privileges.

* Since the new role is added by the user and not by the extension,
  the grants have to be dumped as well. Otherwise, a restore of the
  data will have wrong privileges.

* Since new configuration tables could be added by an update of the
  extension, it is necessary to make sure that these privileges are
  added to new tables when updating. Typically, this means changing
  the default privileges on the schema for the configuration files.

* After an update, the new role with privileges should still be dumped
  both for old tables as well as for new tables. Note that some "old"
  tables could have changed definition in the update (typically by
  creating the new version and copying data from the old table), but
  these should still keep the same privileges and also be dumped
  after the update.

To reproduce the problem, it is necessary to create an extension
and create a new dedicated role "reader" that is expected to read
the configuration schema. We put the configuration tables in a
dedicated schema to easily find them and be able to manipulate them as a group.

    $ psql
    Expanded display is used automatically.
    Null display is "[NULL]".
    psql (12.6 (Ubuntu 12.6-0ubuntu0.20.04.1))
    Type "help" for help.

    mats=# CREATE SCHEMA IF NOT EXISTS simple_catalog;
    CREATE SCHEMA
    mats=# CREATE EXTENSION simple WITH VERSION '1.0' SCHEMA simple_catalog;
    CREATE EXTENSION

We add a new role that should be able to read all the configuration
tables of the extension.

    mats=# CREATE ROLE reader;
    CREATE ROLE

Since these needs to be possible to dump, we need to grant SELECT
privileges on the tables in the schema.

    mats=# GRANT SELECT ON ALL TABLES IN SCHEMA simple_catalog TO reader;
    GRANT

Since an update can create new tables, and we want the "reader" role
to still be able to read those tables after an update, we grant
default privileges on the schema to "reader".

    mats=# ALTER DEFAULT PRIVILEGES IN SCHEMA simple_catalog GRANT SELECT ON TABLES TO reader;
    ALTER DEFAULT PRIVILEGES

Note that at this point, we have these ACLs and initprivs.

    mats=# SELECT nspname, relname, relacl, initprivs
    mats-# FROM pg_class cl JOIN pg_namespace ns ON ns.oid = relnamespace LEFT JOIN pg_init_privs ON objoid = cl.oid
    mats-# WHERE relname = 'objects';
nspname     | relname |                  relacl                   |          initprivs
    ----------------+---------+-------------------------------------------+-----------------------------
     simple_catalog | objects | {mats=arwdDxt/mats,=r/mats,reader=r/mats} | {mats=arwdDxt/mats,=r/mats}
    (1 row)

We now add some configuration data to the configuration schema of the
extension so that we can see that it is dumped correctly.

    mats=# CREATE TABLE update_foo (a int);
    CREATE TABLE
    mats=# CALL add_note('update_foo', 'Just a note');
    CALL
    mats=# SELECT * FROM simple_catalog.objects;
       objoid   |   objnote  
    ------------+-------------
     update_foo | Just a note
    (1 row)

Running "pg_dump" and checking for grants for "reader". We expect it
to dump the grants here since the user created those and not the
extension. And this does indeed work as expected: both grants and
default privileges are dumped.

    $ pg_dump | grep reader
    GRANT SELECT ON TABLE simple_catalog.objects TO reader;
    ALTER DEFAULT PRIVILEGES FOR ROLE mats IN SCHEMA simple_catalog GRANT SELECT ON TABLES  TO reader;

Updating the extension adds the default privileges to "initprivs",
which is unexpected.

    mats=# ALTER EXTENSION simple UPDATE;
    ALTER EXTENSION
    mats=# SELECT nspname, relname, relacl, initprivs
    mats-# FROM pg_class cl JOIN pg_namespace ns ON ns.oid = relnamespace LEFT JOIN pg_init_privs ON objoid = cl.oid
    mats-# WHERE relname = 'objects';
nspname     | relname |                  relacl                   |                initprivs                
    ----------------+---------+-------------------------------------------+-------------------------------------------
     simple_catalog | objects | {mats=arwdDxt/mats,reader=r/mats,=r/mats} | {mats=arwdDxt/mats,reader=r/mats,=r/mats}
    (1 row)

As a result, this means that when we dump the database, it will not
dump grants for "reader" even though those were given by the user and
not the extension and, IMHO, after the update it should not behave
differently compared to before the update.

    $ pg_dump | grep reader
    ALTER DEFAULT PRIVILEGES FOR ROLE mats IN SCHEMA simple_catalog GRANT SELECT ON TABLES TO reader;

It is possible to solve this in the extension by saving away all
privileges and initprivs for the schema and restoring them afterwards,
which is quite cumbersome.

A better approach (IMHO) would be to make sure that new tables do
not use the default privileges to change the initprivs when doing the
extension update. This would allow extensions to add grants as they
please and it will still behave as expected (these will not be dumped).

Best wishes,
Mats Kindahl
Senior Software Engineer, Timescale

Re: Bug in handling default privileges inside extension update scripts

From
Stephen Frost
Date:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> * To be able to read the configuration tables, "reader" need to have
>   SELECT privileges.
>
> * Since the new role is added by the user and not by the extension,
>   the grants have to be dumped as well. Otherwise, a restore of the
>   data will have wrong privileges.
>
> * Since new configuration tables could be added by an update of the
>   extension, it is necessary to make sure that these privileges are
>   added to new tables when updating. Typically, this means changing
>   the default privileges on the schema for the configuration files.

If the extension is updated, I think it's entirely reasonable to expect
an admin to have to go in and update the relevant permissions on any new
tables that have come into existance and, as I've said elsewhere, I
don't think that schema-level default privs should be applied to tables
created by extensions.  Sadly, no one else seems to have an opinion
regarding that and so there hasn't been a change in that, yet, but
that's the source of the issue imv.

If you want to comment on that, I'd suggest doing so on that thread:

https://www.postgresql.org/message-id/20200205034454.GU3195@tamriel.snowman.net

Thanks,

Stephen

Attachment

Re: Bug in handling default privileges inside extension update scripts

From
Mats Kindahl
Date:

On Thu, Apr 22, 2021 at 5:15 PM Stephen Frost <sfrost@snowman.net> wrote:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> * To be able to read the configuration tables, "reader" need to have
>   SELECT privileges.
>
> * Since the new role is added by the user and not by the extension,
>   the grants have to be dumped as well. Otherwise, a restore of the
>   data will have wrong privileges.
>
> * Since new configuration tables could be added by an update of the
>   extension, it is necessary to make sure that these privileges are
>   added to new tables when updating. Typically, this means changing
>   the default privileges on the schema for the configuration files.

If the extension is updated, I think it's entirely reasonable to expect
an admin to have to go in and update the relevant permissions on any new
tables that have come into existance and, as I've said elsewhere, I
don't think that schema-level default privs should be applied to tables
created by extensions.  Sadly, no one else seems to have an opinion
regarding that and so there hasn't been a change in that, yet, but
that's the source of the issue imv.

That is a different way to solve it, but I think that is a little unintuitive. I am actually proposing to still assign default privileges, but not add them to initprivs, to make sure that they are treated the same way before and after an update.


If you want to comment on that, I'd suggest doing so on that thread:

https://www.postgresql.org/message-id/20200205034454.GU3195@tamriel.snowman.net


Will do. Thanks for the pointer.

Best wishes,
Mats Kindahl
Thanks,

Stephen

Re: Bug in handling default privileges inside extension update scripts

From
Stephen Frost
Date:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> On Thu, Apr 22, 2021 at 5:15 PM Stephen Frost <sfrost@snowman.net> wrote:
> > * Mats Kindahl (mats@timescale.com) wrote:
> > > * To be able to read the configuration tables, "reader" need to have
> > >   SELECT privileges.
> > >
> > > * Since the new role is added by the user and not by the extension,
> > >   the grants have to be dumped as well. Otherwise, a restore of the
> > >   data will have wrong privileges.
> > >
> > > * Since new configuration tables could be added by an update of the
> > >   extension, it is necessary to make sure that these privileges are
> > >   added to new tables when updating. Typically, this means changing
> > >   the default privileges on the schema for the configuration files.
> >
> > If the extension is updated, I think it's entirely reasonable to expect
> > an admin to have to go in and update the relevant permissions on any new
> > tables that have come into existance and, as I've said elsewhere, I
> > don't think that schema-level default privs should be applied to tables
> > created by extensions.  Sadly, no one else seems to have an opinion
> > regarding that and so there hasn't been a change in that, yet, but
> > that's the source of the issue imv.
>
> That is a different way to solve it, but I think that is a little
> unintuitive. I am actually proposing to still assign default privileges,
> but not add them to initprivs, to make sure that they are treated the same
> way before and after an update.

Yes, I understood your suggestion, but I did, and still do, disagree
with that approach- how is an admin supposed to correctly guess what
permissions would be appropriate for new tables being added during an
upgrade of an extension?  Not to mention that extensions routinely get
added to existing schemas and I don't think it's at all obvious to
users that tables, functions, etc, added by an extension into a schema
should get the default privileges for that schema (and that could even
lead to security issues, I suspect...), not to mention that you have to
wonder if the privileges installed by the extension should be applied
*first*, and default privs after, or if the default privileges should
be first and the extension's privileges after.  As it's currently the
latter, it's rather complicated as the extension has no idea what to
expect the privileges on the object to be and so how can it sensibly set
privileges on it..?

More and more it looks clear to me that this is really just broken and
we need to stop applying default privs to objects created by extensions.

Thanks,

Stephen

Attachment

Re: Bug in handling default privileges inside extension update scripts

From
Mats Kindahl
Date:
On Mon, Apr 26, 2021 at 7:29 PM Stephen Frost <sfrost@snowman.net> wrote:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> On Thu, Apr 22, 2021 at 5:15 PM Stephen Frost <sfrost@snowman.net> wrote:
> > * Mats Kindahl (mats@timescale.com) wrote:
> > > * To be able to read the configuration tables, "reader" need to have
> > >   SELECT privileges.
> > >
> > > * Since the new role is added by the user and not by the extension,
> > >   the grants have to be dumped as well. Otherwise, a restore of the
> > >   data will have wrong privileges.
> > >
> > > * Since new configuration tables could be added by an update of the
> > >   extension, it is necessary to make sure that these privileges are
> > >   added to new tables when updating. Typically, this means changing
> > >   the default privileges on the schema for the configuration files.
> >
> > If the extension is updated, I think it's entirely reasonable to expect
> > an admin to have to go in and update the relevant permissions on any new
> > tables that have come into existance and, as I've said elsewhere, I
> > don't think that schema-level default privs should be applied to tables
> > created by extensions.  Sadly, no one else seems to have an opinion
> > regarding that and so there hasn't been a change in that, yet, but
> > that's the source of the issue imv.
>
> That is a different way to solve it, but I think that is a little
> unintuitive. I am actually proposing to still assign default privileges,
> but not add them to initprivs, to make sure that they are treated the same
> way before and after an update.

Before delving into the discussion below, my main issue originally is that the default privileges are used to set the initprivs for objects created by the extension, causing them to not be dumped after an update of the extension. From the thread that you mentioned above, it seems like you agree that this should indeed not be the case for the reasons I outlined. Did I understand it correctly? If so, I can create a patch for that part at least.


Yes, I understood your suggestion, but I did, and still do, disagree
with that approach- how is an admin supposed to correctly guess what
permissions would be appropriate for new tables being added during an
upgrade of an extension?

I am not really sure in what situation an admin will not be able to decide on the grants for extension objects (beyond what the extension decides are required).

The example I gave is because a non-superuser should be able to back up the tables and I think that the statements are quite clear in what they mean: assigning grants to tables directly is for the purpose of the currently existing objects, and default privileges are for future objects.

In the example given, the reason adding additional grants and/or default privileges is because the user needs to read the objects for backup purpose. It is quite clearly expressed using the statements in the example. To help me understand what problem you see, do you have an example where this is not as clear and where the water is muddier about what privileges to assign?
 
Not to mention that extensions routinely get
added to existing schemas and I don't think it's at all obvious to
users that tables, functions, etc, added by an extension into a schema
should get the default privileges for that schema (and that could even
lead to security issues, I suspect...),

Well... a user that wants to assign specific privileges to extension objects and keep them "under control" is probably going to use a dedicated schema for the extension(s) to separate user data from extension data (for example, in a hosted environment). Sure, users *can* use the public schema for all extensions (I think that is what you meant by "extensions routinely gets added to existing schemas"), but that will quickly be unmanageable for precisely the reason that it is hard to separate extension data from user data, so not sure if that is a good reason to not allow default privileges on extension objects. It feels like optimizing for the rare case.

I am not sure how this could cause a security issue though. My reasoning is this: escalations of privileges can happen for objects created by the extension if you have default privileges on the schema, so this would mean that some role can get access to new objects created by the extension, but this was the purpose of assigning default privileges on the schema in the first place so it cannot be unexpected.

Do you have some ideas or suspicions for how unexpected escalations could occur?

not to mention that you have to
wonder if the privileges installed by the extension should be applied
*first*, and default privs after, or if the default privileges should
be first and the extension's privileges after.

Forgive my ignorance, but I am not sure how that makes a difference. Could you elaborate?

As it's currently the
latter, it's rather complicated as the extension has no idea what to
expect the privileges on the object to be and so how can it sensibly set
privileges on it..?

Again, forgive my ignorance, but isn't the expectation of the extension that it has superuser privileges to the database where it is being created?
 
Best wishes,
Mats


More and more it looks clear to me that this is really just broken and
we need to stop applying default privs to objects created by extensions.

Thanks,

Stephen

Re: Bug in handling default privileges inside extension update scripts

From
Stephen Frost
Date:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> On Mon, Apr 26, 2021 at 7:29 PM Stephen Frost <sfrost@snowman.net> wrote:
> > * Mats Kindahl (mats@timescale.com) wrote:
> > > On Thu, Apr 22, 2021 at 5:15 PM Stephen Frost <sfrost@snowman.net>
> > wrote:
> > > > * Mats Kindahl (mats@timescale.com) wrote:
> > > > > * To be able to read the configuration tables, "reader" need to have
> > > > >   SELECT privileges.
> > > > >
> > > > > * Since the new role is added by the user and not by the extension,
> > > > >   the grants have to be dumped as well. Otherwise, a restore of the
> > > > >   data will have wrong privileges.
> > > > >
> > > > > * Since new configuration tables could be added by an update of the
> > > > >   extension, it is necessary to make sure that these privileges are
> > > > >   added to new tables when updating. Typically, this means changing
> > > > >   the default privileges on the schema for the configuration files.
> > > >
> > > > If the extension is updated, I think it's entirely reasonable to expect
> > > > an admin to have to go in and update the relevant permissions on any
> > new
> > > > tables that have come into existance and, as I've said elsewhere, I
> > > > don't think that schema-level default privs should be applied to tables
> > > > created by extensions.  Sadly, no one else seems to have an opinion
> > > > regarding that and so there hasn't been a change in that, yet, but
> > > > that's the source of the issue imv.
> > >
> > > That is a different way to solve it, but I think that is a little
> > > unintuitive. I am actually proposing to still assign default privileges,
> > > but not add them to initprivs, to make sure that they are treated the
> > same
> > > way before and after an update.
>
> Before delving into the discussion below, my main issue originally is that
> the default privileges are used to set the initprivs for objects created by
> the extension, causing them to not be dumped after an update of the
> extension. From the thread that you mentioned above, it seems like you
> agree that this should indeed not be the case for the reasons I outlined.
> Did I understand it correctly? If so, I can create a patch for that part at
> least.

If default privileges aren't set for objects created by an extension, as
I feel should be the case, then there's no concern around them being set
in initprivs or impacting the dump/restore case.  I wouldn't agree with
a patch that applied default privileges but then excluded them from
initprivs, as I said before.

> > Yes, I understood your suggestion, but I did, and still do, disagree
> > with that approach- how is an admin supposed to correctly guess what
> > permissions would be appropriate for new tables being added during an
> > upgrade of an extension?
>
> I am not really sure in what situation an admin will not be able to decide
> on the grants for extension objects (beyond what the extension decides are
> required).

Consider this:

An admin reviews v1 of extension ABC which installs some tables and
functions and decides that all users should be allowed to modify those
tables and so they set DEFAULT PRIVILEGES on the schema for everyone to
be able to modify the installed tables.

The ABC extension is then updated to add a new table in a v2 which
should *not* be able to be modified by any user, and the extension
author doesn't GRANT any privileges for that table since they know that
the *default* for a table is that only the owning role can modify the
table.  When that extension is updated, however, the DEFAULT PRIVILEGES
will end up GRANT'ing everyone access to that table anyway.  That
doesn't strike me as at all sane.

> The example I gave is because a non-superuser should be able to back up the
> tables and I think that the statements are quite clear in what they mean:
> assigning grants to tables directly is for the purpose of the currently
> existing objects, and default privileges are for future objects.

Allowing a non-superuser to back up a database is actually something
that's been added to v14 in the form of the pg_read_all_data role.

When it comes to default privileges, there's no shortage of extensions
which modify the privileges as part of the script that is run- but they
can only do that sanely when they know what privileges the object will
have initially.  If we have DEFAULT PRIVILEGES going on, there's no way
for the extension to know what privileges the object has during the
initial or the upgrade script.

> In the example given, the reason adding additional grants and/or default
> privileges is because the user needs to read the objects for backup
> purpose. It is quite clearly expressed using the statements in the example.
> To help me understand what problem you see, do you have an example where
> this is not as clear and where the water is muddier about what privileges
> to assign?

Any DEFAULT PRIVILEGES that get assigned behind the back of the
extension when the object is created means that the extension isn't able
to properly set the privileges on the objects that the extension has
created and that can lead to cases like the extension having a private
table that users are able to modify anyway, which is not a good thing.

> > Not to mention that extensions routinely get
> > added to existing schemas and I don't think it's at all obvious to
> > users that tables, functions, etc, added by an extension into a schema
> > should get the default privileges for that schema (and that could even
> > lead to security issues, I suspect...),
>
> Well... a user that wants to assign specific privileges to extension
> objects and keep them "under control" is probably going to use a dedicated
> schema for the extension(s) to separate user data from extension data (for
> example, in a hosted environment). Sure, users *can* use the public schema
> for all extensions (I think that is what you meant by "extensions routinely
> gets added to existing schemas"), but that will quickly be unmanageable for
> precisely the reason that it is hard to separate extension data from user
> data, so not sure if that is a good reason to not allow default privileges
> on extension objects. It feels like optimizing for the rare case.

It's not an optimization, it's a matter of doing what makes sense and is
not going to be a surprise to extension authors and users, and I don't
buy that having DEFAULT PRIVILEGES applied to objects created by
extensions is sensible to either of those groups.

> I am not sure how this could cause a security issue though. My reasoning is
> this: escalations of privileges can happen for objects created by the
> extension if you have default privileges on the schema, so this would mean
> that some role can get access to new objects created by the extension, but
> this was the purpose of assigning default privileges on the schema in the
> first place so it cannot be unexpected.

> Do you have some ideas or suspicions for how unexpected escalations could
> occur?

I've outlined at least one way this could cause problems above.  I don't
agree that having DEFAULT PRIVILEGES assigned to objects created by
extensions is expected.  Indeed, I'm fairly confident that it's entirely
*unexpected* by extension authors, including for core extensions like
adminpack, that DEFAULT PRIVILEGES might interfere with the privileges
that it's attempting to explicitly assign (such as REVOKE'ing EXECUTE on
sensitive functions from PUBLIC).

At least, when I wrote those REVOKEs into that exact extension, I sure
wasn't imagining that DEFAULT PRIVILEGES might be assigned to the schema
where those functions were being created and which would end up
GRANT'ing access to those very sensitive functions.  Maybe you can argue
that the user installing that extension into such a schema intended it,
but as an extension author, I surely didn't and that's enough of a point
of surprise that I'm fairly well convinced that we shouldn't have
objects being created by extensions have DEFAULT PRIVILEGES applied.

> not to mention that you have to
> > wonder if the privileges installed by the extension should be applied
> > *first*, and default privs after, or if the default privileges should
> > be first and the extension's privileges after.
>
> Forgive my ignorance, but I am not sure how that makes a difference. Could
> you elaborate?

The order in which privileges are applied makes a difference in terms of
what the resulting privileges on the object end up being..

> > As it's currently the
> > latter, it's rather complicated as the extension has no idea what to
> > expect the privileges on the object to be and so how can it sensibly set
> > privileges on it..?
>
> Again, forgive my ignorance, but isn't the expectation of the extension
> that it has superuser privileges to the database where it is being created?

First, no, extensions can be installed by non-superusers in the first
place, and second, I don't see how that has much to do with the question
at hand..

Thanks,

Stephen

Attachment

Re: Bug in handling default privileges inside extension update scripts

From
Mats Kindahl
Date:
Hi Again Stephen,

On Wed, Apr 28, 2021 at 8:23 PM Stephen Frost <sfrost@snowman.net> wrote:
Greetings,

* Mats Kindahl (mats@timescale.com) wrote:
> On Mon, Apr 26, 2021 at 7:29 PM Stephen Frost <sfrost@snowman.net> wrote:
> > * Mats Kindahl (mats@timescale.com) wrote:
> > > On Thu, Apr 22, 2021 at 5:15 PM Stephen Frost <sfrost@snowman.net>
> > wrote:
> > > > * Mats Kindahl (mats@timescale.com) wrote:
> > > > > * To be able to read the configuration tables, "reader" need to have
> > > > >   SELECT privileges.
> > > > >
> > > > > * Since the new role is added by the user and not by the extension,
> > > > >   the grants have to be dumped as well. Otherwise, a restore of the
> > > > >   data will have wrong privileges.
> > > > >
> > > > > * Since new configuration tables could be added by an update of the
> > > > >   extension, it is necessary to make sure that these privileges are
> > > > >   added to new tables when updating. Typically, this means changing
> > > > >   the default privileges on the schema for the configuration files.
> > > >
> > > > If the extension is updated, I think it's entirely reasonable to expect
> > > > an admin to have to go in and update the relevant permissions on any
> > new
> > > > tables that have come into existance and, as I've said elsewhere, I
> > > > don't think that schema-level default privs should be applied to tables
> > > > created by extensions.  Sadly, no one else seems to have an opinion
> > > > regarding that and so there hasn't been a change in that, yet, but
> > > > that's the source of the issue imv.
> > >
> > > That is a different way to solve it, but I think that is a little
> > > unintuitive. I am actually proposing to still assign default privileges,
> > > but not add them to initprivs, to make sure that they are treated the
> > same
> > > way before and after an update.
>
> Before delving into the discussion below, my main issue originally is that
> the default privileges are used to set the initprivs for objects created by
> the extension, causing them to not be dumped after an update of the
> extension. From the thread that you mentioned above, it seems like you
> agree that this should indeed not be the case for the reasons I outlined.
> Did I understand it correctly? If so, I can create a patch for that part at
> least.

If default privileges aren't set for objects created by an extension, as
I feel should be the case, then there's no concern around them being set
in initprivs or impacting the dump/restore case.
 
Agree that if default privileges are not applied to extension objects, the problem goes away.
 
I wouldn't agree with
a patch that applied default privileges but then excluded them from
initprivs, as I said before.

This I do not follow. If the default privileges are added to initprivs, it means that any privileges assigned to new objects created when the extension is updated will not be present in a dump after the update, which is inconsistent because it behaves differently compared to a fresh install of the same extension with a newer version.

Scenario #1:
  1. Install extension v1 using a schema
  2. GRANT privileges on objects in schema
  3. ALTER DEFAULT PRIVILEGES for schema
  4. Update extension to v2
  5. pg_dump
Scenario #2:
  1. Install extension v2 using a schema
  2. GRANT privileges on objects in schema
  3. ALTER DEFAULT PRIVILEGES for schema
  4.  pg_dump
The output of the two dumps will differ, even if the statements inside the extensions for creating objects are the same.

Note that this part is only about initprivs, not about whether default privileges should apply to objects created in extensions (which they currently are).


> > Yes, I understood your suggestion, but I did, and still do, disagree
> > with that approach- how is an admin supposed to correctly guess what
> > permissions would be appropriate for new tables being added during an
> > upgrade of an extension?
>
> I am not really sure in what situation an admin will not be able to decide
> on the grants for extension objects (beyond what the extension decides are
> required).

Consider this:

An admin reviews v1 of extension ABC which installs some tables and
functions and decides that all users should be allowed to modify those
tables and so they set DEFAULT PRIVILEGES on the schema for everyone to
be able to modify the installed tables.

If I understand it correctly, the DBA installs the extension and then checks what tables are there (it is not clear if the DBA reviews the extension before installing it or after, but the most natural case is that the DBA checks the tables after installation). In that case, wouldn't the DBA use GRANT in that case? After all, DEFAULT PRIVILEGES are for *future* objects created in the schema, while GRANT is used to assign privileges to currently existing tables. From https://www.postgresql.org/docs/13/sql-alterdefaultprivileges.html:

ALTER DEFAULT PRIVILEGES allows you to set the privileges that will be applied to objects created in the future. (It does not affect privileges assigned to already-existing objects.)


The ABC extension is then updated to add a new table in a v2 which
should *not* be able to be modified by any user, and the extension
author doesn't GRANT any privileges for that table since they know that
the *default* for a table is that only the owning role can modify the
table.

But under the assumption above (that the DBA does not want future tables installed by the extension to get the privileges)...
 
When that extension is updated, however, the DEFAULT PRIVILEGES
will end up GRANT'ing everyone access to that table anyway.  That
doesn't strike me as at all sane.

... the DBA would not assign DEFAULT PRIVILEGES to the schema since that applies to future objects, but rather just use GRANT on the specific tables that she wants to add privileges for. In that case, the new table would not get any new grants during the update (because the default privileges are not set), which is what the DBA expected.

Am I misunderstanding something?

> The example I gave is because a non-superuser should be able to back up the
> tables and I think that the statements are quite clear in what they mean:
> assigning grants to tables directly is for the purpose of the currently
> existing objects, and default privileges are for future objects.

Allowing a non-superuser to back up a database is actually something
that's been added to v14 in the form of the pg_read_all_data role.

That is useful, but the same situation occurs if you want to ensure that all configuration tables can be written as part of, e.g., a pg_restore. In that case, these privileges would be dumped before an update, but not after, which is inconsistent in the same way as when only assigning select privileges, so unless I am mistaken, having a dedicated role helps with the backup, but not with the restore.


When it comes to default privileges, there's no shortage of extensions
which modify the privileges as part of the script that is run- but they
can only do that sanely when they know what privileges the object will
have initially.  If we have DEFAULT PRIVILEGES going on, there's no way
for the extension to know what privileges the object has during the
initial or the upgrade script.

> In the example given, the reason adding additional grants and/or default
> privileges is because the user needs to read the objects for backup
> purpose. It is quite clearly expressed using the statements in the example.
> To help me understand what problem you see, do you have an example where
> this is not as clear and where the water is muddier about what privileges
> to assign?

Any DEFAULT PRIVILEGES that get assigned behind the back of the
extension when the object is created means that the extension isn't able
to properly set the privileges on the objects that the extension has
created and that can lead to cases like the extension having a private
table that users are able to modify anyway, which is not a good thing.

> > Not to mention that extensions routinely get
> > added to existing schemas and I don't think it's at all obvious to
> > users that tables, functions, etc, added by an extension into a schema
> > should get the default privileges for that schema (and that could even
> > lead to security issues, I suspect...),
>
> Well... a user that wants to assign specific privileges to extension
> objects and keep them "under control" is probably going to use a dedicated
> schema for the extension(s) to separate user data from extension data (for
> example, in a hosted environment). Sure, users *can* use the public schema
> for all extensions (I think that is what you meant by "extensions routinely
> gets added to existing schemas"), but that will quickly be unmanageable for
> precisely the reason that it is hard to separate extension data from user
> data, so not sure if that is a good reason to not allow default privileges
> on extension objects. It feels like optimizing for the rare case.

It's not an optimization, it's a matter of doing what makes sense and is
not going to be a surprise to extension authors and users, and I don't
buy that having DEFAULT PRIVILEGES applied to objects created by
extensions is sensible to either of those groups.

> I am not sure how this could cause a security issue though. My reasoning is
> this: escalations of privileges can happen for objects created by the
> extension if you have default privileges on the schema, so this would mean
> that some role can get access to new objects created by the extension, but
> this was the purpose of assigning default privileges on the schema in the
> first place so it cannot be unexpected.

> Do you have some ideas or suspicions for how unexpected escalations could
> occur?

I've outlined at least one way this could cause problems above.  I don't
agree that having DEFAULT PRIVILEGES assigned to objects created by
extensions is expected.  Indeed, I'm fairly confident that it's entirely
*unexpected* by extension authors, including for core extensions like
adminpack, that DEFAULT PRIVILEGES might interfere with the privileges
that it's attempting to explicitly assign (such as REVOKE'ing EXECUTE on
sensitive functions from PUBLIC).

At least, when I wrote those REVOKEs into that exact extension, I sure
wasn't imagining that DEFAULT PRIVILEGES might be assigned to the schema
where those functions were being created and which would end up
GRANT'ing access to those very sensitive functions.  Maybe you can argue
that the user installing that extension into such a schema intended it,
but as an extension author, I surely didn't and that's enough of a point
of surprise that I'm fairly well convinced that we shouldn't have
objects being created by extensions have DEFAULT PRIVILEGES applied.

Ok. I see what you're aiming for.


> not to mention that you have to
> > wonder if the privileges installed by the extension should be applied
> > *first*, and default privs after, or if the default privileges should
> > be first and the extension's privileges after.
>
> Forgive my ignorance, but I am not sure how that makes a difference. Could
> you elaborate?

The order in which privileges are applied makes a difference in terms of
what the resulting privileges on the object end up being..

Ah, you mean like if there is a default privilege that is GRANT ALL and the extension does a REVOKE of some privileges? Yes, in that case, the end result would be different.


> > As it's currently the
> > latter, it's rather complicated as the extension has no idea what to
> > expect the privileges on the object to be and so how can it sensibly set
> > privileges on it..?
>
> Again, forgive my ignorance, but isn't the expectation of the extension
> that it has superuser privileges to the database where it is being created?

First, no, extensions can be installed by non-superusers in the first
place, and second, I don't see how that has much to do with the question
at hand.

My fault, I was thinking about this comment from https://www.postgresql.org/docs/13/sql-createextension.html (and the following discussion about trusted extensions):

Loading an extension ordinarily requires the same privileges that would be required to create its component objects. For many extensions this means superuser privileges are needed.

... but as you say, it notes that superuser privileges are not required.

Thanks,

Mats Kindahl

Thanks,

Stephen