Suchen Sie nach Objekten, die mit einer PostgreSQL-Rolle verknüpft sind

12

Vor einiger Zeit habe ich einen PostgreSQL-Benutzer namens user1 (PostgreSQL 9.4.9) erstellt.

Ich möchte diesen Benutzer löschen. Daher widerrufe ich zunächst alle Berechtigungen für Tabellen, Sequenzen, Funktionen, Standardberechtigungen und Eigentumsrechte:

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;

Es scheint jedoch, dass ein Objekt in zwei Datenbanken mit diesem Benutzer verknüpft bleibt:

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

Es scheint sogar eine Funktion zu sein:

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

Ich kann jedoch nicht feststellen, welches Objekt dem Benutzer gehört oder mit ihm in Beziehung steht1.

Wenn ich pg_dump -s db1 | grep user1kein Ergebnis bekomme! Könnte es ein globales Objekt sein?

Wie kann ich das fehlende Objekt identifizieren?

Ich habe die Befehle in jeder Datenbank ausgeführt (db1 und db2). Ich möchte keine Objekte löschen user1, deren Eigentümer es ist , sondern nur Zuschüsse für diesen Benutzer neu zuweisen oder entfernen.

Nicolas Payart
quelle

Antworten:

11

Antwort auf die gestellte Frage

So suchen Sie nach der Funktion in der Fehlermeldung und ihrem Besitzer:

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

Verbunden:

Tatsächliches Problem

Die Fehlermeldung lautet:

DETAIL: Berechtigungen für Funktionstext (Boolescher Wert)

Es geht nicht um Eigentum, sondern um Privilegien .

Das Handbuch für DROP ROLE:

Bevor Sie die Rolle löschen, müssen Sie alle Objekte löschen, die sie besitzt (oder deren Besitz neu zuweisen), und alle Berechtigungen widerrufen, die der Rolle für andere Objekte gewährt wurden .

Und für ALTER DEFAULT PRIVILEGES:

Wenn Sie eine Rolle löschen möchten, für die die Standardberechtigungen geändert wurden, müssen Sie die Änderungen in den Standardberechtigungen rückgängig machen oder DROP OWNEDBY verwenden, um den Standardberechtigungseintrag für die Rolle zu entfernen .

Es sieht auch so aus, als hätten Sie nur REASSIGN OWNEDin einer Datenbank ausgeführt, aber das Handbuch weist Sie an:

Da REASSIGN OWNEDObjekte in anderen Datenbanken nicht betroffen sind, muss dieser Befehl normalerweise in jeder Datenbank ausgeführt werden , die Objekte enthält, deren Eigentümer eine zu entfernende Rolle ist.

Meine kühne Betonung.

Und Sie haben Ihre Befehle mit eingeschränkt IN SCHEMA public. Löschen Sie diese Klausel, um auf die gesamte Datenbank abzuzielen. Aber mach dir keine Sorgen, es gibt eine ...

Einfache Lösung mit DROP OWNED

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

Alle Objekte der Rolle haben postgresmit dem ersten Befehl den Besitz geändert und sind jetzt sicher. Der Wortlaut von DROP OWNEDist etwas irreführend, da auch alle Berechtigungen und Standardberechtigungen beseitigt werden. Das Handbuch für DROP OWNED:

DROP OWNEDlöscht alle Objekte in der aktuellen Datenbank, die einer der angegebenen Rollen gehören. Alle Berechtigungen, die den angegebenen Rollen für Objekte in der aktuellen Datenbank und für freigegebene Objekte (Datenbanken, Tablespaces) gewährt werden, werden ebenfalls widerrufen.

Wiederholen Sie dies in allen relevanten DBs, dann können Sie für den Kill einziehen:

DROP ROLE user1;
Erwin Brandstetter
quelle
6

In der folgenden Abfrage werden Objekte mit Eigentümern aufgelistet. Für alle Privilegien brauchen wir tatsächlich mehr.

--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
quelle
Ich finde das fehlende Objekt damit immer noch nicht.
Nicolas Payart
@NicolasPayart: Führen Sie die Abfrage in der richtigen Datenbank aus?
Erwin Brandstetter
1

Sie müssen zuerst eine Verbindung zur Datenbank herstellen. In Ihrem Fall wäre das

\c db1

und

\c db2

Führen Sie dann die Anweisungen REVOKE ALL PRIVILEGES und REASSIGN OWNED / DROP OWNED erneut aus.

Samuel Anyaele
quelle
1
Hey, danke für deine erste Antwort. Überlegen Sie sich jedoch vor dem Posten, was dies zu den vorhandenen Antworten beiträgt, und beschreiben Sie dies auch in Ihrer Antwort.
Dekso