删除具有权限的角色

时间:2017-12-27 19:53:58

标签: sql postgresql rdbms roles database-administration

这看起来像是一个非常基本的需求,但我没有找到任何快速和合适的答案。我在Postgres中有一个角色,它拥有各种数据库中许多其他表的权限。

我需要放弃这个角色。我有一个postgres实例,然后有很多数据库。

SELECT DISTINCT 'REVOKE ALL ON TABLE ' || table_schema || '.' || table_name || ' FROM ' || r.param_role_name || ';'  
FROM information_schema.table_privileges CROSS JOIN (SELECT 'some_role_name'::text AS param_role_name) r
WHERE grantee ~* r.param_role_name;

我可以这样做,通过访问每个数据库并查找所有撤销语句然后删除该角色。有什么办法可以在一个地方为所有数据库找到所有撤销声明。

或者像我可以改变这个角色所拥有的东西,我可以用一个声明改变所有特权吗?

Edit1:由于大部分回复的目标都是重新分配所拥有和掉落所拥有,我希望更具体。 我可以在每个数据库上执行以下命令,并在删除所有依赖项后删除角色。

REASSIGN OWNED BY some_role_name TO postgres;
DROP OWNED BY some_role_name;

但是有很多数据库,所以我正在寻找强制刷新所有权限并放弃此角色的东西。

2 个答案:

答案 0 :(得分:5)

  

我需要放弃这个角色。

每个数据库一个REASSIGN OWNED,后跟DROP OWNED应该这样做:

REASSIGN OWNED BY some_role_name TO postgres;
DROP OWNED BY some_role_name;

postgres是默认的超级用户,他将拥有该角色所拥有的任何对象。在REASSIGN OWNED之后,没有任何对象会被同一个用户拥有。运行DROP OWNED似乎不直观。该命令的措辞具有误导性,因为它撤销了同一数据库中该角色的所有权限和默认权限。 The manual:

  

DROP OWNED删除当前数据库中由其中一个指定角色拥有的所有对象。 授予当前数据库和共享对象(数据库,表空间)中对象的给定角色的任何权限也将被撤销。

大胆强调我的 您仍然必须在 每个数据库 中执行它。手册:

  

由于REASSIGN OWNED不会影响其他数据库中的对象,因此通常需要在每个包含要删除的角色所拥有的对象的数据库中执行此命令。

在你跑步之前(一次!):

DROP role some_role_name;

角色存储在群集范围的系统目录中,而对象的所有权和权限存储在特定于数据库的系统目录中。

相关答案中的详细解释:

@klin在his comment中提到了一个非常有用的手册页:

完全自动化

没有一个命令可以完成所有操作。但是你可以让Postgres为你生成一个完整的psql脚本。

角色的依赖关系存储在系统目录pg_shdepend中。引自那里:

  

此信息允许PostgreSQL在尝试删除它们之前确保这些对象未被引用。

由于我们(可能)需要连接到不同的数据库,我们需要结合使用psql元命令(\c my_database)和SQL DDL命令,如上所示。在数据库集群中的某个位置创建此函数一次:

CREATE OR REPLACE FUNCTION f_generate_ddl_to_remove_role(dead_role_walking regrole)
  RETURNS text AS
$func$
SELECT concat_ws(
   E'\n'
 ,(SELECT string_agg(format(E'\\c %I\nREASSIGN OWNED BY %2$s TO postgres; DROP OWNED BY %2$s;'
                          , d.datname, dead_role_walking)
                   , E'\n')
   FROM  (
      SELECT DISTINCT dbid
      FROM   pg_shdepend
      WHERE  refobjid = dead_role_walking
      ) s
   JOIN   pg_database d ON d.oid = s.dbid)
 , format(E'DROP role %s;\n', dead_role_walking)
   )
$func$  LANGUAGE sql;

呼叫:

SELECT f_generate_ddl_to_remove_role('some_role_name');

生成如下字符串:

\c my_db1
REASSIGN OWNED BY some_role_name TO postgres; DROP OWNED BY some_role_name;
\c my_db2
REASSIGN OWNED BY some_role_name TO postgres; DROP OWNED BY some_role_name;
DROP role some_role_name;

或者,如果角色没有任何东西且没有任何权限,只需:

DROP role some_role_name;

如果您提供不存在的角色名称,则会收到错误。

将字符串(不包含单引号)复制到使用postgres等超级用户打开的psql会话。或者用它连接一个bash脚本。一切都完成了。

有几个相关的答案,对动态SQL有更多解释:

答案 1 :(得分:2)

在任何数据库中都有依赖对象之前,您不能删除角色。

您必须将此用户拥有的对象(some_role_name)重新分配给其他用户。 对所有数据库中的所有对象完成后,您就可以删除该用户。

REASSIGN OWNED BY some_role_name TO some_other_role_name;

如果不需要依赖对象,您也可以继续使用DROP OWNED BY,删除some_role_name拥有的所有对象。

DROP OWNED BY some_role_name;