Hello hackers,

I noticed that in some situations involving the use of REVOKE ON SCHEMA,
pg_dump
can produce a dump that cannot be restored.  This prevents successful
pg_restore (and by corollary, pg_upgrade).

An example shell script to recreate this problem is attached.  The error
output appears at the end like this:

<snippet>
+ pg_restore -d postgres /tmp/foo.dmp
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 2748; 0 0 ACL TABLE
mytable owneruser
pg_restore: [archiver (db)] could not execute query: ERROR:  permission
denied for schema private
    Command was: GRANT SELECT ON TABLE private.mytable TO privileged WITH
GRANT OPTION;
SET SESSION AUTHORIZATION privileged;
GRANT SELECT ON TABLE private.mytable TO enduser WITH GRANT OPTION;
RESET SESSION AUTHORIZATION;
WARNING: errors ignored on restore: 1
-bash-4.2$
</snippet>

Note that `privileged` user needs to grant permissions to `enduser`, but
can no longer do so because `privileged` no longer has access to the
`private` schema (it was revoked).

How might we fix up pg_dump to handle these sorts of situations?  It seems
like pg_dump might need extra logic to GRANT the schema permissions to the
`privileged` user and then REVOKE them later on?

Thanks for looking,
--Richard
#!/bin/bash

set -x

# Clean
pg_ctl -D /tmp/data -mi stop
pg_ctl -D /tmp/data2 -mi stop
rm -rf /tmp/data
rm -rf /tmp/data2

# Initdb
initdb -D /tmp/data

# Start
pg_ctl -D /tmp/data -l /tmp/logfile start

# Create database
createdb foo

# Create users
psql -c "create role owneruser with login" foo
psql -c "create role privileged with login" foo
psql -c "create role enduser with login" foo

# Grant schema permission
psql -c "create schema private" foo
psql -c "alter schema private owner to owneruser" foo
psql -U owneruser -c "grant usage, create on schema private to privileged with grant option" foo
psql -U privileged -c "grant usage, create on schema private to enduser with grant option" foo

# Create table
psql -U owneruser -c "create table private.mytable (id int, name text)" foo

# Grant table permission
psql -U owneruser      -c "grant select on private.mytable to privileged with grant option" foo
psql -U privileged -c "grant select on private.mytable to enduser with grant option" foo

# Revoke schema permission
psql -c "revoke usage, create on schema private from privileged cascade" foo

# Dump globals
pg_dumpall -g > /tmp/globals.dmp

# Dump database
pg_dump -Fc -C foo > /tmp/foo.dmp

# Shut down
pg_ctl -D /tmp/data -mf stop

# Init new cluster
initdb -D /tmp/data2

# Start new cluster
pg_ctl -D /tmp/data2 -l /tmp/logfile2 start

# Load globals
psql -f /tmp/globals.dmp

# Restore database
pg_restore -d postgres /tmp/foo.dmp


#### Failure output looks like this ####
## + pg_restore -d postgres /tmp/foo.dmp
## pg_restore: [archiver (db)] Error while PROCESSING TOC:
## pg_restore: [archiver (db)] Error from TOC entry 2748; 0 0 ACL TABLE mytable owneruser
## pg_restore: [archiver (db)] could not execute query: ERROR:  permission denied for schema private
##     Command was: GRANT SELECT ON TABLE private.mytable TO privileged WITH GRANT OPTION;
## SET SESSION AUTHORIZATION privileged;
## GRANT SELECT ON TABLE private.mytable TO enduser WITH GRANT OPTION;
## RESET SESSION AUTHORIZATION;
## 
## WARNING: errors ignored on restore: 1
## -bash-4.2$
#### End snippet ####

Reply via email to