postgres role to access all schema - postgresql

I am using postgres 9.4 database with many schemas. How can I create a login role that can select table of all table of all schema and also any new schema that we create in the database

To answer your comment I think this statement will work:
ALTER DEFAULT PRIVILEGES
FOR ROLE role_name
IN SCHEMA public
GRANT ALL PRIVILEGES ON TABLES TO role_name;

Related

PostgreSQL: roles can only access tables they've created

I have a postgresql (v10) database. I've created database tn_beta_db with schema tn_schema. I've created three users and executed the following, which is meant to grant all of them read and maybe modify access on all tables, current and future that tn_beta_migrator might create.
\c tn_beta_db
-- User tn_beta_reader --
ALTER DEFAULT PRIVILEGES IN SCHEMA tn_schema FOR ROLE tn_beta_reader GRANT SELECT ON TABLES TO tn_beta_reader;
GRANT CONNECT ON DATABASE tn_beta_db TO tn_beta_reader;
GRANT USAGE ON SCHEMA tn_schema TO tn_beta_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA tn_schema TO tn_beta_reader;
-- User tn_beta_migrator --
ALTER DEFAULT PRIVILEGES IN SCHEMA tn_schema FOR ROLE tn_beta_migrator GRANT ALL ON TABLES TO tn_beta_migrator;
GRANT CONNECT ON DATABASE tn_beta_db TO tn_beta_migrator;
GRANT USAGE ON SCHEMA tn_schema TO tn_beta_migrator;
GRANT ALL ON ALL TABLES IN SCHEMA tn_schema TO tn_beta_migrator;
GRANT CREATE ON SCHEMA tn_schema TO tn_beta_migrator;
-- User tn_beta_writer --
ALTER DEFAULT PRIVILEGES IN SCHEMA tn_schema FOR ROLE tn_beta_writer GRANT SELECT,INSERT,DELETE,UPDATE ON TABLES TO tn_beta_writer;
GRANT CONNECT ON DATABASE tn_beta_db TO tn_beta_writer;
GRANT USAGE ON SCHEMA tn_schema TO tn_beta_writer;
GRANT SELECT,INSERT,DELETE,UPDATE ON ALL TABLES IN SCHEMA tn_schema TO tn_beta_writer;
If I now connect as tn_beta_migrator, I can create a table and do things with it.
create table tn_schema.foo(x int);
-- and then INSERT, SELECT, UPDATE, even DROP
But now if I connect as either of tn_beta_reader or tn_beta_writer, I can not use that table.
tn_beta_db=> select * from tn_schema.foo ;
ERROR: permission denied for relation foo
tn_beta_db=>
I would expect to be able to read/write/modify/delete as tn_beta_writer and to be able to read as tn_beta_reader.
If I rerun the grant script, above, this permits me to access foo, but a newly created table bar would then be inaccessible.
I'd thought that the alter default privileges commands would permit these roles, in the future, to access the tables created by tn_beta_migrator.
Any pointers on what I've misunderstood?
The role in the FOR ROLE clause in ALTER DEFAULT PRIVILEGES is not the role that will get the privileges, it is the role that creates the tables.
So your statements should start with
ALTER DEFAULT PRIVILEGES FOR ROLE tn_beta_migrator ...

Set default ACL for all currently defined roles in Postgres

I would like to set default ACL for all roles (i.e. without using PUBLIC) in PostgreSQL and want to avoid enumerating.
Is there an easy way to do that?
You can do this in the following way:
Grant SELECT privilege to everyone for all tables (and views) you subsequently create in schema myschema:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT SELECT ON TABLES TO PUBLIC;
and allow role webuser to INSERT into them too:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema GRANT INSERT ON TABLES TO webuser;
and to Undo the above:
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE SELECT ON TABLES FROM PUBLIC;
ALTER DEFAULT PRIVILEGES IN SCHEMA myschema REVOKE INSERT ON TABLES FROM webuser;
Source
That's it :)

Grant access to views in postgresql

I have a view called testview in postgresql.
I created a new user called testuser.
I would like testuser to have all privileges on all tables and views in the database.
To do this I ran the following commands:
GRANT ALL PRIVILEGES ON DATABASE testdb TO testuser;
GRANT USAGE ON SCHEMA public TO testuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO testuser;
testuser now has access to all tables in the database, but if I try to run SELECT * FROM testview I get the following error: permission denied for relation testview.
What is wrong? How do testuser get access to testview?
I agree it should work. With permissions GRANT ... ON ALL TABLES should include views too.
Did you create the view after granting the privileges to testuser? If so then it doesn't have the same privileges as the other tables. That's because GRANT ... ON ALL TABLES means "on all tables that currently exist". To include tables/views you create in the future, you can say:
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO testuser;
Or if you want to give more than SELECT, you can say ALL PRIVILEGES instead.
I think this behavior of ON ALL TABLES is one of the most misunderstood bits about Postgres permissions, and it isn't really called out in the standard documentation, so I tried to emphasize it in my own Postgres permissions overview.
postgres=# GRANT ALL PRIVILEGES ON DATABASE testdb TO testuser;
postgres=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO testuser;
GRANT USAGE on schema:
GRANT USAGE ON SCHEMA schema_name TO username;
Grant SELECT for a specific table:
GRANT SELECT ON tbl_loans_new TO oloffm;
Grant SELECT for multiple tables:
GRANT SELECT ON ALL TABLES IN SCHEMA schema_name TO username;

