Come si crea un utente di sola lettura in PostgreSQL?


420

Mi piacerebbe creare un utente in PostgreSQL che può fare solo SELECT da un determinato database. In MySQL il comando sarebbe:

GRANT SELECT ON mydb.* TO 'xxx'@'%' IDENTIFIED BY 'yyy';

Qual è il comando equivalente o serie di comandi in PostgreSQL?

Provai...

postgres=# CREATE ROLE xxx LOGIN PASSWORD 'yyy';
postgres=# GRANT SELECT ON DATABASE mydb TO xxx;

Ma sembra che le uniche cose che puoi concedere su un database siano CREATE, CONNECT, TEMPORARY e TEMP.

Risposte:


641

Concedi l'utilizzo / seleziona una singola tabella

Se si concede CONNECT solo a un database, l'utente può connettersi ma non ha altri privilegi. Devi concedere USAGE su spazi dei nomi (schemi) e SELECT su tabelle e viste singolarmente in questo modo:

GRANT CONNECT ON DATABASE mydb TO xxx;
-- This assumes you're actually connected to mydb..
GRANT USAGE ON SCHEMA public TO xxx;
GRANT SELECT ON mytable TO xxx;

Più tabelle / viste (PostgreSQL 9.0+)

Nelle ultime versioni di PostgreSQL, puoi concedere le autorizzazioni su tutte le tabelle / viste / etc nello schema usando un singolo comando invece di doverle digitare una per una:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Ciò riguarda solo le tabelle che sono già state create. Più efficacemente, in futuro puoi assegnare automaticamente ruoli predefiniti a nuovi oggetti :

ALTER DEFAULT PRIVILEGES IN SCHEMA public
   GRANT SELECT ON TABLES TO xxx;

Si noti che per impostazione predefinita ciò influirà solo sugli oggetti (tabelle) creati dall'utente che ha emesso questo comando: sebbene possa anche essere impostato su qualsiasi ruolo di cui l'utente emittente è membro. Tuttavia, non acquisisci i privilegi predefiniti per tutti i ruoli di cui sei membro durante la creazione di nuovi oggetti ... quindi c'è ancora un po 'di confusione in giro. Se si adotta l'approccio secondo cui un database ha un ruolo proprietario e le modifiche dello schema vengono eseguite come tale ruolo proprietario, è necessario assegnare i privilegi predefiniti a quel ruolo proprietario. IMHO questo è un po 'confuso e potrebbe essere necessario sperimentare per elaborare un flusso di lavoro funzionale.

Più tabelle / viste (versioni PostgreSQL precedenti alla 9.0)

Per evitare errori nelle modifiche lunghe e multi-tabella, si consiglia di utilizzare il seguente processo "automatico" per generare il necessario GRANT SELECTper ogni tabella / vista:

SELECT 'GRANT SELECT ON ' || relname || ' TO xxx;'
FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
WHERE nspname = 'public' AND relkind IN ('r', 'v', 'S');

Questo dovrebbe generare i comandi GRANT pertinenti su GRANT SELECT su tutte le tabelle, viste e sequenze in pubblico, per amore di copia-incolla. Naturalmente, questo verrà applicato solo alle tabelle che sono già state create.


22
Dovresti mettere la tua modifica relativa a PG9 in cima al post.
Danilo Bargen,

5
Bello. Una cosa che aggiungerei è che potrebbe essere necessario consentire all'utente di leggere le sequenze; quindi: SELEZIONA CONCESSIONE SU TUTTE LE SEQUENZE DI SCHEMA pubbliche su xxx;
JJC

26
Nota che per impedire a questo utente di creare nuove tabelle, ho dovuto farlo REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Senza ciò, l'utente "sola lettura" non potrebbe modificare le tabelle esistenti, ma potrebbe creare nuove tabelle nello schema e aggiungere / rimuovere i dati da tali tabelle.
Ajedi32,

3
@ Ajedi32 Questo dovrebbe essere parte della risposta accettata! Grazie
Asfand Qazi,

