Restore database with changed privileges - postgresql

We have two PostgreSQL servers. On web server1 pguser1 is the associated user who creates all database objects required to work with the web application. Let's say, all objects are in schema1.
Similarly, on server2 pguser2 creates data for Web server 2.
I have taken a schema backup (custom option in the backup window from pgadmin) from server1. When I restore to server2 I want all privileges and ownership of objects to be with pguser2 and nothing with pguser1.
How can this be achieved? If possible, an option during during restore (pg_restore command) would be preferred.

It would very much simplify your task if you GRANT privileges and ownership to a non-login role (a.k.a. group). Let's name it foo_admin. On server1 you
GRANT foo_admin TO pguser1;
On server2 you
REVOKE foo_admin FROM pguser1;
GRANT foo_admin TO pguser2;
All done. Or better yet: hack the dump file and replace 1 with 2 in the line
GRANT foo_admin TO pguser1;
.. before you restore. pguser2 has to be created first, of course.
Now, just make sure, when you create anything on server1 to
ALTER TABLE wuchtel12.game OWNER TO foo_admin;
And set privileges. You can preset privileges per schema. Something like:
ALTER DEFAULT PRIVILEGES IN SCHEMA schema1
GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLES
TO foo_admin;
ALTER DEFAULT PRIVILEGES IN SCHEMA schema1
GRANT SELECT, UPDATE, USAGE ON SEQUENCES
TO foo_admin;
This works identically on server1 and server2.
More details and links in this related answer.
You might also be interested in the Grant Wizard of pgAdmin. Details in this related answer

Related

Postgresql: cannot set default privileges on tables [duplicate]

I'm building a spring boot application. Flyway database migrations are executed at the application startup.
I decided to use two different roles: role__app (read/write rights on tables, sequences in app schema) and role__migration (advanced rights in app/migration schemas).
Flyway migrations are executed under role__migration so it becomes the owner of the created objects. I thought that the following statements would help:
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO role__app;
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT USAGE ON SEQUENCES TO role__app;
But when the new tables are added to the app schema the user__app (belongs to the role__app) doesn't have access to the tables.
Is it possible to maintain such a flow (with app, migrattion users/roles) by Postgres or by any other means?
As a side note I should mention that I run the following statements on the target database:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON DATABASE myDb FROM PUBLIC;
Update 1
I added the FOR ROLE clause, yet I'm still getting the permission denied message for a created table (app.property) in app schema for user user__app. The owner of the table is user__mig.
Update 2
After logging in as postgres user in dbeaver we can see that user__mig has all necessary permissions ticked whereas the user__app has no permissions on the app.property table at all:
Here is a gist to reproduce the problem: https://gist.github.com/happygrizzly/849a6a791f028ba5b191f73180ae35d1
You should write
ALTER DEFAULT PRIVILEGES FOR USER role__migration ...
If you omit the FOR USER clause, the privileges are only granted on objects created by the user who ran ALTER DEFAULT PRIVILEGES.
With the above statement, the privileges are granted when role__migration creates an object. That does not extend to members of the role role__migration.

PostgreSQL: Grant CRUD operations only in one database

Is there any way to grant CRUD operations to a user ONLY on a specific database?
Let's asume there are 2 databases on my server: database_allowed and database_forbiden
I have created a user on postgreSQL, and granted this privileges:
CREATE ROLE crud_user LOGIN PASSWORD '###';
--Next commands are executed connected to the database
GRANT CONNECT ON DATABASE database_allowed TO crud_user ;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO crud_user;
However, after executing the commands, I only get an error:
FATAL: role "crud_user" is not permitted to log in
I know I can execute: ALTER ROLE crud_user WITH LOGIN, but, despite the user can only execute CRUD operations on database_allowed, he can connect both, and see tablenames, etc...
Is there a way to prevent granting login on all databases?
Your crud_user can access the other database because of its PUBLIC permissions:
PostgreSQL grants privileges on some types of objects to PUBLIC by default when the objects are created. No privileges are granted to PUBLIC by default on tables, table columns, sequences, foreign data wrappers, foreign servers, large objects, schemas, or tablespaces. For other types of objects, the default privileges granted to PUBLIC are as follows: CONNECT and TEMPORARY (create temporary tables) privileges for databases; EXECUTE privilege for functions and procedures; and USAGE privilege for languages and data types (including domains). The object owner can, of course, REVOKE both default and expressly granted privileges.
(Postgres documentation Privileges)
So you'll want to run
REVOKE CONNECT ON DATABASE database_forbidden FROM PUBLIC

Postgres: granting access to a role/user for future tables created by a different role/user

