【发布时间】:2020-01-30 05:58:05
【问题描述】:
我想编写一个查询,为每个用户转储针对到达表的权限。进行此搜索的原因是我可以对表权限进行快照,然后在服务器之间或在运行大型 GRANTS 重置脚本之前和之后比较它们。我正在寻找易于比较的输出,所以是这样的:
schema_name table_name qualified_name owner_name privilege setting
api base4 api.base4 postgres delete TRUE
api bucket_test api.bucket_test postgres delete TRUE
我已经编写了一个查询,可以让我了解其中的一部分,但权限名称和设置是列对。我可以通过在特权之后命名它们来将列切成两半,但我遵循上面的窄行格式。这使得我将比较细化到表+用户+权限。
schema_name table_name qualified_name owner_name privilege delete privilege insert privilege references privilege setting privilege trigger privilege truncate privilege update
api base4 api.base4 postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
api bucket_test api.bucket_test postgres delete TRUE insert TRUE references TRUE select TRUE trigger TRUE truncate TRUE update TRUE
有人可以建议正确的 join 或 unnest+join 来修改我现在的查询吗?
而且,是的,这个查询会生成很多结果行。没关系,这就是我所追求的。
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
quote_ident(schemaname) || '.' || quote_ident(tablename) as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select table_list.schema_name,
table_list.table_name,
table_list.qualified_name,
table_list.owner_name,
'delete' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'delete') as delete,
'insert' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'insert') as insert,
'references' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'references') as references,
'select' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'select') as select,
'trigger' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'trigger') as trigger,
'truncate' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'truncate') as truncate,
'update' as privilege, has_table_privilege(user_list.user_name, concat(table_list.qualified_name), 'update') as update
from table_list
cross join user_list
我在 RDS 上使用 Postgres 11.4。
跟进
对于以后发现此问题的任何人,以下是最终查询的一个版本作为视图:
DROP VIEW IF EXISTS data.table_grants;
CREATE OR REPLACE VIEW data.table_grants AS
with
table_list as
( select schemaname as schema_name,
tablename as table_name,
schemaname::text || '.' || tablename::text as qualified_name,
tableowner as owner_name
from pg_tables
where schemaname in ('data','api')
order by 3),
user_list as
( select usename as user_name
from pg_user
order by 1)
select
table_list.*,
user_list.user_name,
privilege,
has_table_privilege(user_name, qualified_name, privilege) as setting
from
table_list
cross join user_list
cross join (values
('delete'), ('insert'), ('references'), ('select'), ('trigger'), ('truncate'), ('update')
) as p(privilege);
ALTER TABLE data.table_grants
OWNER TO user_change_structure;
这使得对表授权的搜索更简单一些,例如查看在名为item 的表上授予的权限
select *
from table_grants
where table_name = 'item'
order by user_name,
privilege;
或者这个查询来获取特定表上用户权限的汇总视图:
select qualified_name,
owner_name,
user_name,
array_agg(privilege) as rights
from table_grants
where table_name = 'item' and
setting = true
group by qualified_name,
owner_name,
user_name;
上面的查询不一定是最有效的,并且视图的产品是表 * 用户 * 8...但对于我来说,这一切都是即时的,只有不到 100 个表和大约 15 个角色。
【问题讨论】:
-
也许引入一个具有所有权限的第三个“表”(使用
VALUES)并加入这个?还有你对has_table_privilege()的调用都是搜索选择权限,我猜这个错误会在使用加入不同权限的方法时看到。 -
感谢 VALUES 的建议,我得看看……不是我知道的功能。感谢发现 has_table_privilege 调用中的错误。我已经修复了原始答案中的代码。
-
顺便说一句,为了构建你的
qualified_name,我强烈建议在这两个部分上使用quote_ident。 -
@Bergi:感谢您的更正,我已经进行了编辑。我意识到我一直在函数中使用 regclass 参数而不是 quote_ident....但是 Postgres 中没有参数化视图。修改后的版本好看吗?
-
@MorrisdeOryx 是的,我就是这个意思
标签: postgresql grant