Permission denied to copy database - postgresql

I'm still getting used to the concept of roles in Postgres.
I'm trying to create a role, migrator, that will have the ability to read from a production db and use it as a template to make stage and dev databases.
I've created this role migrator originally like so:
CREATE ROLE migrator LOGIN ENCRYPTED PASSWORD '<password>'
and proceeded to restrict access to the prod database:
REVOKE ALL ON DATABASE prod FROM PUBLIC;
GRANT CONNECT ON DATABASE prod TO migrator;
/* switch to prod database */
GRANT USAGE ON SCHEMA public TO migrator;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO migrator;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO migrator;
After trying a CREATE DATABASE stage TEMPLATE prod; and getting an error, I had to alter the role to create a db:
ALTER ROLE migrator CREATEDB;
and tried again. This time I got the error:
ERROR: permission denied to copy database "prod"
And again, I tried to add the replication permission to the migrator role (not sure if this is correct, as the manual says this is a very elevated permission)
ALTER ROLE migrator REPLICATION;
however, I still get the same error.
UPDATE: I've figured out that this has something to do with who owns the database; however, my problem remains. How can I allow another role with just READ privileges the ability to copy a database as well? I looked at role inheritance, but at first glance it looks like the inheriting role will just get the same permissions as the parent role.

It's not possible to copy a database unless the logged-in role is an owner or the database is flagged as a template:
datistemplate can be set to indicate that a database is intended as a template for CREATE DATABASE. If this flag is set, the database can be cloned by any user with CREATEDB privileges; if it is not set, only superusers and the owner of the database can clone it.

Related

Postgres: prevent new user from creating tables, without superuser

In Cloud SQL Postgres, where superuser permissions are not accessible, how can I prevent a new user from creating tables?
I know that REVOKE CREATE ON SCHEMA public FROM public works, but this seem to require superuser permissions, as I get a WARNING: no privileges could be revoked for "public" error.
You have to run that statement as the user who owns public.

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.

CloudSQL Postgres confused around table grants and owners

I'm using CloudSQL Postgres 11 on GCP, and I've got a few questions around permissions and grants. I'm just not getting it at the moment, being very new to postgres.
I have a user, pgadmin which is a superuser. With this user I can connect to the instance and create a database called 'sandbox' for example.
I then have an app role which is defined as follows:
CREATE ROLE app;
GRANT CONNECT ON DATABASE <database name> TO app;
GRANT USAGE, CREATE ON SCHEMA public TO app;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO app;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE ON SEQUENCES TO app;
I create a user called app_sandbox which I grant this role.
The app user then makes a db migration using flyway which creates 2 tables. That side of things is fine.
But with my superuser, pgadmin, I can't see these tables or query them even though this user owns the database and is a superuser. I've tried all sorts of grants. Feels like I'm missing something important because even if I true to create a readonly role with the pgadmin user I am unable to grant access to the underlying tables in the public schema of the database.
What am I missing?
Just because one user (=pgadmin) owns the database, does not mean that user also owns the tables created in that database. And because pgadmin doesn't own those tables, you can't access them when logged in as pgadmin
If the app user created the tables, they belong to that user, and only the app user can grant privileges on those tables to other users.

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.

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.