Read only postgres user [duplicate]

I'd like to create a user in PostgreSQL that can only do SELECTs from a particular database. In MySQL the command would be:
GRANT SELECT ON mydb.* TO 'xxx'#'%' IDENTIFIED BY 'yyy';
What is the equivalent command or series of commands in PostgreSQL?
I tried...
postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;
But it appears that the only things you can grant on a database are CREATE, CONNECT, TEMPORARY, and TEMP.
Grant usage/select to a single table
If you only grant CONNECT to a database, the user can connect but has no other privileges. You have to grant USAGE on namespaces (schemas) and SELECT on tables and views individually like so:
GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;
Multiple tables/views (PostgreSQL 9.0+)
In the latest versions of PostgreSQL, you can grant permissions on all tables/views/etc in the schema using a single command rather than having to type them one by one:
GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;
This only affects tables that have already been created. More powerfully, you can automatically have default roles assigned to new objects in future:
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO xxx;
Note that by default this will only affect objects (tables) created by the user that issued this command: although it can also be set on any role that the issuing user is a member of. However, you don't pick up default privileges for all roles you're a member of when creating new objects... so there's still some faffing around. If you adopt the approach that a database has an owning role, and schema changes are performed as that owning role, then you should assign default privileges to that owning role. IMHO this is all a bit confusing and you may need to experiment to come up with a functional workflow.
Multiple tables/views (PostgreSQL versions before 9.0)
To avoid errors in lengthy, multi-table changes, it is recommended to use the following 'automatic' process to generate the required GRANT SELECT to each table/view:
SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');
This should output the relevant GRANT commands to GRANT SELECT on all tables, views, and sequences in public, for copy-n-paste love. Naturally, this will only be applied to tables that have already been created.
Reference taken from this blog:
Script to Create Read-Only user:
CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234'
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';
\connect YourDatabaseName;
Assign permission to this read-only user:
GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Assign permissions to read all newly tables created in the future
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;
From PostgreSQL v14 on, you can do that simply by granting the predefined pg_read_all_data role:
GRANT pg_read_all_data TO xxx;
Do note that PostgreSQL 9.0 (today in beta testing) will have a simple way to do that:
test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
Here is the best way I've found to add read-only users (using PostgreSQL 9.0 or newer):
$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
Then log in to all related machines (master + read-slave(s)/hot-standby(s), etc..) and run:
$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload
By default new users will have permission to create tables. If you are planning to create a read-only user, this is probably not what you want.
To create a true read-only user with PostgreSQL 9.0+, run the following steps:
# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;
# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;
# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;
If your read-only user doesn't have permission to list tables (i.e. \d returns no results), it's probably because you don't have USAGE permissions for the schema. USAGE is a permission that allows users to actually use the permissions they have been assigned. What's the point of this? I'm not sure. To fix:
# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;
# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;
I’ve created a convenient script for that; pg_grant_read_to_db.sh. This script grants read-only privileges to a specified role on all tables, views and sequences in a database schema and sets them as default.
I read trough all the possible solutions, which are all fine, if you remember to connect to the database before you grant the things ;) Thanks anyway to all other solutions!!!
user#server:~$ sudo su - postgres
create psql user:
postgres#server:~$ createuser --interactive
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
start psql cli and set a password for the created user:
postgres#server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.
postgres=# alter user readonly with password 'readonly';
ALTER ROLE
connect to the target database:
postgres=# \c target_database
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".
grant all the needed privileges:
target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT
target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT
target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT
alter default privileges for targets db public shema:
target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES
If your database is in the public schema, it is easy (this assumes you have already created the readonlyuser)
db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT
If your database is using customschema, execute the above but add one more command:
db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE
The not straightforward way of doing it would be granting select on each table of the database:
postgres=# grant select on db_name.table_name to read_only_user;
You could automate that by generating your grant statements from the database metadata.
Taken from a link posted in response to despesz' link.
Postgres 9.x appears to have the capability to do what is requested. See the Grant On Database Objects paragraph of:
http://www.postgresql.org/docs/current/interactive/sql-grant.html
Where it says: "There is also an option to grant privileges on all objects of the same type within one or more schemas. This functionality is currently supported only for tables, sequences, and functions (but note that ALL TABLES is considered to include views and foreign tables)."
This page also discusses use of ROLEs and a PRIVILEGE called "ALL PRIVILEGES".
Also present is information about how GRANT functionalities compare to SQL standards.
CREATE USER username SUPERUSER password 'userpass';
ALTER USER username set default_transaction_read_only = on;

