在 postgres 中查询表的授权

Posted

技术标签:

【中文标题】在 postgres 中查询表的授权【英文标题】:Query grants for a table in postgres 【发布时间】:2011-11-12 06:41:54 【问题描述】:

如何在 postgres 中查询授予对象的所有 GRANTS?

例如我有表“mytable”:

GRANT SELECT, INSERT ON mytable TO user1
GRANT UPDATE ON mytable TO user2 

我需要一些能给我的东西:

user1: SELECT, INSERT
user2: UPDATE

【问题讨论】:

【参考方案1】:

下面的查询将为您提供所有用户的列表以及他们对架构中表的权限。

select a.schemaname, a.tablename, b.usename,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'select') as has_select,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'insert') as has_insert,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'update') as has_update,
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'delete') as has_delete, 
  HAS_TABLE_PRIVILEGE(usename, quote_ident(schemaname) || '.' || quote_ident(tablename), 'references') as has_references 
from pg_tables a, pg_user b 
where a.schemaname = 'your_schema_name' and a.tablename='your_table_name';

更多关于has_table_privilages的信息请见here。

【讨论】:

这是这里唯一计算从其他角色的成员资格获得的权限的答案,所以它得到了我的投票。另一方面,我会说has_table_privilege(usename, contact(schemaname, '.', tablename), ...) 以避免歧义。 加一 - 这是纯金!【参考方案2】:

添加到@shruti 的答案

为给定用户查询架构中所有表的授权

select a.tablename, 
       b.usename, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'select') as select,
       HAS_TABLE_PRIVILEGE(usename,tablename, 'insert') as insert, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'update') as update, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'delete') as delete, 
       HAS_TABLE_PRIVILEGE(usename,tablename, 'references') as references 
from pg_tables a, 
     pg_user b 
where schemaname='your_schema_name' 
      and b.usename='your_user_name' 
order by tablename;

【讨论】:

这很好用,假设您以具有适当权限的用户身份登录。 Nitpick:我建议应该明确编写交叉连接,例如FROM pg_tables AS a CROSS JOIN pg_user AS b 而不是 SQL 92 使用逗号 from pg_tables a, pg_user b 的方式【参考方案3】:

此查询将列出所有数据库和架构中的所有表(取消注释 WHERE 子句中的行以过滤特定数据库、架构或表),并按顺序显示权限很容易看出是否授予了特定特权:

SELECT grantee
      ,table_catalog
      ,table_schema
      ,table_name
      ,string_agg(privilege_type, ', ' ORDER BY privilege_type) AS privileges
FROM information_schema.role_table_grants 
WHERE grantee != 'postgres' 
--  and table_catalog = 'somedatabase' /* uncomment line to filter database */
--  and table_schema  = 'someschema'   /* uncomment line to filter schema  */
--  and table_name    = 'sometable'    /* uncomment line to filter table  */
GROUP BY 1, 2, 3, 4;

样本输出:

grantee |table_catalog   |table_schema  |table_name     |privileges     |
--------|----------------|--------------|---------------|---------------|
PUBLIC  |adventure_works |pg_catalog    |pg_sequence    |SELECT         |
PUBLIC  |adventure_works |pg_catalog    |pg_sequences   |SELECT         |
PUBLIC  |adventure_works |pg_catalog    |pg_settings    |SELECT, UPDATE |
...

【讨论】:

这只会给出与执行它的用户匹配的行......不是所有的授权【参考方案4】:

这是一个为特定表生成授权查询的脚本。它省略了所有者的权限。

SELECT 
    format (
      'GRANT %s ON TABLE %I.%I TO %I%s;',
      string_agg(tg.privilege_type, ', '),
      tg.table_schema,
      tg.table_name,
      tg.grantee,
      CASE
        WHEN tg.is_grantable = 'YES' 
        THEN ' WITH GRANT OPTION' 
        ELSE '' 
      END
    )
  FROM information_schema.role_table_grants tg
  JOIN pg_tables t ON t.schemaname = tg.table_schema AND t.tablename = tg.table_name
  WHERE
    tg.table_schema = 'myschema' AND
    tg.table_name='mytable' AND
    t.tableowner <> tg.grantee
  GROUP BY tg.table_schema, tg.table_name, tg.grantee, tg.is_grantable;

【讨论】:

【参考方案5】:

如果你真的想要每个用户一行,你可以按被授权者分组(string_agg 需要 PG9+)

SELECT grantee, string_agg(privilege_type, ', ') AS privileges
FROM information_schema.role_table_grants 
WHERE table_name='mytable'   
GROUP BY grantee;

这应该输出类似:

 grantee |   privileges   
---------+----------------
 user1   | INSERT, SELECT
 user2   | UPDATE
(2 rows)

【讨论】:

几乎是我想要的,我可以得到准确的GRANTs 像 pg_dump 输出吗?【参考方案6】:

我已经找到了:

SELECT grantee, privilege_type 
FROM information_schema.role_table_grants 
WHERE table_name='mytable'

【讨论】:

【参考方案7】:

来自 psql 的\z mytable 为您提供表中的所有授权,但您必须按单个用户将其拆分。

【讨论】:

你会直接从 sql 窗格或 pg 命令行运行它吗? @DanielL.VanDenBosch:所有元命令,如\z,都用于 psql。 psql 是 PostgreSQL 的命令行界面。

以上是关于在 postgres 中查询表的授权的主要内容,如果未能解决你的问题,请参考以下文章

哪个 postgres 系统表存储 PID 到会话授权的映射?

Postgres:即使授予了授权,也拒绝架构的权限

UnauthorizedError:没有授权令牌——EC2/RDS Postgres

在 postgres 中查询文本数组

防止在 Postgres 中为特定查询使用索引

Postgres如何创建一个在查询中使用的函数