【问题标题】:How to find the privileges granted to a user in AWS Redshift?如何在 AWS Redshift 中查找授予用户的权限?
【发布时间】:2014-03-02 13:57:19
【问题描述】:

我正在使用 Redshift 集群。

版本:

PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.735

我只需要删除一个用户,但它给出了以下错误消息:

redshiftpocdb=# drop user test_55;
ERROR:  user "test_55" cannot be dropped because the user has a privilege on some object

这是\dp 命令的输出:

redshiftpocdb=# \dp
              Access privileges
 schema |  name   | type  | access privileges
--------+---------+-------+-------------------
 public | company | table |
 public | test2   | table |
 public | test22  | table |
 public | test222 | table |
 public | v_date  | table |
(5 rows)

在 Postgresql 环境中,我们有命令 DROP OWNED BY,但它在 Redshift 中不起作用。

我怎样才能知道TEST_55 用户被授予了哪些权限?有没有我们可以查询的系统视图(例如,在 Oracle 中,我们有 DBA_ROLE_PRIVS、DBA_TAB_PRIVS...DBA_SYS_PRIVS .etc)?

【问题讨论】:

标签: amazon-redshift


【解决方案1】:

我不得不使用 ||连接字符串,有点不同,因为我有区分大小写的对象名称 '"' || 模式名 || '"."' || 表名 || '"' AS fullobj '"' || schemaname || '"."' || viewname || '"' AS fullobj

而不是 模式名 + '.' + 表名 AS fullobj 模式名 + '.' + viewname AS fullobj

【讨论】:

    【解决方案2】:

    另一个变体,将所有用户的权限组织在一起:

    WITH 
    usrs as (SELECT * FROM pg_user),
    objs as (
      SELECT 
        schemaname, 't' AS obj_type,
        tablename AS objectname,
        schemaname + '.' + tablename AS fullobj
      FROM pg_tables
      WHERE schemaname not in ('pg_internal')
      UNION
      SELECT 
        schemaname, 'v' AS obj_type, 
        viewname AS objectname, 
        schemaname + '.' + viewname AS fullobj 
      FROM pg_views
      WHERE schemaname NOT IN ('pg_internal')
    ),
    query as (
      SELECT 
        schemaname,
        objectname,
        usename,
        HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AS sel,
        HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AS ins,
        HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AS upd,
        HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AS del,
        HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AS ref
      FROM objs, usrs
      ORDER BY fullobj
    )
    SELECT * FROM query
    WHERE (
      sel = TRUE 
      OR ins = TRUE 
      OR upd = TRUE 
      OR del = TRUE 
      OR ref = TRUE
    ) AND schemaname='[optional schemaname]'
      AND usename = '[optional username]';
    

    【讨论】:

      【解决方案3】:

      为了能够删除用户,您必须(至少)

      • 如果他们拥有任何对象,请将所有者更改为其他用户
      • 从任何对象中删除授权
      • 从组中删除他们
      • 从架构中移除授权

      您可以使用它来查找他们拥有的任何表(然后运行“将表所有者更改为”):

      select * from pg_tables where tableowner = 'test_55'
      

      您可以使用它来构建脚本以撤销任何授权:

      select relacl , 
      'revoke ' || substring(
                  case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',select ' else '' end 
                ||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',update ' else '' end 
                ||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',insert ' else '' end 
                ||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',delete ' else '' end 
                ||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',rule ' else '' end 
                ||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',references ' else '' end 
                ||case when charindex('t',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',trigger ' else '' end 
                ||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',execute ' else '' end 
                ||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end 
                ||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end 
                ||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',temporary ' else '' end 
             , 2,10000)
      || ' on '||namespace||'.'||item ||' from "'||pu.usename||'";' as grantsql
      from 
      (SELECT 
       use.usename as subject, 
       nsp.nspname as namespace, 
       c.relname as item, 
       c.relkind as type, 
       use2.usename as owner, 
       c.relacl 
       FROM 
       pg_user use 
       cross join pg_class c 
       left join pg_namespace nsp on (c.relnamespace = nsp.oid) 
       left join pg_user use2 on (c.relowner = use2.usesysid)
       WHERE 
       c.relowner = use.usesysid  
       and  nsp.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
       ORDER BY   subject,   namespace,   item 
      ) join pg_user pu on array_to_string(relacl, '|') like '%'||pu.usename||'%' 
      where relacl is not null
       and pu.usename='test_55'
      

      您可以使用此查询的变体来查看用户是否属于任何组(然后使用“alter group drop user”):

      select usesysid, usename, nvl(groname,'default') from pg_user u 
      left join pg_group g on ','||array_to_string(grolist,',')||','
        like '%,'||cast(usesysid as varchar(10))||',%' 
      where usename='test_55' order by 2,1;
      

      您可以使用此查询来查看他们是否有任何架构授权:

      select * from pg_namespace where nspowner > 1 and array_to_string(nspacl,',') like '%test_55%';
      

      【讨论】:

      • 嗨 Mike,当我运行上述脚本来撤销任何授权时,我收到以下消息:错误:无法识别类型 aclitem[] 的排序运算符提示:使用显式排序运算符或修改查询。如何压制这个?你能给我提供修改后的查询吗?我正在使用亚马逊红移(数据库版本:8.0.2)谢谢
      • 我很抱歉。最后一行“order by 1”应该被删除。我忘记了我已将 relacl 添加到所选字段以显示原始权限。
      • 谢谢谢谢谢谢!我已经争取了一个多小时从 Redshift 中删除用户,结果发现他们拥有一些我什至不知道存在的模式! :-)
      猜你喜欢
      • 2020-07-14
      • 2022-10-08
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      • 2018-10-05
      • 1970-01-01
      相关资源
      最近更新 更多