Encuentra objetos vinculados a un rol de PostgreSQL

12

Hace algunas veces creé un usuario de PostgreSQL llamado user1 (PostgreSQL 9.4.9).

Quiero dejar caer este usuario. Así que primero revoco todos los permisos en tablas, secuencias, funciones, privilegios predeterminados y propiedad también:

ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON SEQUENCES FROM user1;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON TABLES FROM user1;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON FUNCTIONS FROM user1;

REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM user1;
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM user1;
REVOKE ALL ON ALL FUNCTIONS IN SCHEMA public FROM user1;

REASSIGN OWNED BY user1 TO postgres;

Sin embargo, parece que un objeto permanece vinculado a este usuario en 2 bases de datos:

postgres=# DROP ROLE user1;
ERROR:  role "user1" cannot be dropped because some objects depend on it
DETAIL:  1 object in database db1
1 object in database db2

Incluso parece ser una función:

postgres=# \c db1
You are now connected to database "db1" as user "postgres".
db1=# DROP ROLE user1;
ERROR:  role "user1" cannot be dropped because some objects depend on it
DETAIL:  privileges for function text(boolean)
1 object in database db2

Pero no puedo determinar qué objeto pertenece o está relacionado con el usuario1.

Si no pg_dump -s db1 | grep user1obtengo ningún resultado! ¿Podría ser un objeto global?

¿Cómo puedo identificar el objeto perdido?

He ejecutado los comandos en cada base de datos (db1 y db2). No quiero dejar caer los objetos de su propiedad user1, solo quiero reasignar o eliminar concesiones para este usuario.

Nicolas Payart
fuente

Respuestas:

11

Respuesta a la pregunta formulada

Para buscar la función en el mensaje de error y su propietario:

SELECT oid::regprocedure AS function
     , pg_get_userbyid(proowner) AS owner
FROM   pg_proc
WHERE  oid = 'text(boolean)'::regprocedure;

Relacionado:

Problema real

El mensaje de error dice:

DETALLE: privilegios para texto de función (booleano)

No se trata de propiedad sino de privilegios .

El manual para DROP ROLE:

Antes de descartar el rol, debe descartar todos los objetos que posee (o reasignar su propiedad) y revocar cualquier privilegio que se le haya otorgado al rol en otros objetos .

Y para ALTER DEFAULT PRIVILEGES:

Si desea eliminar un rol para el que se han alterado los privilegios predeterminados, es necesario revertir los cambios en sus privilegios predeterminados o usar DROP OWNEDBY para deshacerse de la entrada de privilegios predeterminados para el rol .

También parece que solo se ejecutó REASSIGN OWNEDen una base de datos, pero el manual indica:

Debido a REASSIGN OWNEDque no afecta los objetos dentro de otras bases de datos, generalmente es necesario ejecutar este comando en cada base de datos que contiene objetos propiedad de un rol que se va a eliminar.

El énfasis audaz es mío.

Y restringiste tus comandos con IN SCHEMA public. Suelta esa cláusula para apuntar a toda la base de datos. Pero no te molestes, hay un ...

Solución simple con DROP OWNED

REASSIGN OWNED BY user1 TO postgres;
DROP OWNED BY user1;

Todos los objetos del rol cambiaron de propietario postgrescon el primer comando y ahora están a salvo. La redacción de DROP OWNEDes un poco engañosa, ya que también elimina todos los privilegios y privilegios predeterminados. El manual para DROP OWNED:

DROP OWNEDdescarta todos los objetos dentro de la base de datos actual que son propiedad de uno de los roles especificados. También se revocará cualquier privilegio otorgado a los roles dados en los objetos de la base de datos actual y en los objetos compartidos (bases de datos, espacios de tablas).

Repita en todos los DB relevantes, luego puede moverse para matar:

DROP ROLE user1;
Erwin Brandstetter
fuente
6

La consulta a continuación enumera los objetos con los propietarios. Para todos los privilegios realmente necesitamos más.

--r = ordinary table, i = index, S = sequence, v = view, m = materialized view, c = composite type, t = TOAST table, f = foreign table
SELECT 
    n.nspname AS schema_name,
    c.relname AS rel_name,
    c.relkind AS rel_kind,
    pg_get_userbyid(c.relowner) AS owner_name
  FROM pg_class c
  JOIN pg_namespace n ON n.oid = c.relnamespace

UNION ALL

-- functions (or procedures)
SELECT
    n.nspname AS schema_name,
    p.proname,
    'p',
    pg_get_userbyid(p.proowner)
  FROM pg_proc p
  JOIN pg_namespace n ON n.oid = p.pronamespace
Sahap Asci
fuente
Todavía no encuentro el objeto que falta con esto.
Nicolas Payart
@NicolasPayart: ¿Está ejecutando la consulta en la base de datos correcta?
Erwin Brandstetter
1

Primero debe conectarse a la base de datos. En tu caso eso sería

\c db1

y

\c db2

Luego, intente ejecutar las declaraciones REVOKE ALL PRIVILEGES y REASSIGN OWNED / DROP DWNP nuevamente.

Samuel Anyaele
fuente
1
Hola, gracias por tu primera respuesta. Sin embargo, antes de publicar, piense en qué agrega esto a las respuestas existentes y descríbalas también en su respuesta.
dezso