12
Per i neofiti come me penso che valga la pena ricordare che dovresti avviare la console usando psql mydbaltrimenti la maggior parte di queste manipolazioni non lo farebbe. Personalmente mi ci è voluto molto tempo per capirlo da solo. Spero che questo aiuti qualcuno.
Anass,

41

Nota che PostgreSQL 9.0 (oggi in beta test) avrà un modo semplice per farlo :

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;

3
Ho dovuto essere nel database specifico per far funzionare tutto questo. Postgresql 9.5.
user1158559

8
Questo funziona solo per le tabelle esistenti nello schema. Se in seguito l'utente di scrittura crea o sostituisce tabelle, l'utente di sola lettura non avrà accesso ad esse
anneb

33

Riferimento tratto da questo blog:

Script per creare l'utente di sola lettura:

CREATE ROLE Read_Only_User WITH LOGIN PASSWORD 'Test1234' 
NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE NOREPLICATION VALID UNTIL 'infinity';

Assegna l'autorizzazione a questo utente di sola lettura:

GRANT CONNECT ON DATABASE YourDatabaseName TO Read_Only_User;
GRANT USAGE ON SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO Read_Only_User;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO Read_Only_User;

Assegna le autorizzazioni per leggere tutte le nuove tabelle create in futuro

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;

6
Questa è un'ottima risposta tranne una cosa mancante: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; che consentirebbe anche di leggere tutte le tabelle create nello stesso DB in futuro.
Ravbaker,

2
È insolito consentire a un utente di sola lettura l'accesso alle sequenze. La lettura della sequenza lo aggiorna e in genere sono necessari solo per INSERTs.
jpmc26,

Per completezza, eventualmente aggiungere:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi,

@ jpmc26: vuol dire che vi consigliamo: GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User?
Fabien Haddadi,

@FabienHaddadi Significa che, a meno che tu non ne abbia alcuni fuori dall'ordinario, non vedo la necessità di concedere autorizzazioni per le sequenze a un utente di sola lettura.
jpmc26,

24

Ecco il modo migliore che ho trovato per aggiungere utenti di sola lettura (usando PostgreSQL 9.0 o versioni successive):

$ sudo -upostgres psql postgres
postgres=# CREATE ROLE readonly WITH LOGIN ENCRYPTED PASSWORD '<USE_A_NICE_STRONG_PASSWORD_PLEASE';
postgres=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;

Quindi accedere a tutte le macchine correlate (master + read-slave (s) / hot-standby (s), ecc.) Ed eseguire:

$ echo "hostssl <PUT_DBNAME_HERE> <PUT_READONLY_USERNAME_HERE> 0.0.0.0/0 md5" | sudo tee -a /etc/postgresql/9.2/main/pg_hba.conf
$ sudo service postgresql reload

2
Mi piace l'approccio ma avevo anche bisogno di CONNETTERE IL DATABASE [il database] A [l'utente o il ruolo]; e CONCEDERE L'UTILIZZO SU SCHEMA pubblico a [l'utente o il ruolo];
Ian Connor,

1
Lo schema pubblico consente ancora a tale utente di creare tabelle. Inoltre, le nuove tabelle non sono coperte, né le sequenze. Sfortunatamente, questo è un po 'più complicato di così. : - / Pubblicherò quello che ho finito dopo averlo convalidato ancora un po '.
JJC il

Nel tuo script sopra stai cercando di creare il ruolo due volte. Sospetto che tu abbia intenzione di utilizzare "ALTER ROLE ..." quando abiliti il ​​ruolo per il login e imposti la password
Bogdan,

Se hai già l'utente, dopo aver creato il ruolo di sola lettura e concedere permessi di selezione concedi all'utente il nuovo ruolo: CONCESSIONE sola a <USER>
gonz,

18

Per impostazione predefinita, i nuovi utenti avranno l'autorizzazione per creare tabelle. Se stai pensando di creare un utente di sola lettura, questo probabilmente non è quello che desideri.

Per creare un vero utente di sola lettura con PostgreSQL 9.0+, eseguire le seguenti operazioni:

