Thread: BUG #2085: pg_dump incompletely dumps ACLs

BUG #2085: pg_dump incompletely dumps ACLs

From
"David Begley"
Date:
The following bug has been logged online:

Bug reference:      2085
Logged by:          David Begley
Email address:      d.begley@uws.edu.au
PostgreSQL version: 8.1.0
Operating system:   Windows XP
Description:        pg_dump incompletely dumps ACLs
Details:

Running the following command:

pg_dump -v -C -f \windows\temp\dump.sql dbname

produced a plain text dump of the named database containing various
ACL-related statements (GRANT/REVOKE), but unfortunately some information
from the original running database was lost.

This means when the dump is imported to another PostgreSQL instance, the
resultant ACLs do not match those of the original instance.

The ACLs in question are those represented as "{}" (ie., nothing between the
braces);  such an ACL on a database object or language object (there may be
others affected but these are the only two I have so far confirmed) is not
properly recorded by pg_dump, but the same ACL on a function is recorded
(and recreated on the destination PostgreSQL instance) perfectly fine.

The dump generated contains no GRANT/REVOKE statements for the database
itself at all, whilst the language object includes only a REVOKE from PUBLIC
(a REVOKE from the owner is missing).  For functions, a REVOKE from both
PUBLIC and the owner are correctly included by pg_dump.

The dump was generated/recreated by a user with "superuser" access to the
database.

This may sound like a puzzling ACL, but regardless the dump should include
all information from the source database so it can be reproduced correctly
when restored.

Cheers..

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
Tom Lane
Date:
"David Begley" <d.begley@uws.edu.au> writes:
> This means when the dump is imported to another PostgreSQL instance, the
> resultant ACLs do not match those of the original instance.

Please provide a concrete test case, not handwaving.

            regards, tom lane

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
David J N Begley
Date:
Earlier today, Tom Lane wrote:

> "David Begley" <d.begley@uws.edu.au> writes:
> > This means when the dump is imported to another PostgreSQL instance, the
> > resultant ACLs do not match those of the original instance.
>
> Please provide a concrete test case, not handwaving.

C:\Program Files\PostgreSQL\8.1\bin>createdb concrete "Test Case"
CREATE DATABASE
COMMENT

C:\Program Files\PostgreSQL\8.1\bin>psql -q concrete
concrete=# REVOKE ALL ON DATABASE concrete FROM PUBLIC;
concrete=# REVOKE ALL ON DATABASE concrete FROM david;
concrete=# SELECT datacl FROM pg_database WHERE datname = 'concrete';
 datacl
--------
 {}
(1 row)

concrete=# \q

C:\Program Files\PostgreSQL\8.1\bin>pg_dump -C -f \windows\temp\dump.sql concrete

C:\Program Files\PostgreSQL\8.1\bin>dropdb -q concrete

C:\Program Files\PostgreSQL\8.1\bin>psql -f \windows\temp\dump.sql postgres
SET
SET
SET
CREATE DATABASE
ALTER DATABASE
You are now connected to database "concrete".
SET
SET
SET
COMMENT
COMMENT
CREATE LANGUAGE
REVOKE
REVOKE
GRANT
GRANT

C:\Program Files\PostgreSQL\8.1\bin>psql -q concrete
concrete=# SELECT datacl FROM pg_database WHERE datname = 'concrete';
 datacl
--------

(1 row)

concrete=# -- datacl in restored database does not match origin database
concrete=# \q

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
Tom Lane
Date:
David J N Begley <d.begley@uws.edu.au> writes:
> Earlier today, Tom Lane wrote:
>> Please provide a concrete test case, not handwaving.

> C:\Program Files\PostgreSQL\8.1\bin>createdb concrete "Test Case"
> CREATE DATABASE
> COMMENT

> C:\Program Files\PostgreSQL\8.1\bin>psql -q concrete
> concrete=# REVOKE ALL ON DATABASE concrete FROM PUBLIC;
> concrete=# REVOKE ALL ON DATABASE concrete FROM david;
> concrete=# SELECT datacl FROM pg_database WHERE datname = 'concrete';
>  datacl
> --------
>  {}
> (1 row)

> concrete=# \q

> C:\Program Files\PostgreSQL\8.1\bin>pg_dump -C -f \windows\temp\dump.sql concrete

Database ACLs are dumped by pg_dumpall, not pg_dump.  I agree this is a
bit inconsistent considering that pg_dump has a -C option, but the -C
option has always been pretty poorly thought out :-(.

Given that -C overlaps pg_dumpall functionality anyway, maybe it should
dump GRANT/REVOKE commands for the database too?  Any thoughts pro or
con out there?

            regards, tom lane

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
Alvaro Herrera
Date:
Tom Lane wrote:

> Given that -C overlaps pg_dumpall functionality anyway, maybe it should
> dump GRANT/REVOKE commands for the database too?  Any thoughts pro or
> con out there?

I agree.  Why have only half a funcionality if we can have the whole
thing?  Maybe we can take that part of of pg_dumpall if at all possible,
and make it use pg_dump's.

Does pg_dump -C include the database comment already?  If not, maybe
it's worth to add it as well.

--
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
David J N Begley
Date:
On Fri, 2 Dec 2005, Alvaro Herrera wrote:

> Tom Lane wrote:
>
> > Given that -C overlaps pg_dumpall functionality anyway, maybe it should
> > dump GRANT/REVOKE commands for the database too?  Any thoughts pro or
> > con out there?

See below - I hadn't tried it previously, but having now tried pg_dumpall I've
found it also has an ACL-loss bug.

> I agree.  Why have only half a funcionality if we can have the whole
> thing?  Maybe we can take that part of of pg_dumpall if at all possible,
> and make it use pg_dump's.

Speaking as just a dumb end-user, I get the impression that pg_dump is used to
extract a single database, not just part of a database;  sayeth the manual:

  "pg_dump is a utility for backing up a PostgreSQL database. [...] Script
  dumps are plain-text files containing the SQL commands required to
  reconstruct the database to the state it was in at the time it was
  saved."

Unless I'm missing something, that means pg_dump should include (when told to
do so, as in this case) _all_ commands required to restore the database "to
the state it was in at the time it was saved".  What's happening at the moment
is that some GRANT/REVOKE commands are included but others are missing,
meaning any transfer of a database is potentially losing (at least some) ACLs
along the way.

