I am using PostgreSQL 10.4 and I found a strange behavior.
If we create an role and grant it to CONNECT
the database:
CREATE ROLE dummy;
GRANT CONNECT ON DATABASE test TO dummy;
Then we cannot drop this role, even if it owns no object at all, this command:
DROP ROLE dummy;
Raises:
ERROR: role "dummy" cannot be dropped because some objects depend on it
SQL state: 2BP01
Detail: privileges for database test
Documentation is a bit misleading:
Class 2B — Dependent Privilege Descriptors Still Exist
2B000 dependent_privilege_descriptors_still_exist
2BP01 dependent_objects_still_exist
It says dependent objects still exist, but it seems there are no objects dependent to this specific role, it owns nothing on the database.
Anyway, if we revoke the CONNECT
privilege, then role can be dropped:
REVOKE CONNECT ON DATABASE test FROM dummy;
DROP ROLE dummy;
I just checked the behavior also exists on PostgreSQL 9.5. I feel it a bit strange and I cannot understand why this specific privilege makes dropping role fails.
Additional observations
This is really blocking, because we can neither reassign this object:
REASSIGN OWNED BY dummy TO postgres;
Nor drop the object:
DROP OWNED BY dummy;
Both raise related errors:
ERROR: permission denied to reassign objects
SQL state: 42501
ERROR: permission denied to drop objects
SQL state: 42501
As @RaymondNijland pointed out, this must be because the CONNECT
privileges is viewed as a role dependent object. The following query:
WITH
R AS (SELECT * FROM pg_roles WHERE rolname = 'dummy')
SELECT
D.*
FROM
R, pg_shdepend AS D
WHERE
refobjid = R.oid;
Returns a single row when CONNECT
is granted:
"dbid";"classid";"objid";"objsubid";"refclassid";"refobjid";"deptype"
0;1262;27961;0;1260;27966;"a"
And no row at all when the privilege is revoked. This at least explain why we cannot reassign the object.
About the Dependency Type, the documentation states:
SHARED_DEPENDENCY_ACL
(a)The referenced object (which must be a role) is mentioned in the ACL (access control list, i.e., privileges list) of the dependent object. (
A SHARED_DEPENDENCY_ACL
entry is not made for the owner of the object, since the owner will have aSHARED_DEPENDENCY_OWNER
entry anyway.)
But I have not enough insight to understand it clearly.
My question are:
- Do Postgres always require to revoke privileges before dropping a role?
- If not, why this specific privilege behaves like this?
There are 2 ways to run REASSIGN OWNED and DROP OWNED. The 1st way is with a superuser and the 2nd way is with a normal user.
<The 1st way>:
For example, first, log in to
apple
database with any superuser e.g.,postgres
. *My answer explains how to create a superuser. and my answer explains how to make a user a superuser:Finally, you can run
REASSIGN OWNED
andDROP OWNED
as shown below:Or:
Or:
Or:
<The 2nd way>:
For example, first, log in to any database e.g.,
postgres
database with any superuser e.g.,postgres
as shown below:Then, create the user
john
as shown below:Then, grant the users
david
andpeter
to the userjohn
, exit as shown below:Then, log in to
apple
database with the userjohn
as shown below:Finally, you can run
REASSIGN OWNED
andDROP OWNED
as shown below:Or:
Or:
Or: