【问题标题】:How do I view grants on Redshift如何查看 Redshift 上的赠款
【发布时间】:2013-09-15 11:40:11
【问题描述】:

我想查看关于红移的赠款。

我找到this view for postgres

CREATE OR REPLACE VIEW view_all_grants AS 
SELECT 
  use.usename as subject, 
  nsp.nspname as namespace, 
  c.relname as item, 
  c.relkind as type, 
  use2.usename as owner, 
  c.relacl, 
  (use2.usename != use.usename and c.relacl::text !~ ('({|,)' || use.usename || '=')) as public
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 or 
  c.relacl::text ~ ('({|,)(|' || use.usename || ')=') 
ORDER BY 
  subject, 
  namespace, 
  item 

这不起作用,因为 relacl::text 演员表失败并显示以下内容:

ERROR: cannot cast type aclitem[] to character varying [SQL State=42846] 

将查询修改为

CREATE OR REPLACE VIEW view_all_grants AS 
SELECT 
  use.usename as subject, 
  nsp.nspname as namespace, 
  c.relname as item, 
  c.relkind as type, 
  use2.usename as owner, 
  c.relacl 
  -- , (use2.usename != use.usename and c.relacl::text !~ ('({|,)' || use.usename || '=')) as public
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 
  -- or c.relacl::text ~ ('({|,)(|' || use.usename || ')=') 
ORDER BY 
  subject, 
  namespace, 
  item 

允许创建视图,但我担心这不会显示所有相关数据。

如何修改视图以在 redshift 上工作,或者是否有更好/替代方式来查看 redshift 上的授权?

更新: Redshift 有 HAS_TABLE_PRIVILEGE 函数来检查授权。 (见here

【问题讨论】:

  • 不注释掉这两行会出现什么错误?如果肯定是演员阵容失败,relacl 列的类型是什么?
  • 更新了来自演员表的实际错误消息。
  • select 'postgres=arwdDxt/postgres'::aclitem::text 工作正常吗? select '{postgres=arwdDxt/postgres,=r/postgres}'::aclitem[]::text[]::text 怎么样?如果这些工作,那么您应该能够将c.relacl::text 更改为c.relacl::text[]::text。如果没有,您需要找到另一种查看 ACL 内部的方法(或创建自定义转换)。
  • 感谢您查看此内容,select 'anmediaextract01=arwdxt/anmediaextract01'::aclitem::text(注意没有“D”)失败并出现同样的错误。与其他变体相同。顺便说一句,不要认为可以在 redshift 中创建自定义演员表。
  • 啊哈! - 似乎 HAS_TABLE_PRIVILEGE 函数适用于红移:docs.aws.amazon.com/redshift/latest/dg/…

标签: sql amazon-redshift


【解决方案1】:

另一种变化是:

SELECT * 
FROM 
    (
    SELECT 
        schemaname
        ,objectname
        ,usename
        ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'select') AND has_schema_privilege(usrs.usename, schemaname, 'usage')  AS sel
        ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'insert') AND has_schema_privilege(usrs.usename, schemaname, 'usage')  AS ins
        ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'update') AND has_schema_privilege(usrs.usename, schemaname, 'usage')  AS upd
        ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'delete') AND has_schema_privilege(usrs.usename, schemaname, 'usage')  AS del
        ,HAS_TABLE_PRIVILEGE(usrs.usename, fullobj, 'references') AND has_schema_privilege(usrs.usename, schemaname, 'usage')  AS ref
    FROM
        (
        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')
        ) AS objs
        ,(SELECT * FROM pg_user) AS usrs
    ORDER BY fullobj
    )
WHERE (sel = true or ins = true or upd = true or del = true or ref = true)
and schemaname='<opt schema>'
and usename = '<opt username>';

【讨论】:

  • 正是我想要的!
  • 我收到了[3F000][500310] [Amazon](500310) Invalid operation: schema "pg_temp_12" does not exist;,您知道可能出了什么问题吗?
【解决方案2】:

有点意思:

select tablename, 
   HAS_TABLE_PRIVILEGE(tablename, 'select') as select,
   HAS_TABLE_PRIVILEGE(tablename, 'insert') as insert,
   HAS_TABLE_PRIVILEGE(tablename, 'update') as update,
   HAS_TABLE_PRIVILEGE(tablename, 'delete') as delete, 
   HAS_TABLE_PRIVILEGE(tablename, 'references') as references 
from pg_tables where schemaname='public' order by tablename;

给我我需要的一切。

【讨论】:

  • 我收到错误消息[42P01][500310] [Amazon](500310) Invalid operation: relation "sql_features" does not exist; :/
【解决方案3】:

对 mike_pdb 答案的发展我想出了以下内容

 WITH object_list(schema_name,object_name,permission_info)
 AS (
    SELECT N.nspname, C.relname, array_to_string(relacl,',')
    FROM pg_class AS C
        INNER JOIN pg_namespace AS N
        ON C.relnamespace = N.oid
    WHERE C.relkind in ('v','r')
    AND  N.nspname NOT IN ('pg_catalog', 'pg_toast', 'information_schema')
    AND C.relacl[1] IS NOT NULL
  ),
  object_permissions(schema_name,object_name,permission_string)
  AS (
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',1) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',2) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',3) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',4) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',5) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',6) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',7) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',8) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',9) FROM object_list
    UNION ALL
    SELECT schema_name,object_name, SPLIT_PART(permission_info,',',10) FROM object_list
  ),
  permission_parts(schema_name, object_name,security_principal, permission_pattern)
  AS (
      SELECT
          schema_name,
          object_name,
          LEFT(permission_string ,CHARINDEX('=',permission_string)-1),
          SPLIT_PART(SPLIT_PART(permission_string,'=',2),'/',1)
      FROM object_permissions
      WHERE permission_string >''
  )
SELECT
    schema_name,
    object_name,
    'GRANT ' ||
    SUBSTRING(
        case when charindex('r',permission_pattern) > 0 then ',SELECT ' else '' end
      ||case when charindex('w',permission_pattern) > 0 then ',UPDATE ' else '' end
      ||case when charindex('a',permission_pattern) > 0 then ',INSERT ' else '' end
      ||case when charindex('d',permission_pattern) > 0 then ',DELETE ' else '' end
      ||case when charindex('R',permission_pattern) > 0 then ',RULE ' else '' end
      ||case when charindex('x',permission_pattern) > 0 then ',REFERENCES ' else '' end
      ||case when charindex('t',permission_pattern) > 0 then ',TRIGGER ' else '' end
      ||case when charindex('X',permission_pattern) > 0 then ',EXECUTE ' else '' end
      ||case when charindex('U',permission_pattern) > 0 then ',USAGE ' else '' end
      ||case when charindex('C',permission_pattern) > 0 then ',CREATE ' else '' end
      ||case when charindex('T',permission_pattern) > 0 then ',TEMPORARY ' else '' end
    ,2,10000
    )
    || ' ON ' || schema_name||'.'||object_name
     || ' TO ' || security_principal
     || ';' as grantsql
FROM permission_parts

;

这里使用了 3 个常用的表表达式。

  • object_list - 表和视图,其权限数组为逗号分隔字符串。
  • object_permissions - 架构/对象(表或视图)和每个权限字符串的记录。请注意,SPLIT_PART 函数不允许动态部件位置,因此这里假设分配直接权限的用户或组不超过 10 个
  • permission_parts 架构/对象、被授予权限的安全主体以及设置的安全属性。

根据 mike_pdb 的解决方案,单个权限字符被转换为连接的授权列表。由于我们不知道将使用哪些授权,我们使用位置 2 的 SUBSTRING 来丢弃列表中的第一个逗号。

您可以使用完全相同的方法编写架构权限的脚本

WITH schema_list(schema_name, permission_info)
AS (
    SELECT nspname, array_to_string(nspacl,',')
    FROM pg_namespace
    WHERE nspacl[1] IS NOT NULL
    AND nspname NOT LIKE 'pg%' AND nspname NOT IN ('public','information_schema')
),
schema_permissions(schema_name,permission_string)
AS (
    SELECT schema_name,SPLIT_PART(permission_info,',',1) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',2) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',3) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',4) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',5) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',6) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',7) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',8) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',9) FROM schema_list
    UNION ALL
    SELECT schema_name,SPLIT_PART(permission_info,',',10) FROM schema_list
),
permission_parts(schema_name, security_principal, permission_pattern)
AS (
    SELECT
        schema_name,
        LEFT(permission_string ,CHARINDEX('=',permission_string)-1),
        SPLIT_PART(SPLIT_PART(permission_string,'=',2),'/',1)
    FROM schema_permissions
    WHERE permission_string >''
)
SELECT
    schema_name,
    'GRANT ' ||
    SUBSTRING(
        case when charindex('r',permission_pattern) > 0 then ',SELECT ' else '' end
      ||case when charindex('w',permission_pattern) > 0 then ',UPDATE ' else '' end
      ||case when charindex('a',permission_pattern) > 0 then ',INSERT ' else '' end
      ||case when charindex('d',permission_pattern) > 0 then ',DELETE ' else '' end
      ||case when charindex('R',permission_pattern) > 0 then ',RULE ' else '' end
      ||case when charindex('x',permission_pattern) > 0 then ',REFERENCES ' else '' end
      ||case when charindex('t',permission_pattern) > 0 then ',TRIGGER ' else '' end
      ||case when charindex('X',permission_pattern) > 0 then ',EXECUTE ' else '' end
      ||case when charindex('U',permission_pattern) > 0 then ',USAGE ' else '' end
      ||case when charindex('C',permission_pattern) > 0 then ',CREATE ' else '' end
      ||case when charindex('T',permission_pattern) > 0 then ',TEMPORARY ' else '' end
    ,2,10000
    )
    || ' ON SCHEMA ' || schema_name
     || ' TO ' || security_principal
     || ';' as grantsql