# This will prevent default users from creating tables
REVOKE CREATE ON SCHEMA public FROM public;

# If you want to grant a write user permission to create tables
# note that superusers will always be able to create tables anyway
GRANT CREATE ON SCHEMA public to writeuser;

# Now create the read-only user
CREATE ROLE readonlyuser WITH LOGIN ENCRYPTED PASSWORD 'strongpassword';
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonlyuser;

Se l'utente di sola lettura non dispone dell'autorizzazione per elencare le tabelle (ovvero \dnon restituisce risultati), è probabilmente perché non si dispone delle USAGEautorizzazioni per lo schema. USAGEè un'autorizzazione che consente agli utenti di utilizzare effettivamente le autorizzazioni che sono state loro assegnate. Che senso ha questo? Non ne sono sicuro. Aggiustare:

# You can either grant USAGE to everyone
GRANT USAGE ON SCHEMA public TO public;

# Or grant it just to your read only user
GRANT USAGE ON SCHEMA public TO readonlyuser;

8

Ho creato uno script conveniente per quello; pg_grant_read_to_db.sh . Questo script concede i privilegi di sola lettura a un ruolo specificato su tutte le tabelle, viste e sequenze in uno schema di database e li imposta come predefiniti.


4

Ho letto tutte le possibili soluzioni, che vanno bene se ricordi di collegarti al database prima di concedere le cose;) Grazie comunque a tutte le altre soluzioni !!!

user@server:~$ sudo su - postgres

creare l'utente psql:

postgres@server:~$ createuser --interactive 
Enter name of role to add: readonly
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n

avvia psql cli e imposta una password per l'utente creato:

postgres@server:~$ psql
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
Type "help" for help.

postgres=# alter user readonly with password 'readonly';
ALTER ROLE

connettersi al database di destinazione:

postgres=# \c target_database 
psql (10.6 (Ubuntu 10.6-0ubuntu0.18.04.1), server 9.5.14)
You are now connected to database "target_database" as user "postgres".

concedere tutti i privilegi necessari:

target_database=# GRANT CONNECT ON DATABASE target_database TO readonly;
GRANT

target_database=# GRANT USAGE ON SCHEMA public TO readonly ;
GRANT

target_database=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly ;
GRANT

alterare i privilegi di default per target db public shema:

target_database=# ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
ALTER DEFAULT PRIVILEGES

3

Se il tuo database è nello schema pubblico, è facile (questo presuppone che tu abbia già creato il readonlyuser)

db=> GRANT SELECT ON ALL TABLES IN SCHEMA public to readonlyuser;
GRANT
db=> GRANT CONNECT ON DATABASE mydatabase to readonlyuser;
GRANT
db=> GRANT SELECT ON ALL SEQUENCES IN SCHEMA public to readonlyuser;
GRANT

Se il tuo database sta utilizzando customschema, esegui quanto sopra ma aggiungi un altro comando:

db=> ALTER USER readonlyuser SET search_path=customschema, public;
ALTER ROLE

1

Il modo non semplice di farlo sarebbe garantire la selezione su ogni tabella del database:

postgres=# grant select on db_name.table_name to read_only_user;

È possibile automatizzare ciò generando le dichiarazioni di sovvenzione dai metadati del database.


1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;

0

Tratto da un link pubblicato in risposta al link di despesz .

Postgres 9.x sembra avere la capacità di fare ciò che è richiesto. Vedi il paragrafo Grant On Database Objects di:

http://www.postgresql.org/docs/current/interactive/sql-grant.html

Dove dice: "Esiste anche un'opzione per concedere privilegi su tutti gli oggetti dello stesso tipo all'interno di uno o più schemi. Questa funzionalità è attualmente supportata solo per tabelle, sequenze e funzioni (ma si noti che TUTTE LE TABELLE sono considerate includere viste e tavoli stranieri). "

Questa pagina illustra anche l'uso dei ruoli e un PRIVILEGE chiamato "TUTTI I PRIVILEGI".

Sono presenti anche informazioni su come le funzionalità GRANT si confrontano con gli standard SQL.

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.