Обсуждение: Restoring default privileges on objects

Поиск
Список
Период
Сортировка

Restoring default privileges on objects

От
Stuart McGraw
Дата:
Hello,

The Postgresql docs on object privileges,
   https://www.postgresql.org/docs/14/ddl-priv.html
say this in regard to the output of the psql \dp command:

   | If the “Access privileges” column is empty for a given object, it
   | means the object has default privileges (that is, its privileges
   | entry in the relevant system catalog is null). [...] The first GRANT
   | or REVOKE on an object will instantiate the default privileges
   | (producing, for example, miriam=arwdDxt/miriam) and then modify them
   | per the specified request.

If I've done a GRANT or REVOKE on some of the tables, how do I restore
the default privileges so that the “Access privileges” appears empty
again?  I re-granted what I think are the default privileges but the
"Access privileges" column for that table contains "user1=arwdDxt/user1"
rather than being blank.  This is Postgresql-14.

Thanks for any suggestions!



Re: Restoring default privileges on objects

От
Erik Wienhold
Дата:
> On 29/08/2023 03:23 CEST Stuart McGraw <smcgraw@mtneva.com> wrote:
>
> If I've done a GRANT or REVOKE on some of the tables, how do I restore
> the default privileges so that the “Access privileges” appears empty
> again?  I re-granted what I think are the default privileges but the
> "Access privileges" column for that table contains "user1=arwdDxt/user1"
> rather than being blank.  This is Postgresql-14.

Yes, "user1=arwdDxt/user1" matches the default privileges if user1 is the table
owner.  Function acldefault('r', 'user1'::regrole) [1] gives you the default
privileges for tables.

You could set pg_class.relacl to NULL to restore the default privileges, but
messing with pg_catalog is at your own risk.  Besides that I don't know of any
way to restore the default privileges other than revoking all privileges before
granting whatever acldefault gives you.  Changing the table owner will then
also change the grantee and grantor in pg_class.relacl to the new owner.

[1] https://www.postgresql.org/docs/14/functions-info.html#FUNCTIONS-ACLITEM-FN-TABLE

--
Erik



Re: Restoring default privileges on objects

От
Tom Lane
Дата:
Erik Wienhold <ewie@ewie.name> writes:
> On 29/08/2023 03:23 CEST Stuart McGraw <smcgraw@mtneva.com> wrote:
>> If I've done a GRANT or REVOKE on some of the tables, how do I restore
>> the default privileges so that the “Access privileges” appears empty
>> again?  I re-granted what I think are the default privileges but the
>> "Access privileges" column for that table contains "user1=arwdDxt/user1"
>> rather than being blank.  This is Postgresql-14.

> Yes, "user1=arwdDxt/user1" matches the default privileges if user1 is the table
> owner.

Right.  There is no (supported) way to cause the ACL entry to go back
to null.  It starts life that way as an ancient hack to save a step
during object creation.  But the moment you do anything to the object's
privileges, the NULL is replaced by an explicit representation of the
default privileges, which is then modified per whatever command you
are giving.  After that the privileges will always be explicit.

There's been occasional discussion of changing this behavior, but
it'd take work and it'd likely add about as much surprise as it
removes.  People have been used to this quirk for a long time.

            regards, tom lane



Re: Restoring default privileges on objects

От
Stuart McGraw
Дата:
On 8/29/23 08:14, Tom Lane wrote:
> Erik Wienhold <ewie@ewie.name> writes:
>> On 29/08/2023 03:23 CEST Stuart McGraw <smcgraw@mtneva.com> wrote:
>>> If I've done a GRANT or REVOKE on some of the tables, how do I restore
>>> the default privileges so that the “Access privileges” appears empty
>>> again?  I re-granted what I think are the default privileges but the
>>> "Access privileges" column for that table contains "user1=arwdDxt/user1"
>>> rather than being blank.  This is Postgresql-14.
> 
>> Yes, "user1=arwdDxt/user1" matches the default privileges if user1 is the table
>> owner.
> 
> Right.  There is no (supported) way to cause the ACL entry to go back
> to null.  It starts life that way as an ancient hack to save a step
> during object creation.  But the moment you do anything to the object's
> privileges, the NULL is replaced by an explicit representation of the
> default privileges, which is then modified per whatever command you
> are giving.  After that the privileges will always be explicit.
> 
> There's been occasional discussion of changing this behavior, but
> it'd take work and it'd likely add about as much surprise as it
> removes.  People have been used to this quirk for a long time.