I have verified that _no_ GRANT/REVOKE commands are dumped for the database,
and only some GRANT/REVOKE commands are dumped for "language" objects (see
below);  near as I can tell, all GRANT/REVOKE commands are dumped for
"function" and "table" objects, but it's early in the morning so I may be
missing something.

When I say that "only some" commands are dumped for "language" objects,
remember my original bug report - I tripped over this whilst verifying whether
or not "{}" ACLs (ie., not even owner or PUBLIC) are correctly
dumped/restored.  For functions, I find this in the pg_dump output:

REVOKE ALL ON FUNCTION function_check() FROM PUBLIC;
REVOKE ALL ON FUNCTION function_check() FROM postgres;

In other words, dump/restore appears to do its job.  For the database, there
are no GRANT/REVOKE statements at all.  For "language" objects, pg_dump
provides:

REVOKE ALL ON LANGUAGE plpgsql FROM PUBLIC;

Here, a second statement revoking rights from the owner (in order to achieve
the "{}" ACL in the original database) is missing (yet it revoked rights
from PUBLIC - why only half an ACL?).

> Does pg_dump -C include the database comment already?  If not, maybe
> it's worth to add it as well.

A very basic test for me shows the database comment is already included.

Bearing in mind Tom's statement regarding pg_dump versus pg_dumpall, I ran the
latter to check its output (though in reality it's not the entire cluster I'm
trying to dump here):

- pg_dumpall includes the two missing REVOKE statements on the database
  that pg_dump is mising;

- both pg_dump and pg_dumpall include the database comment;  and,

- both pg_dump and pg_dumpall are missing the second REVOKE statement (for
  the owner) on the "language" object (ie., bug in both).

I don't know what other objects may be affected (either in pg_dump or
pg_dumpall).

Cheers..

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
Tom Lane
Date:
David J N Begley <d.begley@uws.edu.au> writes:
> I have verified that _no_ GRANT/REVOKE commands are dumped for the database,
> and only some GRANT/REVOKE commands are dumped for "language" objects (see
> below);

The latter is not really a bug.  Languages don't currently have owners
(ie there is no owner column in pg_language).  For ACL-munging purposes
we act as though the bootstrap superuser owns the language, that is,
that userid is shown as the grantor of privileges.  But having a
superuser revoke his own privileges is a no-op, because he's a superuser
and the privileges aren't going to be enforced against him anyway.  So
the fact that pg_dump doesn't process that part of the ACL isn't very
meaningful.

Sooner or later we may get around to assigning explicit owners to
languages, but it's not a high-priority problem --- AFAICS the lack
of ownership doesn't create any problems worse than these sorts of
corner-case confusions.  It'll always be true that superuserdom is
needed to create a PL, and distinguishing one superuser from another
is not a particularly useful activity in the context of permission
checks ...

I fooled around with having pg_dump explicitly treat the language as
being owned by the bootstrap superuser, and think I may apply the patch
now even though it doesn't really matter, because it does clean up the
output a little bit --- instead of

--
-- Name: pltcl; Type: ACL; Schema: -; Owner:
--

REVOKE ALL ON LANGUAGE pltcl FROM PUBLIC;
SET SESSION AUTHORIZATION postgres;
GRANT ALL ON LANGUAGE pltcl TO postgres;
RESET SESSION AUTHORIZATION;
SET SESSION AUTHORIZATION postgres;
GRANT ALL ON LANGUAGE pltcl TO tgl;
RESET SESSION AUTHORIZATION;

I get

--
-- Name: pltcl; Type: ACL; Schema: -; Owner: postgres
--

REVOKE ALL ON LANGUAGE pltcl FROM PUBLIC;
REVOKE ALL ON LANGUAGE pltcl FROM postgres;
GRANT ALL ON LANGUAGE pltcl TO postgres;
GRANT ALL ON LANGUAGE pltcl TO tgl;

for a pg_language ACL of "{postgres=U/postgres,tgl=U/postgres}".
Avoiding the SET SESSION AUTHORIZATIONs seems like a good idea.

            regards, tom lane

Re: BUG #2085: pg_dump incompletely dumps ACLs

From
David J N Begley
Date:
On Sat, 3 Dec 2005, Tom Lane wrote:

> The latter is not really a bug.  Languages don't currently have owners
> (ie there is no owner column in pg_language).  For ACL-munging purposes

The true behaviour of the ACL may be somewhat unusual - understood (after all,
I admitted at the outset that the use of the "{}" ACLs could seem strange).

> and the privileges aren't going to be enforced against him anyway.  So
> the fact that pg_dump doesn't process that part of the ACL isn't very
> meaningful.

True, though that could have unintended side effects in future as certain
details (ACLs or whatever) are lost/modified as a database is dumped/restored
between different PostgreSQL versions (something that was a no-op before
suddenly creates problems a newer version due to feature changes/additions).

Thanks for taking the time to investigate this - my whole concern was just
that the doco-set user expectations be met by the dump tools in reality (ie.,
if a whole database dump is requested, then everything is restored in the
destination cluster).

Thanks again..