How do you create a read-only user in PostgreSQL?

I'd like to create a user in PostgreSQL that can only do SELECTs from a particular database. In MySQL the command would be:
GRANT SELECT ON mydb.* TO 'xxx'#'%' IDENTIFIED BY 'yyy';
What is the equivalent command or series of commands in PostgreSQL?
I tried...
postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;
But it appears that the only things you can grant on a database are CREATE, CONNECT, TEMPORARY, and TEMP.
Grant usage/select to a single table
If you only grant CONNECT to a database, the user can connect but has no other privileges. You have to grant USAGE on namespaces (schemas) and SELECT on tables and views individually like so:
GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;
Multiple tables/views (PostgreSQL 9.0+)
In the latest versions of PostgreSQL, you can grant permissions on all tables/views/etc in the schema using a single command rather than having to type them one by one:
GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;
This only affects tables that have already been created. More powerfully, you can automatically have default roles assigned to new objects in future:
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO xxx;
Note that by default this will only affect objects (tables) created by the user that issued this command: although it can also be set on any role that the issuing user is a member of. However, you don't pick up default privileges for all roles you're a member of when creating new objects... so there's still some faffing around. If you adopt the approach that a database has an owning role, and schema changes are performed as that owning role, then you should assign default privileges to that owning role. IMHO this is all a bit confusing and you may need to experiment to come up with a functional workflow.
Multiple tables/views (PostgreSQL versions before 9.0)
To avoid errors in lengthy, multi-table changes, it is recommended to use the following 'automatic' process to generate the required GRANT SELECT to each table/view:
SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');
This should output the relevant GRANT commands to GRANT SELECT on all tables, views, and sequences in public, for copy-n-paste love. Naturally, this will only be applied to tables that have already been created.
Reference taken from this blog:
Script to Create Read-Only user:
CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234'
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';
\connect YourDatabaseName;
Assign permission to this read-only user:
GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
Assign permissions to read all newly tables created in the future
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;
From PostgreSQL v14 on, you can do that simply by granting the predefined pg_read_all_data role:
GRANT pg_read_all_data TO xxx;
Do note that PostgreSQL 9.0 (today in beta testing) will have a simple way to do that:
test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
Here is the best way I've found to add read-only users (using PostgreSQL 9.0 or newer):
$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
Then log in to all related machines (master + read-slave(s)/hot-standby(s), etc..) and run:
$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload
By default new users will have permission to create tables. If you are planning to create a read-only user, this is probably not what you want.
To create a true read-only user with PostgreSQL 9.0+, run the following steps:
# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;
# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;
# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;
If your read-only user doesn't have permission to list tables (i.e. \d returns no results), it's probably because you don't have USAGE permissions for the schema. USAGE is a permission that allows users to actually use the permissions they have been assigned. What's the point of this? I'm not sure. To fix:
# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;
# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;
I’ve created a convenient script for that; pg_grant_read_to_db.sh. This script grants read-only privileges to a specified role on all tables, views and sequences in a database schema and sets them as default.
I read trough all the possible solutions, which are all fine, if you remember to connect to the database before you grant the things ;) Thanks anyway to all other solutions!!!
user#server:~$ sudo su - postgres
create psql user:
postgres#server:~$ createuser --interactive
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
start psql cli and set a password for the created user:
postgres#server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.
postgres=# alter user readonly with password 'readonly';
ALTER ROLE
connect to the target database:
postgres=# \c target_database
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".
grant all the needed privileges:
target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT
target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT
target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT
alter default privileges for targets db public shema:
target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES
If your database is in the public schema, it is easy (this assumes you have already created the readonlyuser)
db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT
If your database is using customschema, execute the above but add one more command:
db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE
The not straightforward way of doing it would be granting select on each table of the database:
postgres=# grant select on db_name.table_name to read_only_user;
You could automate that by generating your grant statements from the database metadata.
Taken from a link posted in response to despesz' link.
Postgres 9.x appears to have the capability to do what is requested. See the Grant On Database Objects paragraph of:
http://www.postgresql.org/docs/current/interactive/sql-grant.html
Where it says: "There is also an option to grant privileges on all objects of the same type within one or more schemas. This functionality is currently supported only for tables, sequences, and functions (but note that ALL TABLES is considered to include views and foreign tables)."
This page also discusses use of ROLEs and a PRIVILEGE called "ALL PRIVILEGES".
Also present is information about how GRANT functionalities compare to SQL standards.
CREATE USER username SUPERUSER password 'userpass';
ALTER USER username set default_transaction_read_only = on;