如何使用 LOOP 撤销访问权限 - redshift

Posted

技术标签:

【中文标题】如何使用 LOOP 撤销访问权限 - redshift【英文标题】:How to revoke the access using LOOP - redshift 【发布时间】:2014-02-25 20:35:34 【问题描述】:

团队, 我正在使用亚马逊红移。以下是版本:

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.748

我想删除一个用户帐户。如果该用户有权访问任何表/模式/数据库,则必须先撤销该用户,然后才能删除该用户。在 redshift 中,“drop 归 ;”所有不管用。所以,我需要在删除之前以编程方式找出授予用户的访问权限。

例如我在 2 个模式上授予该用户访问权限。但是在撤销它时,我需要使用一些 FOR ..LOOP 然后找出这个用户可以访问的模式并撤销它,而不是手动(如下)。你能帮帮我吗?我需要编写一个小程序,其中需要创建一个游标并存储这两个模式,并且在 FOR..loop 下,我需要调用它们并一一撤销它们。如果您提供此功能,我可以使用它来撤销其他表授权、数据库授权等。

redshift=# GRANT all on schema schema44 to proj_user1;
GRANT
redshift=# grant all on schema proj_schema1 to proj_user1;
GRANT
redshift=#
redshift=# select nspname from pg_catalog.pg_namespace where array_to_string(nspacl,',') like '%proj_user1%';
   nspname
--------------
 schema44
 proj_schema1
(2 rows)



redshift=# revoke all on schema schema44 from proj_user1;
REVOKE
redshift=# revoke all on schema proj_schema1 from proj_user1;
REVOKE
redshift=# select nspname from pg_catalog.pg_namespace where array_to_string(nspacl,',') like '%proj_user1%';
 nspname
---------
(0 rows)

谢谢

【问题讨论】:

【参考方案1】:

Redshift 中没有提供循环功能的脚本。您可以从 psql 运行以下查询并将输出用作删除用户的脚本。

此查询为对象构建撤销 cmd:

select  
'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='<username>'
order by 1;

然后您将需要更改任何表的所有权:

select 'alter table '||schemaname||'.'||tablename||' owner to <newowner>;' from pg_tables where tableowner = '<username>';

您无法更改视图的所有权,因此您必须删除它们:

select 'drop view '||schemaname||'.'||viewname||' ;' from pg_views where viewowner = '<username>';

您需要从任何组中删除用户:

select 'alter group '||nvl(groname,'default')||' drop user '||usename||';' from pg_user u left join pg_group g on ','||array_to_string(grolist,',')||',' like '%,'||cast(usesysid as varchar(10))||',%' where usename='<username>' ;

最后从模式中移除:

select 
'revoke ' || substring(
          case when charindex('U',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',usage ' else '' end 
          ||case when charindex('C',split_part(split_part(array_to_string(nspacl, '|'),pu.usename,2 ) ,'/',1)) > 0 then ',create ' else '' end 
       , 2,10000)
|| ' on schema '||nspname||' from "'||pu.usename||'";' 
from pg_namespace pn,pg_user pu
 where pu.usename='<username>' and array_to_string(nspacl,',') like '%'||pu.usename||'%'
 and nspowner > 1 ;

【讨论】:

谢谢迈克。如果此用户有权访问任何其他数据库,那么我需要撤销它(mynewdb1=# revoke all on database mynewdb1 from test_4;)。但我仍然可以将此数据库(mynewdb1)连接为 TEST_4。 (注意:我也从公众中删除了,无论它发生在 redshift 中)。任何替代品? 所以您不想删除用户,而只是禁止他们连接?我不确定,但我认为唯一的选择就是放弃它们。

以上是关于如何使用 LOOP 撤销访问权限 - redshift的主要内容,如果未能解决你的问题,请参考以下文章

用于撤销项目集合管理员某些权限的 TFS 访问权限

应用程序的临时分发和撤销访问权限

Big Query 服务帐号的访问权限已被撤销?

撤销 PostgreSQL 用户的访问权限以查看其他表

Flutter:如何实时监听权限

如何在 PostgreSQL 中默认撤销函数的执行权限