PostgreSQL: How to view current "grant usage on schema" permissions? - postgresql

Is there a system view in Postgres where I can see which users/roles have "grant usage" and on which schema?

The grants are stored in ACLs (=Access Control Lists) for each schema. You can view them by looking a pg_namespace
select nspname, nspacl
from pg_namespace
The format of the acl is explained in the manual

Related

Why can't I see user privileges in postgresql?

I am using PostgreSQL 11.8 in AWS RDS and I created a user as below:
CREATE USER test WITH LOGIN;
GRANT rds_iam TO test;
the code runs success but I can't find the user test from:
SELECT * FROM information_schema.table_privileges where grantee='test';
it returns an empty result to me.
I am able to see that user by running
SELECT *FROM pg_catalog.pg_user where usename='test';.
Why can't I grant access to the user?
Your GRANT statement didn't grant a privilege on a table, it added the user to the role (“group”) rds_iam.
User test itself doesn't have any privileges on tables, it only inherits them.
information_schema.table_privileges will only show the privileges that were granted to a user, not the privileges inherited via role membership.
Your SQL command is correct. The problem is on the given role_name. You can get all users by executing the below command
SELECT *FROM pg_catalog.pg_user
Make sure the given role_name is in the listed role name in the PostgreSQL server. Below the command, you can get users with role
SELECT usename AS role_name,
CASE
WHEN usesuper AND usecreatedb THEN
CAST('superuser, create database' AS pg_catalog.text)
WHEN usesuper THEN
CAST('superuser' AS pg_catalog.text)
WHEN usecreatedb THEN
CAST('create database' AS pg_catalog.text)
ELSE
CAST('' AS pg_catalog.text)
END role_attributes
FROM pg_catalog.pg_user
ORDER BY role_name desc;
In PostgreSQL RDS I seen this behavior, where "information_schema.table_privileges" is not getting updated with privileges which granted to any user or role If the table owner is not "dbuser".
So I changed the table owner to "dbuser" immediately it's started showing all the grants which I granted to different users and roles. Not sure how the "Table owner" impacting "table_privileges" view.

Permission uncertainty in Greenplum

I am using Greenplum 6.8(Postgres 9.4) open source, I created role that have all permission on a schema, after assigning that role to user I added a new table in schema but user is not able to access that table. I have to refresh my role definition to access that new table, role definition is like below:
grant usage on schema <schema_name> to <rolename>;
grant select on all tables in schema <schema_name> to <rolename>;
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema_name> GRANT SELECT ON TABLES TO <rolename>;
In MySQL, there is a flag in its configuration automatic_sp_privileges; however I am also looking for same in Greenplum.

Select databases for current role as non superuser

Postgresql 9.1
I have a multi-tenant solution where one or more database are owned by a role (tenant).
When logging in as a superuser this works:
SELECT datname FROM pg_database
JOIN pg_authid ON pg_database.datdba = pg_authid.oid
WHERE rolname = current_user
But logging in as a tenant I get an error: permission denied for pg_autid
The tenant is created as this:
CREATE ROLE 'tenant1' WITH PASSWORD '12345' LOGIN
Strange the tenant1 could however see all other databases:
SELECT datname FROM pg_database
My questions are:
How do I list all databases belonging to a certain tenant in a safe way?
Is there a better way to make this multi-tenant solution safer?
I know that I can login as superuser, list the database for a tenant and then logging in as tenant. But I am searching for a simpler solution. Some data is obviously accessible as a restricted tenant as I can list all pg_database.
I have searched all archives but not finding any applicable solution.
Thanks in advance for any clue!
The function pg_get_userbyid() should be accessible to every user:
SELECT datname
FROM pg_database
WHERE pg_get_userbyid(datdba) = current_user

PostgreSQL: View database connect permissions

How do you view users that have been issued GRANT CONNECT ON DATABASE <database> TO <user>?
\dp - lists table/view permissions
\dn+ - lists schema permissions
\l+ does not list all users that can access the database
A bit odd if the \l+ command just displays some of the users that have permission/privilege to connect to the database. I could not repeat that myself on a PostgreSQL 8.4 installation (Ubuntu 10.04 LTS). What version are you using?
Anyway, perhaps you could check the table holding the ACL's for that particular database and from that deduce whether the user has the correct privileges or not:
SELECT datname as "Relation", datacl as "Access permissions" FROM pg_database WHERE datname = 'databasename';
If you just want to check one user you could do something like this:
SELECT * FROM has_database_privilege('username', 'database', 'connect');
How are the permissions/privileges to interpreted? The privileges are to be read like this:
user = privileges / granted by
Omitting user means that PUBLIC is granted the privilege, ie all roles. For example if the privilege is =Tc/postgres then all roles may connect and create temporary tables in that particular database and it is the postgres user who granted the privilege.
There is a synopsis at the PostgreSQL site explaining the different privileges: https://www.postgresql.org/docs/current/ddl-priv.html#PRIVILEGE-ABBREVS-TABLE.
rolename=xxxx -- privileges granted to a role
=xxxx -- privileges granted to PUBLIC
r -- SELECT ("read")
w -- UPDATE ("write")
a -- INSERT ("append")
d -- DELETE
D -- TRUNCATE
x -- REFERENCES
t -- TRIGGER
X -- EXECUTE
U -- USAGE
C -- CREATE
c -- CONNECT
T -- TEMPORARY
arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
* -- grant option for preceding privilege
/yyyy -- role that granted this privilege
I'm using psql from postgres 8.4 and postgres 9.0, and the command \l or \l+ gives me column Access Privileges where I have entry:
<user_name>=c/<database_name>
and earlier I gave the user the connect privilege as you wanted.
As it states on the page http://www.postgresql.org/docs/9.0/static/sql-grant.html, the c letter here means Connect.

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;