it-swarm.com.de

Warum darf ein neuer Benutzer eine Tabelle erstellen?

Ich frage mich, warum ein neu erstellter Benutzer nach dem Herstellen einer Verbindung zu einer Datenbank eine Tabelle erstellen darf. Ich habe eine Datenbank, project2_core:

postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)

So weit, ist es gut. Jetzt erstelle ich einen Benutzer:

postgres=# CREATE ROLE dietrich ENCRYPTED PASSWORD 'md5XXX' LOGIN NOCREATEROLE NOCREATEDB NOSUPERUSER

Okay. Wenn ich versuche, eine Verbindung zur Datenbank herzustellen, darf der Benutzer dies nicht tun:

$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql: FATAL:  permission denied for database "project2_core"
DETAIL:  User does not have CONNECT privilege.

Das habe ich erwartet. Jetzt fängt das seltsame Zeug an. Ich erteile dem Benutzer CONNECT:

postgres=# GRANT CONNECT ON DATABASE project2_core TO dietrich;
GRANT
postgres=# \l
                                          List of databases
     Name      |    Owner     | Encoding  |   Collate   |    Ctype    |       Access privileges       
---------------+--------------+-----------+-------------+-------------+-------------------------------
 postgres      | postgres     | SQL_ASCII | C           | C           | 
 project2_core | atm_project2 | UTF8      | de_DE.UTF-8 | de_DE.UTF-8 | project2=CTc/project2+
               |              |           |             |             | dietrich=c/project2
 template0     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
 template1     | postgres     | SQL_ASCII | C           | C           | =c/postgres                  +
               |              |           |             |             | postgres=CTc/postgres
(5 rows)

Und ohne weitere Zuschüsse darf der Benutzer eine Tabelle erstellen:

