Is there a query I can run to show currently assigned privileges on a particular schema?
i.e. privileges that were assigned like so:
GRANT USAGE ON SCHEMA dbo TO MyUser
I have tried
SELECT *
FROM information_schema.usage_privileges;
but this only returns grants to the built-in PUBLIC role. Instead, I want to see which users have been granted privileges on the various schema.
Note: I'm actually using Amazon Redshift rather than pure PostgreSQL, although I will accept a pure PostgreSQL answer if this is not possible in Amazon Redshift. (Though I suspect it is)
select * from dba_role_privs where grantee = 'SCHEMA_NAME'; All the role granted to the schema will be listed.
Another way to do this is to use the information_schema schema and query the table_privileges table as: $ SELECT * FROM information_schema. table_privileges LIMIT 5; The above query will show detailed information about user privileges on databases as well as tables.
Interestingly, the solution was quite simple: select tablename, tableowner from pg_catalog. pg_tables where schemaname = 'public' ; All of the schemas in our db are the default public , so to eliminate some of the tables Postgres provides, I included that filter.
in console util psql:
\dn+
will show you
Name | Owner | Access privileges | Description
List all schemas with their priveleges for current user:
WITH "names"("name") AS (
SELECT n.nspname AS "name"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_'
AND n.nspname <> 'information_schema'
) SELECT "name",
pg_catalog.has_schema_privilege(current_user, "name", 'CREATE') AS "create",
pg_catalog.has_schema_privilege(current_user, "name", 'USAGE') AS "usage"
FROM "names";
The response will be for example:
name | create | usage
---------+--------+-------
public | t | t
test | t | t
awesome | f | f
(3 rows)
In this example current user is not owner of the awesome
schema.
As you could guess, similar request for particular schema:
SELECT
pg_catalog.has_schema_privilege(
current_user, 'awesome', 'CREATE') AS "create",
pg_catalog.has_schema_privilege(
current_user, 'awesome', 'USAGE') AS "usage";
and response:
create | usage
--------+-------
f | f
As you know, it's possible to use pg_catalog.current_schema()
for current schema.
Of all the possible privileges
-- SELECT
-- INSERT
-- UPDATE
-- DELETE
-- TRUNCATE
-- REFERENCES
-- TRIGGER
-- CREATE
-- CONNECT
-- TEMP
-- EXECUTE
-- USAGE
the only CREATE
and USAGE
allowed for schemas.
Like the current_schema()
the current_user
can be replaced with particular role.
BONUS with current
column
WITH "names"("name") AS (
SELECT n.nspname AS "name"
FROM pg_catalog.pg_namespace n
WHERE n.nspname !~ '^pg_'
AND n.nspname <> 'information_schema'
) SELECT "name",
pg_catalog.has_schema_privilege(current_user, "name", 'CREATE') AS "create",
pg_catalog.has_schema_privilege(current_user, "name", 'USAGE') AS "usage",
"name" = pg_catalog.current_schema() AS "current"
FROM "names";
-- name | create | usage | current
-- ---------+--------+-------+---------
-- public | t | t | t
-- test | t | t | f
-- awesome | f | f | f
-- (3 rows)
WITH | System Information Functions | GRANT (privileges)
The privileges are stored in the nspacl field of pg_namespace. Since it's an array field, you have to do a little fancy coding to parse it. This query will give you the grant statements used for users and groups:
select
'grant ' || substring(
case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end
, 2,10000)
|| ' on schema '||nspname||' to "'||pu.usename||'";'
from pg_namespace pn,pg_user pu
where array_to_string(nspacl,',') like '%'||pu.usename||'%' --and pu.usename='<username>'
and nspowner > 1
union
select
'grant ' || substring(
case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pg.groname,2 ) ,'/',1)) > 0 then ',usage ' else '' end
||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pg.groname,2 ) ,'/',1)) > 0 then ',create ' else '' end
, 2,10000)
|| ' on schema '||nspname||' to group "'||pg.groname||'";'
from pg_namespace pn,pg_group pg
where array_to_string(nspacl,',') like '%'||pg.groname||'%' --and pg.groname='<username>'
and nspowner > 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With