Thank you Erik and Tom for the explanations.  I guess it's a it-is-
what-it-is situation :-).  But while trying to figure it out myself
I found the following:

   test=# CREATE ROLE user1;
   test=# SET ROLE user1;
   test=> CREATE TABLE t1(x int);
   test=> \dp
                               Access privileges
    Schema | Name | Type  | Access privileges | Column privileges | Policies
   --------+------+-------+-------------------+-------------------+----------
    public | t1   | table |                   |                   |

   test=> SELECT FROM t1;
   (0 rows)

   test=> SET ROLE postgres;
   test=# REVOKE ALL ON t1 FROM user1;
   test=# SET ROLE user1;
   test=> \dp
    Schema | Name | Type  | Access privileges | Column privileges | Policies
   --------+------+-------+-------------------+-------------------+----------
    public | t1   | table |                   |                   |

   test=> SELECT FROM t1;
   ERROR:  permission denied for table t1

How does one distinguish between (blank)=(default privileges)
and (blank)=(no privileges)?

Shouldn't psql put *something* (like "(default)" or "-") in the
"Access privileges" column to indicate that?  Or conversely,
something (like "(none)"?) in the revoked case?

It doesn't seem like a good idea to use the same visual
representation for two nearly opposite conditions.  It confused
the heck out of me anyway... :-)




Re: Restoring default privileges on objects

От
Erik Wienhold
Дата:
> On 29/08/2023 18:43 CEST Stuart McGraw <smcg4191@mtneva.com> wrote:
>
> How does one distinguish between (blank)=(default privileges)
> and (blank)=(no privileges)?
>
> Shouldn't psql put *something* (like "(default)" or "-") in the
> "Access privileges" column to indicate that?  Or conversely,
> something (like "(none)"?) in the revoked case?
>
> It doesn't seem like a good idea to use the same visual
> representation for two nearly opposite conditions.  It confused
> the heck out of me anyway... :-)

Indeed, that's confusing.  Command \dp always prints null as empty string [1].
So \pset null '(null)' has no effect.

The docs don't mention that edge case [2] (the second to last paragraph):

    "If the “Access privileges” column is empty for a given object, it
     means the object has default privileges (that is, its privileges
     entry in the relevant system catalog is null)."

[1]
https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/bin/psql/describe.c;h=bac94a338cfbc497200f0cf960cbabce2dadaa33;hb=9b581c53418666205938311ef86047aa3c6b741f#l1149
[2] https://www.postgresql.org/docs/14/ddl-priv.html

--
Erik



Re: Restoring default privileges on objects

От
Tom Lane
Дата:
Erik Wienhold <ewie@ewie.name> writes:
> On 29/08/2023 18:43 CEST Stuart McGraw <smcg4191@mtneva.com> wrote:
>> Shouldn't psql put *something* (like "(default)" or "-") in the
>> "Access privileges" column to indicate that?  Or conversely,
>> something (like "(none)"?) in the revoked case?

> Indeed, that's confusing.  Command \dp always prints null as empty string [1].
> So \pset null '(null)' has no effect.