$ psql -h localhost -p 5432 -U dietrich -W project2_core
Password for user dietrich: 
psql (9.2.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

project2_core=> create table adsf ();
CREATE TABLE
project2_core=> \d
        List of relations
 Schema | Name | Type  |  Owner   
--------+------+-------+----------
 public | adsf | table | dietrich
(1 row)

Ich hätte erwartet, dass der Benutzer nichts tun darf, bevor ich explizit GRANT USAGE Für das Schema und dann GRANT SELECT Für die Tabellen ausführe.

Wo ist mein Fehler? Was mache ich falsch? Wie kann ich erreichen, was ich will (dass ein neuer Benutzer nichts tun darf, bevor er ihm ausdrücklich die entsprechenden Rechte gewährt?.

Ich bin verloren und deine Hilfe wird sehr geschätzt :)

EDIT Nach dem Rat von @ daniel-verite widerrufe ich jetzt alles sofort nach dem Erstellen der Datenbank. Der Benutzer dietrich darf keine Tabelle mehr erstellen. Gut. ABER : Nun, auch der Eigentümer der Datenbank, project2 , ist es nicht darf eine Tabelle erstellen. Selbst nach der Ausgabe von GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2 Und GRANT ALL PRIVILEGES ON SCHEMA public TO project2 Erhalte ich eine Fehlermeldung . FEHLER: Es wurde kein Schema zum Erstellen in ausgewählt. und wenn ich speziell versuche, CREATE TABLE public.WHATEVER (); zu verwenden, erhalte ich ERROR: Berechtigung für Schema public verweigert . Was mache ich falsch?

44
andreas-h

Wenn Sie eine neue Datenbank erstellen, kann jede Rolle Objekte im Schema public erstellen. Um diese Möglichkeit zu entfernen, können Sie unmittelbar nach der Datenbankerstellung Folgendes ausgeben:

REVOKE ALL ON schema public FROM public;

Bearbeiten: Nach dem obigen Befehl darf nur ein Superuser neue Objekte im Schema public erstellen, was nicht praktikabel ist. Angenommen, einem Nicht-Superuser foo_user Sollte dieses Privileg gewährt werden, sollte dies folgendermaßen geschehen:

GRANT ALL ON schema public TO foo_user;

Um zu wissen, was ALL für ein Schema bedeutet, müssen wir auf GRANT im Dokument verweisen (in PG 9.2 gibt es nicht weniger als 14 Formen von GRANT-Anweisungen, die für verschiedene Dinge gelten. ..). Es scheint, dass es für ein Schema CREATE und USAGE bedeutet.

Auf der anderen Seite gewährt GRANT ALL PRIVILEGES ON DATABASE...CONNECT und CREATE und TEMP, aber CREATE bezieht sich in diesem Zusammenhang auf nicht permanente Schemata Tabellen.

In Bezug auf diesen Fehler: ERROR: no schema has been selected to create in Tritt es auf, wenn versucht wird, ein Objekt ohne Schemaqualifikation (wie in create table foo(...)) zu erstellen, ohne die Berechtigung zum Erstellen in einem beliebigen Schema des search_path.

41
Daniel Vérité

Das Entscheidende hier ist, dass Privilegien sind nicht heirachisch und nicht von enthaltenden Objekten geerbt. ALL bedeutet alle Berechtigungen für dieses Objekt nicht alle Berechtigungen für dieses Objekt und alle enthaltenen Objekte.

Wenn Sie ALL für eine Datenbank gewähren, gewähren Sie CREATE, CONNECT, TEMP. Dies sind Aktionen für das Datenbankobjekt selbst:

  • CONNECT: Stellen Sie eine Verbindung zur Datenbank her
  • CREATE: Erstellen Sie eine Schema (nicht eine Tabelle)
  • TEMP: Erstellen Sie temporäre Objekte, einschließlich, aber nicht beschränkt auf temporäre Tabellen

Jetzt verfügt jede PostgreSQL-Datenbank standardmäßig über ein public - Schema, das beim Erstellen der Datenbank erstellt wird. Dieses Schema hat alle Rechte, die der Rolle public gewährt werden, zu der implizit jeder gehört. Für ein Schema bedeutet ALLCREATE, USAGE:

  • CREATE: Erstellen Sie Objekte (einschließlich Tabellen) in diesem Schema
  • USAGE: Listet Objekte im Schema auf und greift auf sie zu, wenn ihre Berechtigungen dies zulassen

Wenn Sie das Schema nicht angeben, in dem ein Objekt wie eine Tabelle erstellt werden soll, verwendet das Datenbankmodul das search_path, Und standardmäßig befindet sich das Schema public zuerst im search_path Dort wird die Tabelle erstellt. Jeder hat standardmäßig Rechte an public, daher ist die Erstellung zulässig. Die Benutzerrechte an der Datenbank sind zu diesem Zeitpunkt irrelevant, da der Benutzer nicht versucht, selbst etwas mit dem Datenbankobjekt zu tun, sondern nur ein Schema darin.

Es spielt keine Rolle, dass Sie dem Benutzer keine anderen Rechte als das Gewähren von CONNECT für die Datenbank gewährt haben, da das Schema public allen Benutzern erlaubt, standardmäßig Tabellen darin zu erstellen. Daniel hat bereits erklärt, wie man dieses Recht auf Wunsch widerruft.

Wenn Sie jedes Recht explizit delegieren möchten, widerrufen Sie alles aus der Öffentlichkeit oder löschen Sie einfach das öffentliche Schema. Sie können eine neue Vorlagendatenbank mit dieser Änderung erstellen, wenn Sie möchten. Alternativ können Sie es auf template1 Anwenden, aber das wird wahrscheinlich viele Codes von Drittanbietern beschädigen, die davon ausgehen, dass public existiert und beschreibbar ist.


Dies ist möglicherweise sinnvoller, wenn Sie sich eine Dateisystemanalogie ansehen.

Wenn ich die Verzeichnisstruktur habe (Modus vereinfacht, um nur den Modus anzuzeigen, der für den aktuellen Benutzer gilt):

/dir1           mode=r-x
/dir1/dir2      mode=rwx

dann kann ich innerhalb von /dir1 nichts erstellen, da ich keine Schreibberechtigung habe. Wenn ich also touch /dir1/somefile Erhalte, wird mir ein Fehler mit verweigerter Berechtigung angezeigt.

Ich do habe jedoch die Berechtigung, in /dir1 Zu schauen und auf enthaltene Dateien und Verzeichnisse zuzugreifen, einschließlich /dir1/dir2. Ich habe Schreibberechtigung für dir2. Also wird touch /dir1/dir2/somefileerfolgreich sein, obwohl ich keine Schreibberechtigung für dir1 Habe.

Gleiches gilt für Datenbanken und Schemata.

19
Craig Ringer

Wenn Sie nur verhindern möchten, dass neue Benutzer Tabellen erstellen, müssen Sie den folgenden Befehl ausführen:

REVOKE CREATE ON SCHEMA public FROM public;

Wenn du REVOKE ALL (wie andere Antworten vermuten lassen), verhindern Sie auch, dass Benutzer über USAGE Berechtigungen verfügen. USAGE bedeutet, dass Benutzer die ihnen zugewiesenen Berechtigungen verwenden können. Wenn Sie diese entfernen, können Ihre Benutzer keine Tabellen auflisten oder darauf zugreifen, auf die sie Zugriff haben.

Alternativ können Sie auch REVOKE CREATE für einen bestimmten Benutzer:

REVOKE CREATE ON schema public FROM myuser;

Siehe auch: So erstellen Sie einen schreibgeschützten Benutzer mit PostgreSQL .

7
Adrian Macneil