如何查看某个角色的所有数据库和对象授权?

How can I review all database and object grants for a role?

我正在尝试在发布前审核应用程序的所有权限,并且我想确保没有任何角色拥有超过其需要的访问权限。我看过不同的函数和系统表,但一切都很零碎。

是否有好的查询或方法能够转储特定角色拥有的每项授权?

我正在使用 pg 9.5。

系统目录pg_class的第relacl列包含所有权限信息。

模式 public 中的示例数据由 postgres 拥有并授予 newuser

create table test(id int);
create view test_view as select * from test;

grant select, insert, update on test to newuser;
grant select on test_view to newuser;

正在查询 pg_class:

select 
    relname, 
    relkind, 
    coalesce(nullif(s[1], ''), 'public') as grantee, 
    s[2] as privileges
from 
    pg_class c
    join pg_namespace n on n.oid = relnamespace
    join pg_roles r on r.oid = relowner,
    unnest(coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)::text[])) acl, 
    regexp_split_to_array(acl, '=|/') s
where nspname = 'public'
and relname like 'test%';

  relname  | relkind | grantee  | privileges 
-----------+---------+----------+------------
 test      | r       | postgres | arwdDxt      <- owner postgres has all privileges on the table
 test      | r       | newuser  | arw          <- newuser has append/read/write privileges
 test_view | v       | postgres | arwdDxt      <- owner postgres has all privileges on the view
 test_view | v       | newuser  | r            <- newuser has read privilege
(4 rows)

评论:

  • coalesce(relacl::text[], format('{%s=arwdDxt/%s}', rolname, rolname)) - relacl 中为空表示所有者拥有所有权限;
  • unnest(...) acl - relaclaclitem的数组,一个数组元素为一个用户;
  • regexp_split_to_array(acl, '=|/') s - 拆分 aclitem 为:s[1] 用户名,s[2] 权限;
  • coalesce(nullif(s[1], ''), 'public') as grantee - 空用户名表示 public.

将查询修改为 select 个人用户或特定类型的关系或其他模式等...

阅读文档:

以类似的方式,您可以获得有关授予模式的权限的信息(nspacl in pg_namespace) and databases (datacl in pg_database 列)

relacl 列(以及 aclitem 类型的其他列)不必解析为文本。 函数 aclexplode 取消嵌套数组,使其适合横向连接。结果是具有良好命名字段的记录,只需将 oid 转换为人类可读的名称:

select c.*, n.nspname,
  acl.grantor, acl.grantee,
  pg_catalog.pg_get_userbyid(acl.grantor), pg_catalog.pg_get_userbyid(acl.grantee),
  acl.privilege_type, acl.is_grantable
from pg_catalog.pg_class c
join pg_catalog.pg_namespace n on n.oid = c.relnamespace,
lateral aclexplode(c.relacl) acl;