Yeah, perhaps.  The reason it so seldom comes up is that a state of
zero privileges is extremely rare (because it's useless in practice).

That being the case, if we were to do something about this, I'd vote
for changing the display of zero-privileges to "(none)" or something
along that line, rather than changing the display of NULL, which
people are accustomed to.

Fixing \dp to honor "\pset null" for this might be a reasonable
thing to do too.  I'm actually a bit surprised that that doesn't
work already.

            regards, tom lane



Re: Restoring default privileges on objects

От
Erik Wienhold
Дата:
> On 29/08/2023 21:27 CEST Tom Lane <tgl@sss.pgh.pa.us> wrote:
>
> Yeah, perhaps.  The reason it so seldom comes up is that a state of
> zero privileges is extremely rare (because it's useless in practice).
>
> That being the case, if we were to do something about this, I'd vote
> for changing the display of zero-privileges to "(none)" or something
> along that line, rather than changing the display of NULL, which
> people are accustomed to.

+1

> Fixing \dp to honor "\pset null" for this might be a reasonable
> thing to do too.  I'm actually a bit surprised that that doesn't
> work already.

Looks like all commands in src/bin/psql/describe.c set nullPrint = NULL.  Has
been that way since at least 1999.

--
Erik



Re: Restoring default privileges on objects

От
Stuart McGraw
Дата:
On 8/29/23 13:27, Tom Lane wrote:
> Erik Wienhold <ewie@ewie.name> writes:
>> On 29/08/2023 18:43 CEST Stuart McGraw <smcg4191@mtneva.com> wrote:
>>> Shouldn't psql put *something* (like "(default)" or "-") in the
>>> "Access privileges" column to indicate that?  Or conversely,
>>> something (like "(none)"?) in the revoked case?
> 
>> Indeed, that's confusing.  Command \dp always prints null as empty string [1].
>> So \pset null '(null)' has no effect.
> 
> Yeah, perhaps.  The reason it so seldom comes up is that a state of
> zero privileges is extremely rare (because it's useless in practice).
> 
> That being the case, if we were to do something about this, I'd vote
> for changing the display of zero-privileges to "(none)" or something
> along that line, rather than changing the display of NULL, which
> people are accustomed to.
> 
> Fixing \dp to honor "\pset null" for this might be a reasonable
> thing to do too.  I'm actually a bit surprised that that doesn't
> work already.
> 
>             regards, tom lane

That change would still require someone using \dp to realize that
the "Access privileges" value could be either '' or NULL (I guess
that could be pointed out more obviously in the psql doc), and then
do a '\pset null' before doing \dp?  That seems a little inconvenient.

As a possible alternative, in the query that \dp sends, what about
replacing the line:

   select ...,
     pg_catalog.array_to_string(c.relacl, E'\n') as "Access privileges"
     ...

with something like:

     CASE array_length(c.relacl,1) WHEN 0 THEN '(none)' ELSE pg_catalog.array_to_string(c.relacl, E'\n') END as "Access
privileges"

I realize that removes the ability to control with pset what is
displayed, but maybe a little more foolproof for naive users like
myself?




Re: Restoring default privileges on objects

От
Erik Wienhold
Дата:
> On 29/08/2023 22:44 CEST Stuart McGraw <smcg4191@mtneva.com> wrote:
>
> That change would still require someone using \dp to realize that
> the "Access privileges" value could be either '' or NULL (I guess
> that could be pointed out more obviously in the psql doc), and then
> do a '\pset null' before doing \dp?  That seems a little inconvenient.

Right.

> As a possible alternative, in the query that \dp sends, what about
> replacing the line:
>
>    select ...,
>      pg_catalog.array_to_string(c.relacl, E'\n') as "Access privileges"
>      ...
>
> with something like:
>
>      CASE array_length(c.relacl,1) WHEN 0 THEN '(none)' ELSE pg_catalog.array_to_string(c.relacl, E'\n') END as
"Accessprivileges"
 
>
> I realize that removes the ability to control with pset what is
> displayed, but maybe a little more foolproof for naive users like
> myself?

I think hardcoding '(none)' is what Tom meant (at least how I read it).  Also
'(none)' should probably be localizable like the table header.

The \pset change would be separate.

--
Erik



Re: Restoring default privileges on objects

От
"Peter J. Holzer"
Дата:
On 2023-08-29 14:44:48 -0600, Stuart McGraw wrote:
> On 8/29/23 13:27, Tom Lane wrote:
> > Fixing \dp to honor "\pset null" for this might be a reasonable
> > thing to do too.  I'm actually a bit surprised that that doesn't
> > work already.
>
> That change would still require someone using \dp to realize that
> the "Access privileges" value could be either '' or NULL (I guess
> that could be pointed out more obviously in the psql doc), and then
> do a '\pset null' before doing \dp?  That seems a little inconvenient.

Or just always do a \pset null. For me printing NULL the same as an
empty string is just as confusing in normal tables, so that's the first
line in my ~/.psqlrc. YMMV, of course.

But I guess the point is that people who do \pset null expect to be able
to distinguish '' and NULL visually and might be surprised if that
doesn't work everywhere, while people who don't \pset null know that ''
and NULL are visually indistinguishable and that they may need some
other way to distinguish them if the difference matters.

So +1 for me fixing \dp to honor "\pset null".

        hp

--
   _  | Peter J. Holzer    | Story must make more sense than reality.
|_|_) |                    |
| |   | hjp@hjp.at         |    -- Charles Stross, "Creative writing
__/   | http://www.hjp.at/ |       challenge!"

Вложения