Perché un nuovo utente è autorizzato a creare una tabella?


41

Mi chiedo perché un utente appena creato sia autorizzato a creare una tabella dopo essersi connesso a un database. Ho un database 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)

Fin qui tutto bene. Ora creo un utente:

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

Va bene. Quando provo a connettermi al database, l'utente non è autorizzato a farlo:

$ 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.

Questo è quello che mi aspettavo. Ora inizia la strana roba. Concedo all'utente 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)

E senza ulteriori sovvenzioni, l'utente è autorizzato a creare una tabella:

$ 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)

Mi sarei aspettato che l'utente non fosse autorizzato a fare nulla prima di fare esplicitamente GRANT USAGEsullo schema e quindi GRANT SELECTsulle tabelle.

Dov'è il mio errore? Che cosa sto facendo di sbagliato? Come posso ottenere ciò che voglio (che un nuovo utente non è autorizzato a fare nulla prima di concederle esplicitamente i diritti appropriati.

Mi sono perso e il tuo aiuto è molto apprezzato :)

MODIFICA Seguendo i consigli di @ daniel-verite, ora ho revocato tutto immediatamente dopo aver creato il database. L'utente dietrich non può più creare una tabella. Buono. MA : Ora, anche il proprietario del database, project2 , non è autorizzato a creare una tabella. Anche dopo l'emissione GRANT ALL PRIVILEGES ON DATABASE project2_core TO project2e GRANT ALL PRIVILEGES ON SCHEMA public TO project2, viene visualizzato un errore ERRORE: nessuno schema è stato selezionato per la creazione e, quando provo in modo specifico CREATE TABLE public.WHATEVER ();, ottengo ERRORE: autorizzazione negata per lo schema pubblico . Che cosa sto facendo di sbagliato?

Risposte:


38

Quando si crea un nuovo database, a qualsiasi ruolo è consentito creare oggetti nello publicschema. Per rimuovere questa possibilità, è possibile emettere immediatamente dopo la creazione del database:

REVOKE ALL ON schema public FROM public;

Modifica: dopo il comando sopra, solo un superutente può creare nuovi oggetti all'interno dello publicschema, il che non è pratico. Supponendo che un non-superutente foo_userdovrebbe avere questo privilegio, questo dovrebbe essere fatto con:

GRANT ALL ON schema public TO foo_user;

Per sapere cosa ALLsignifica uno schema, dobbiamo fare riferimento a GRANT nel documento (in PG 9.2 non ci sono meno di 14 forme di istruzioni GRANT che si applicano a cose diverse ...). Sembra che per uno schema significhi CREATEe USAGE.

D'altra parte, GRANT ALL PRIVILEGES ON DATABASE...garantirà CONNECTe CREATEe TEMP, ma CREATEin questo contesto si riferisce a schemi, non a tabelle permanenti.

Per quanto riguarda questo errore ERROR: no schema has been selected to create in:, accade quando si tenta di creare un oggetto senza qualifica di schema (come in create table foo(...)) mentre manca l'autorizzazione per crearlo in qualsiasi schema di search_path.


funziona :) Ma ancora non capisco: ci ho già provato REVOKE ALL ON DATABASE project2_core FROM PUBLIC;. perché questo non ha avuto alcun effetto?
andreas-h

mhh. ora il proprietario del database non è più autorizzato CREATE TABLE. vedi la mia modifica sopra.
andreas-h

@ andreas-h: modifica la risposta con maggiori dettagli
Daniel Vérité,

Per quanto riguarda l'errore, può essere facilmente riprodotto emettendo i comandi dalla domanda e il tuo REVOKE in ordine :)
dezso

@ DanielVérité Ho elaborato i concetti alla base di questo in una nuova risposta per integrare la tua. Un controllo di integrità sarebbe valutato.
Craig Ringer,

19

La cosa cruciale da capire qui è che i privilegi non sono erirachici e non sono ereditati dal contenere oggetti . ALLindica tutti i privilegi per questo oggetto, non tutti i privilegi per questo oggetto e tutti gli oggetti contenuti .

Quando concedi ALLsu un database, lo concedi CREATE, CONNECT, TEMP. Queste sono azioni sull'oggetto database stesso:

  • CONNECT: Connettersi al DB
  • CREATE: Crea uno schema ( non una tabella)
  • TEMP: Crea oggetti temporanei, incluso ma non limitato a tabelle temporanee

Ora, per impostazione predefinita, ogni database PostgreSQL ha uno publicschema creato al momento della creazione del database. Questo schema ha tutti i diritti concessi al ruolo public, di cui tutti sono implicitamente membri. Per uno schema, ALLsignifica CREATE, USAGE:

  • CREATE: Crea oggetti (comprese le tabelle) all'interno di questo schema
  • USAGE: Elenca gli oggetti nello schema e accede ad essi se le loro autorizzazioni lo consentono

Se non si specifica lo schema per la creazione di un oggetto come una tabella, il motore di database utilizza il search_path, e per impostazione predefinita lo publicschema è il primo sul search_pathmodo in cui la tabella viene creata lì. Tutti hanno i diritti di publicdefault, quindi la creazione è consentita. I diritti degli utenti sul database sono irrilevanti a questo punto, poiché l'utente non sta tentando di fare nulla all'oggetto del database da solo, ma solo uno schema al suo interno.

Non importa che tu non abbia concesso all'utente altri diritti oltre alla concessione CONNECTsul database, perché lo publicschema consente a tutti gli utenti di creare tabelle in esso per impostazione predefinita. Daniel ha già spiegato come revocare tale diritto se lo si desidera.

Se si desidera delegare esplicitamente ogni diritto, revocare tutto dal pubblico o eliminare semplicemente lo schema pubblico. È possibile creare un nuovo database di modelli con questa modifica applicata, se lo si desidera. In alternativa, puoi applicarlo a template1, ma probabilmente si romperà un sacco di codice di terze parti che presume che publicesista ed è scrivibile.


Questo potrebbe avere più senso se guardi un'analogia del filesystem.

Se ho la struttura della directory (modalità semplificata per mostrare solo la modalità che si applica all'utente corrente):

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

quindi non riesco a creare nulla all'interno /dir1, perché non ho il permesso di scrittura. Quindi se avrò touch /dir1/somefileun errore negato l'autorizzazione.

Tuttavia, ho fare avere il permesso di guardare dentro /dir1e per accedere a file e directory, tra cui contenuti /dir1/dir2. Ho il permesso di scrivere su dir2. Quindi touch /dir1/dir2/somefileci riuscirà , anche se non ho il permesso di scrivere dir1.

Stessa cosa con database e schemi.


7

Se si desidera solo impedire ai nuovi utenti di creare tabelle, è necessario eseguire il comando seguente:

REVOKE CREATE ON SCHEMA public FROM public;

Se REVOKE ALL(come suggeriscono altre risposte), impedirai anche agli utenti di disporre delle USAGEautorizzazioni. USAGEsignifica che gli utenti possono utilizzare le autorizzazioni loro assegnate, quindi se lo rimuovi, i tuoi utenti non saranno in grado di elencare o accedere alle tabelle a cui hanno accesso.

In alternativa, potresti anche REVOKE CREATEper un utente specifico:

REVOKE CREATE ON schema public FROM myuser;

Vedi anche: Come creare un utente di sola lettura con PostgreSQL .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.