I'm building a spring boot application. Flyway database migrations are executed at the application startup.
I decided to use two different roles: role__app (read/write rights on tables, sequences in app schema) and role__migration (advanced rights in app/migration schemas).
Flyway migrations are executed under role__migration so it becomes the owner of the created objects. I thought that the following statements would help:
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO role__app;
ALTER DEFAULT PRIVILEGES IN SCHEMA app GRANT USAGE ON SEQUENCES TO role__app;
But when the new tables are added to the app schema the user__app (belongs to the role__app) doesn't have access to the tables.
Is it possible to maintain such a flow (with app, migrattion users/roles) by Postgres or by any other means?
As a side note I should mention that I run the following statements on the target database:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON DATABASE myDb FROM PUBLIC;
Update 1
I added the FOR ROLE clause, yet I'm still getting the permission denied message for a created table (app.property) in app schema for user user__app. The owner of the table is user__mig.
Update 2
After logging in as postgres user in dbeaver we can see that user__mig has all necessary permissions ticked whereas the user__app has no permissions on the app.property table at all:
Here is a gist to reproduce the problem: https://gist.github.com/happygrizzly/849a6a791f028ba5b191f73180ae35d1
You should write
ALTER DEFAULT PRIVILEGES FOR USER role__migration ...
If you omit the FOR USER clause, the privileges are only granted on objects created by the user who ran ALTER DEFAULT PRIVILEGES.
With the above statement, the privileges are granted when role__migration creates an object. That does not extend to members of the role role__migration.

Limit db user permission on google cloud sql

I'm new to Google Cloud SQL. I created two postgres DBs with two new users (one created from web dashboard and one created from commandline). My goal is to prevent the two users to be able to modify each other DB, but I cannot get it to work.
Here is what I want:
UserA all privileges on DB_A
UserA no privileges on DB_B
UserB all privileges on DB_B
UserB no privileges on DB_A
I already tried to grant/revoke permissions from psql prompt, but in the end I still be able to create/drop tables in DB_A as UserB.
Is it possible to achieve what I want? Am I missing something?
Postgres on Cloud SQL is standard Postgres, so it's just like any other Postgres instance:
To give a role all privileges:
GRANT ALL ON <db_name> TO <role_name>;
To remove all privileges:
REVOKE ALL ON <db_name> TO <role_name>;
The Postgres docs on privileges does give the follow caveat for:
The special privileges of an object's owner (i.e., the right to modify
or destroy the object) are always implicit in being the owner, and
cannot be granted or revoked
So keep that in mind - if UserA owns both databases, they can always modify them.

ERROR: permission denied for schema user1_gmail_com at character 46

I need to restrict a user, access only on a particualr schema tables only.So I tried following query and login as user1_gmail_com. But I got following error when I try to browse any schema table.
My Query:
SELECT clone_schema('my_application_template_schema','user1_gmail_com');
CREATE USER user1_gmail_com WITH PASSWORD 'myloginpassword';
REVOKE ALL ON ALL TABLES IN SCHEMA user1_gmail_com FROM PUBLIC;
GRANT SELECT ON ALL TABLES IN SCHEMA user1_gmail_com TO user1_gmail_com;
SQL error:
ERROR: permission denied for schema user1_gmail_com at character 46
In statement:
SELECT COUNT(*) AS total FROM (SELECT * FROM "user1_gmail_com"."organisations_table") AS sub
Updated Working Query:
SELECT clone_schema('my_application_template_schema','user1_gmail_com');
CREATE USER user1_gmail_com WITH PASSWORD 'myloginpassword';
REVOKE ALL ON ALL TABLES IN SCHEMA user1_gmail_com FROM PUBLIC;
GRANT USAGE ON SCHEMA user1_gmail_com TO user1_gmail_com;
GRANT SELECT ON ALL TABLES IN SCHEMA user1_gmail_com TO user1_gmail_com;
You need to grant access not only to the tables in the schema, but also to the schema itself.
From the manual:
By default, users cannot access any objects in schemas they do not own. To allow that, the owner of the schema must grant the USAGE privilege on the schema.
So either make your created user the owner of the schema, or grant USAGE on the schema to this user.
This confused me. Still not sure I'm handling it correctly. Run \h grant for the syntax within psql. Here is how I managed to get my other users and groups to work as I needed:
GRANT ALL PRIVILEGES ON SCHEMA foo TO GROUP bar;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA foo TO GROUP bar;
I kept getting this error when using flyway to deploy database changes. I do some manual setup first, such as creating the database, so flyway wouldn't need those super-admin permissions.
My Fix
I had to ensure that the database user that flyway job used had ownership rights to the public schema, so that the flyway user could then assign the right to use the schema to other roles.
Additional setup Details
I am using AWS RDS (both regular and Aurora), and they don't allow super users in the databases. RDS reserves super users for use by AWS, only, so that consumers are unable to break the replication stuff that is built in. However, there's a catch-22 that you must be an owner in postgres to be able to modify it.
My solution was to create a role that acts as the owner ('owner role'), and then assign both my admin user and the flyway user to the owner role, and use ALTER scripts for each object to assign the object's owner to the owner role.
I missed the public schema, since that was auto-created when I created the database script manually. The public schema defaulted to my admin role rather than the shared owner role. So when the flyway user tried to assign public schema permissions to other roles, it didn't have the authority to do that. An error was not thrown during flyway execution, however.