检索特定角色的所有对象权限

时间:2014-03-11 02:02:41

标签: postgresql

是否有一种简单的方法可以枚举特定角色具有某些访问权限的所有对象?我知道pg_catalog中的has_*_privilege函数集,但它们不能完成这项工作,我想反过来工作。实际上,我希望有一个视图,为特定角色的pg_class中存储的任何内容提供oid和访问权限。

这样的视图非常便于检查数据库的安全性是否正确设置。通常,角色的关系远远少于关系,因此检查角色的麻烦要少得多。这样的实用程序是否应该在标准PostgreSQL发行版中不可用?

根据源代码(acl.h),aclitem是一个结构:

typedef struct AclItem
{ Oid         ai_grantee;     /* ID that this item grants privs to */
  Oid         ai_grantor;     /* grantor of privs */
  AclMode     ai_privs;       /* privilege bits */
} AclItem;

易于使用。但是,pg_type将其列为用户定义的非复合类型。这是为什么?我现在看到的唯一方法是使用字符串函数解析aclitem []数组。有没有更好的方法来分析aclitem数组?

添加了信息 通过各种PG列表进行拖拽,显然这个问题至少从1997年开始以各种形式出现(我们当时有电脑吗?是电视吗?),最相关的讨论主题是“二进制输入/输出为aclitem”在2011年初的pgsql-hackers上。作为PG技术熟练的用户 - 而不是黑客 - 我很欣赏开发人员对维护稳定界面的关注,但是线程中表达的一些担忧有点远。我的口味。什么是在系统目录中没有pg_acl表的真正原因,其定义等于源代码中的AclItem结构?该结构何时发生变化?我也意识到SE的发展很可能会改变安全性的处理方式 - 当用户选择的时候 - 大概是 - 所以我会满足于提供acl信息的东西,以便很容易枚举授予的权限特定用户,例如:

SELECT * FROM pg_privileges WHERE grantee = 16384;

就像这样,它仍然可以是底层结构的抽象,因此引擎盖下的任何变化都可能(可能)仍然被转换为暴露的界面。我会说,与information_schema方法没有什么不同。

干杯, 帕特里克

2 个答案:

答案 0 :(得分:16)

没有开箱即用的视图,但创建它所需的数据在系统目录中:

http://www.postgresql.org/docs/current/static/catalogs.html

例如,relacl中有一个pg_class字段:

select oid::regclass, relacl from pg_class;

其他目录中也有类似的字段,typacl中的pg_typeproacl中的pg_proc

您可能希望使用另外两个目录,即pg_authid来了解哪些角色具有超级用户权限,以及pg_auth_members以了解谁具有哪个角色。

pg_default_acl仅在对象创建期间使用,因此无用。)

有一些与aclitem相关的内部函数可能会在创建视图时派上用场。您可以像psql一样列出它们:

\df+ *acl*

特别是aclexplode()。以下示例有望让您入门:

select oid::regclass,
       (aclexplode(relacl)).grantor,
       (aclexplode(relacl)).grantee,
       (aclexplode(relacl)).privilege_type,
       (aclexplode(relacl)).is_grantable
from pg_class
where relacl is not null;

可以通过首先扩展acl行来优化它,例如:

select oid::regclass,
       aclitem.grantee
from (select oid, aclexplode(relacl) as aclitem from pg_class) sub

它将引导您直接达到预期的效果。

就我所知,这与它使用内置工具一样好。 (当然,如果您想尝试进一步优化此操作符,您可以在C中编写自己的一组运算符。)

关于你的额外问题,我担心他们只能由世界上的少数人(也就是核心开发者自己)来回答。他们比在这里更频繁地登上pg黑客名单。

答案 1 :(得分:1)

可能不是最好/最有效的方式,但它对我有很大的帮助!我在需要删除角色和出错时遇到了这个问题。

TilePane

您可以将其用作

ERROR:  role ROLE_NAME cannot be dropped because some objects depend on it

代码如下。我不包括" system"对象(来自pg_catalog和information_schema),如果要枚举它们,可以从查询中取出条件。

SELECT * FROM upg_roles_privs WHERE grantee = 'testuser'