我正在使用 PostgreSQL 10.4,我发现了一个奇怪的行为。
如果我们创建一个角色并将其授予CONNECT
数据库:
CREATE ROLE dummy;
GRANT CONNECT ON DATABASE test TO dummy;
那么我们就不能删除这个角色,即使它根本不拥有任何对象,这个命令:
DROP ROLE dummy;
Raises:
ERROR: role "dummy" cannot be dropped because some objects depend on it
SQL state: 2BP01
Detail: privileges for database test
文档有点误导:
2B 类 — 依赖权限描述符仍然存在
2B000 dependent_privilege_descriptors_still_exist
2BP01 dependent_objects_still_exist
It says 依赖对象仍然存在,但似乎没有任何对象依赖于这个特定角色,它在数据库上不拥有任何东西。
无论如何,如果我们撤销CONNECT
特权,然后可以删除角色:
REVOKE CONNECT ON DATABASE test FROM dummy;
DROP ROLE dummy;
我刚刚检查了 PostgreSQL 9.5 上也存在这种行为。我觉得有点奇怪,我不明白为什么这个特定的特权会导致删除角色失败。
额外的观察结果
这确实是阻塞的,因为我们无法重新分配这个对象:
REASSIGN OWNED BY dummy TO postgres;
也不丢弃对象:
DROP OWNED BY dummy;
两者都会引发相关错误:
错误:重新分配对象的权限被拒绝
SQL状态:42501
错误:删除对象的权限被拒绝
SQL状态:42501
正如@RaymondNijland 指出的,这一定是因为CONNECT
特权被视为角色相关的对象。以下查询:
WITH
R AS (SELECT * FROM pg_roles WHERE rolname = 'dummy')
SELECT
D.*
FROM
R, pg_shdepend AS D
WHERE
refobjid = R.oid;
当以下情况时返回单行CONNECT
被授予:
"dbid";"classid";"objid";"objsubid";"refclassid";"refobjid";"deptype"
0;1262;27961;0;1260;27966;"a"
当特权被撤销时,根本没有任何行。这至少解释了为什么我们不能重新分配对象。
关于依赖类型,文档 states:
SHARED_DEPENDENCY_ACL
(a)
引用的对象(必须是角色)在
依赖的ACL(访问控制列表,即权限列表)
目的。 (A SHARED_DEPENDENCY_ACL
条目不是为所有者创建的
对象,因为所有者将拥有一个SHARED_DEPENDENCY_OWNER
入口
反正。)
但我没有足够的洞察力来清楚地理解它。
我的问题是:
- Postgres 是否总是要求在删除角色之前撤销权限?
- 如果不是,为什么这个特定特权会这样?