FROM permission_parts;

【讨论】:

    【解决方案4】:

    has_table_privilege 函数很方便,但在您想要管理组时并不总是有助于管理。我修改了您的原始查询,为特定用户或组创建授权脚本。此示例查询可以轻松修改以满足您的需求

    select namespace||'.'||item as tablename , 
    'grant ' || substring(
                    case when charindex('r',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',select ' else '' end 
                  ||case when charindex('w',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',update ' else '' end 
                  ||case when charindex('a',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',insert ' else '' end 
                  ||case when charindex('d',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',delete ' else '' end 
                  ||case when charindex('R',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',rule ' else '' end 
                  ||case when charindex('x',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',references ' else '' end 
                  ||case when charindex('t',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',trigger ' else '' end 
                  ||case when charindex('X',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',execute ' else '' end 
                  ||case when charindex('U',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',usage ' else '' end 
                  ||case when charindex('C',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',create ' else '' end 
                  ||case when charindex('T',split_part(split_part(array_to_string(relacl, '|'),'group dw_developers=',2 ) ,'/',1)) > 0 then ',temporary ' else '' end 
               , 2,10000)
     || ' on '||namespace||'.'||item ||' to group dw_developers;' 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 
     ) where relacl is not null
     and array_to_string(relacl, '|') like '%group dw_developers%' order by 1
    

    【讨论】:

    • ....这似乎在某处有 () 关闭问题,但我没有尝试追踪它。
    • 这不只会获得所有权关系吗?所以,如果我创建(并拥有)一个模式并授予对组的访问权限,它就不会出现,对吧?
    【解决方案5】:

    我为此苦苦挣扎,最后想出了一个解决方案,让我得到了我想要看到的东西。

    WITH tabledef as (
        SELECT schemaname,
            't' AS typename,
            tablename AS objectname,
            tableowner as owner,
            schemaname + '.' + tablename AS fullname
        FROM pg_tables
        UNION 
        SELECT schemaname,
            'v' AS typename,
            viewname AS objectname,
            viewowner as owner,
            schemaname + '.' + viewname AS fullname
        FROM pg_views
    ),
    res AS (
        SELECT t.*,
        CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'select')
        WHEN true THEN u.usename
        ELSE NULL END AS sel,
        CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'insert')
        WHEN true THEN u.usename
        ELSE NULL END AS ins,
        CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'update')
        WHEN true THEN u.usename
        ELSE NULL END AS upd,
        CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'delete')
        WHEN true THEN u.usename
        ELSE NULL END AS del,
        CASE HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'references')
        WHEN true THEN u.usename
        ELSE NULL END AS ref
        FROM tabledef AS t
        JOIN pg_user AS u
        ON HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'select') = true
            OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'insert') = true
            OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'update') = true
            OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'delete') = true
            OR HAS_TABLE_PRIVILEGE(u.usename, t.fullname, 'references') = true
            OR t.owner = u.usename
        WHERE t.schemaname = 'analytics'
    )
    SELECT schemaname, objectname, owner, sel, ins, upd, del, ref FROM res
    WHERE sel not in ('rdsdb', '<superuser>')
    ORDER BY schemaname, objectname;
    

    两条重要的线 - 一条指出要扫描访问的架构

    WHERE t.schemaname = 'analytics'
    

    And - Second 从结果中丢弃超级用户权限(他们仍然拥有完全权限)。

    WHERE sel not in ('rdsdb', '<superuser>')
    

    【讨论】:

    • 2021 年开工
    【解决方案6】:

    这是另一个有用的查询,用于查看我根据@drtf 上面的查询创建的用户对架构(使用、创建)的授权:

    SELECT * 
    FROM 
        (
        SELECT 
            schemaname
            ,usename
            ,HAS_SCHEMA_PRIVILEGE(usrs.usename, schemaname, 'usage') AS usg
            ,HAS_SCHEMA_PRIVILEGE(usrs.usename, schemaname, 'create') AS crt
        FROM
            (
            SELECT distinct(schemaname) FROM pg_tables
            WHERE schemaname not in ('pg_internal')
            UNION
            SELECT distinct(schemaname) FROM pg_views
            WHERE schemaname not in ('pg_internal')
            ) AS objs
            ,(SELECT * FROM pg_user) AS usrs
        ORDER BY schemaname
        )
    WHERE (usg = true or crt = true)
    --and schemaname='<opt schemaname>'
    --and usename = '<opt username>';
    

    【讨论】:

      猜你喜欢
      • 2023-01-26
      • 1970-01-01
      • 2018-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-12
      • 2015-08-14
      相关资源
      最近更新 更多