无法删除被授予连接数据库的角色

jla*_*rcy 4 sql postgresql privileges dependencies sql-revoke

我正在使用 PostgreSQL 10.4,我发现了一个奇怪的行为。

如果我们创建一个角色并将其授予CONNECT数据库:

CREATE ROLE dummy;
GRANT CONNECT ON DATABASE test TO dummy;
Run Code Online (Sandbox Code Playgroud)

然后我们不能删除这个角色,即使它根本不拥有任何对象,这个命令:

DROP ROLE dummy;
Run Code Online (Sandbox Code Playgroud)

提高:

ERROR: role "dummy" cannot be dropped because some objects depend on it
SQL state: 2BP01
Detail: privileges for database test
Run Code Online (Sandbox Code Playgroud)

文档有点误导:

2B 类 — 依赖特权描述符仍然存在

2B000dependent_privilege_descriptors_still_exist

2BP01dependent_objects_still_exist

它说依赖对象仍然存在,但似乎没有依赖于这个特定角色的对象,它在数据库上没有任何东西。

无论如何,如果我们撤销CONNECT特权,那么角色可以被删除:

REVOKE CONNECT ON DATABASE test FROM dummy;
DROP ROLE dummy;
Run Code Online (Sandbox Code Playgroud)

我刚刚检查了 PostgreSQL 9.5 上也存在该行为。我觉得有点奇怪,我不明白为什么这个特定的特权会导致删除角色失败。

其他观察

这真的是阻塞,因为我们既不能重新分配这个对象:

REASSIGN OWNED BY dummy TO postgres;
Run Code Online (Sandbox Code Playgroud)

也不丢弃对象:

DROP OWNED BY dummy;
Run Code Online (Sandbox Code Playgroud)

两者都引发相关错误:

ERROR: permission denied to reassign objects
SQL state: 42501

ERROR: permission denied to drop objects
SQL state: 42501
Run Code Online (Sandbox Code Playgroud)

正如@RaymondNijland 指出的那样,这一定是因为CONNECT权限被视为角色相关对象。以下查询:

WITH
R AS (SELECT * FROM pg_roles WHERE rolname = 'dummy')
SELECT
    D.*
FROM
    R, pg_shdepend AS D
WHERE
    refobjid = R.oid;
Run Code Online (Sandbox Code Playgroud)

CONNECT授予时返回单行:

"dbid";"classid";"objid";"objsubid";"refclassid";"refobjid";"deptype"
0;1262;27961;0;1260;27966;"a"
Run Code Online (Sandbox Code Playgroud)

当特权被撤销时,根本没有行。这至少解释了为什么我们不能重新分配对象。

关于依赖类型,文档说明:

SHARED_DEPENDENCY_ACL (一种)

被引用的对象(必须是角色)在依赖对象的ACL(访问控制列表,即权限列表)中有提到。(A SHARED_DEPENDENCY_ACL不会为对象的所有者创建SHARED_DEPENDENCY_OWNER条目,因为无论如何所有者都会有条目。)

但我没有足够的洞察力来清楚地理解它。

我的问题是:

  • Postgres 是否总是需要在删除角色之前撤销权限?
  • 如果不是,为什么这个特定的特权会这样?

mlt*_*tsy 6

使用REASSIGN.

我发现当超级用户帐户不可用时(如 RDS 或 Cloud SQL),我必须将目标角色授予我当前的角色,以便从目标角色重新分配或删除拥有的对象。例如,如果我的活跃用户是postsgres,而我正在尝试删除user_a

> DROP OWNED BY user_a
ERROR:  permission denied to drop objects
> GRANT user_a TO postgres;
GRANT ROLE
> DROP OWNED BY user_a;
DROP OWNED
Run Code Online (Sandbox Code Playgroud)

现在,如果user_a碰巧是 的成员,这会变得有点棘手postgres,尤其是如果它碰巧通过其他角色继承了该成员身份,让我们称其为schema_admin...

> DROP OWNED BY user_a
ERROR:  permission denied to drop objects
> GRANT user_a TO postgres;
ERROR:  role "user_a" is a member of role "postgres"

-- Alright, let's try to revoke it...
> REVOKE postgres FROM user_a;
REVOKE ROLE
> GRANT user_a TO postgres;
ERROR:  role "user_a" is a member of role "postgres"

-- It's still a member through the inherited grant - trying to revoke again doesn't work:
> REVOKE postgres FROM user_a;
WARNING:  role "user_a" is not a member of role "postgres"
REVOKE ROLE

-- So you have to identify the role it's inheriting from, and revoke that:
> REVOKE schema_admin FROM user_a;
REVOKE ROLE
> GRANT user_a TO postgres;
GRANT ROLE

-- Now just to be safe, I'll reassign owned objects before actually dropping everything:
> REASSIGN OWNED BY user_a TO postgres;
REASSIGN OWNED
> DROP OWNED BY user_a;
DROP OWNED
> DROP ROLE user_a;
DROP ROLE;
Run Code Online (Sandbox Code Playgroud)

瞧!

注意:这里还有另一个广泛引用且有效的答案:https : //sysadmintips.com/services/databases/postgresql-error-permission-denied-to-reassign-objects/只要您能够创建并以新的临时用户身份登录。然而,在某些情况下,这本身就是一个问题(然后你还有额外的清理工作来处理完成后删除该临时角色),所以我试图在这里避免这种情况。