postgresql - view schema privileges
是否可以运行查询以显示特定模式上当前分配的特权?
即按以下方式分配的特权:
1 | GRANT USAGE ON SCHEMA dbo TO MyUser |
我试过了
1 2 | SELECT * FROM information_schema.usage_privileges; |
但这只会将授予返回给内置PUBLIC角色。 相反,我想查看哪些用户已获得各种架构的特权。
注意:我实际上使用的是Amazon Redshift而不是纯PostgreSQL,但如果在Amazon Redshift中无法做到这一点,我将接受纯PostgreSQL答案。 (尽管我怀疑是这样)
在控制台util psql中:
1 | \dn+ |
会告诉你
1 | Name | Owner | Access privileges | Description |
列出当前用户的所有模式及其特权:
1 2 3 4 5 6 7 8 9 | 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"; |
响应将例如:
1 2 3 4 5 6 | name | CREATE | usage ---------+--------+------- public | t | t test | t | t awesome | f | f (3 ROWS) |
在此示例中,当前用户不是
您可能会猜到,对特定架构的类似要求:
1 2 3 4 5 | SELECT pg_catalog.has_schema_privilege( CURRENT_USER, 'awesome', 'CREATE') AS"create", pg_catalog.has_schema_privilege( CURRENT_USER, 'awesome', 'USAGE') AS"usage"; |
和回应:
1 2 3 | CREATE | usage --------+------- f | f |
如您所知,对于当前模式可以使用
在所有可能的特权中
1 2 3 4 5 6 7 8 9 10 11 12 | -- SELECT -- INSERT -- UPDATE -- DELETE -- TRUNCATE -- REFERENCES -- TRIGGER -- CREATE -- CONNECT -- TEMP -- EXECUTE -- USAGE |
模式仅允许使用
像
带
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |系统信息功能|授予(特权)
特权存储在pg_namespace的nspacl字段中。由于它是一个数组字段,因此您必须进行一些精美的编码才能对其进行解析。此查询将为您提供用于用户和组的Grant语句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 |
这就是psql在内部使用的内容:)
1 2 3 4 5 6 7 8 | SELECT n.nspname AS"Name", pg_catalog.pg_get_userbyid(n.nspowner) AS"Owner", pg_catalog.array_to_string(n.nspacl, E' ') AS"Access privileges", pg_catalog.obj_description(n.oid, 'pg_namespace') AS"Description" FROM pg_catalog.pg_namespace n WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema' ORDER BY 1; |
尝试以下一项(适用于PUBLIC角色):
1 2 3 4 5 6 7 8 9 10 | SELECT nspname, COALESCE(NULLIF(ROLE.name,''), 'PUBLIC') AS name, SUBSTRING( CASE WHEN POSITION('U' IN split_part(split_part((','||array_to_string(nspacl,',')), ','||ROLE.name||'=',2 ) ,'/',1)) > 0 THEN ', USAGE' ELSE '' END || CASE WHEN POSITION('C' IN split_part(split_part((','||array_to_string(nspacl,',')), ','||ROLE.name||'=',2 ) ,'/',1)) > 0 THEN ', CREATE' ELSE '' END , 3,10000) AS privileges FROM pg_namespace pn, (SELECT pg_roles.rolname AS name FROM pg_roles UNION ALL SELECT '' AS name) AS ROLE WHERE (','||array_to_string(nspacl,',')) LIKE '%,'||ROLE.name||'=%' AND nspowner > 1; |
适用于AWS Redshift的组合版本(组,用户,PUBLIC):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | SELECT * FROM (SELECT 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 AS rights, nspname AS schema, '' AS ROLE, pu.usename AS USER FROM pg_namespace pn, pg_user pu WHERE ARRAY_TO_STRING(nspacl,',') LIKE '%' ||pu.usename|| '%' --and pu.usename='<username>' AND nspowner > 1 UNION SELECT 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 AS rights, nspname AS schema, pg.groname AS ROLE, '' AS USER FROM pg_namespace pn, pg_group pg WHERE ARRAY_TO_STRING(nspacl,',') LIKE '%' ||pg.groname|| '%' --and pg.groname='<username>' AND nspowner > 1 UNION SELECT CASE WHEN POSITION('U' IN SPLIT_PART(SPLIT_PART((',' ||array_to_string (nspacl,',')),',' ||roles.name|| '=',2),'/',1)) > 0 THEN ' USAGE' ELSE '' END || CASE WHEN POSITION('C' IN SPLIT_PART(SPLIT_PART((',' ||array_to_string (nspacl,',')),',' ||roles.name|| '=',2),'/',1)) > 0 THEN ' CREATE' ELSE '' END AS rights, nspname AS schema, COALESCE(NULLIF(roles.name,''),'PUBLIC') AS ROLE, '' AS USER FROM pg_namespace pn, (SELECT pg_group.groname AS name FROM pg_group UNION ALL SELECT '' AS name) AS roles WHERE (',' ||array_to_string (nspacl,',')) LIKE '%,' ||roles.name|| '=%' AND nspowner > 1) privs ORDER BY schema,rights |
对于当前问题,可以尝试以下方法:
1 2 3 4 5 6 7 8 9 10 | SELECT r.rolname AS role_name, n.nspname AS schema_name, p.perm AS privilege FROM pg_catalog.pg_namespace AS n CROSS JOIN pg_catalog.pg_roles AS r CROSS JOIN (VALUES ('USAGE'), ('CREATE')) AS p(perm) WHERE has_schema_privilege(r.oid, n.oid, p.perm) -- AND n.nspname <> 'information_schema' -- AND n.nspname !~~ 'pg\_%' -- AND NOT r.rolsuper |
在我遇到过很多对象和用户的数据库上,性能可能会很低。所以我有使用
1 2 3 4 5 6 7 8 9 | SELECT oid_to_rolname(a.grantee) AS role_name, n.nspname AS schema_name, a.privilege_type AS privilege_type FROM pg_catalog.pg_namespace AS n, aclexplode(nspacl) a WHERE n.nspacl IS NOT NULL AND oid_to_rolname(a.grantee) IS NOT NULL -- AND n.nspname <> 'information_schema' -- AND n.nspname !~~ 'pg\_%' |
但是请注意,最后一个不包括用户从
其中
并且,像@Jaisus一样,我的任务要求拥有所有用户所拥有的所有特权。所以我对
此外,还有一个有用的扩展
我知道这篇文章很旧,但是我根据不同的答案又做了一个查询,以使查询简短易懂。
1 2 3 4 5 6 7 8 | SELECT nspname AS schema_name , r.rolname AS role_name , pg_catalog.has_schema_privilege(r.rolname, nspname, 'CREATE') AS create_grant , pg_catalog.has_schema_privilege(r.rolname, nspname, 'USAGE') AS usage_grant FROM pg_namespace pn,pg_catalog.pg_roles r WHERE array_to_string(nspacl,',') LIKE '%'||r.rolname||'%' AND nspowner > 1 |
我一直在想,有一天我会查询仅在一个视图中拥有所有权利。 ;)