¿Cómo se crea un usuario de solo lectura en PostgreSQL?

420

Me gustaría crear un usuario en PostgreSQL que solo pueda hacer SELECT desde una base de datos en particular. En MySQL el comando sería:

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

¿Cuál es el comando equivalente o serie de comandos en PostgreSQL?

Lo intenté...

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

Pero parece que las únicas cosas que puede otorgar en una base de datos son CREATE, CONNECT, TEMPORARY y TEMP.

Ethan
fuente

Respuestas:

641

Conceder uso / seleccionar a una sola tabla

Si solo concede CONNECT a una base de datos, el usuario puede conectarse pero no tiene otros privilegios. Debe otorgar USAGE en espacios de nombres (esquemas) y SELECT en tablas y vistas individualmente de la siguiente manera:

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;

Múltiples tablas / vistas (PostgreSQL 9.0+)

En las últimas versiones de PostgreSQL, puede otorgar permisos en todas las tablas / vistas / etc. en el esquema utilizando un solo comando en lugar de tener que escribirlos uno por uno:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO xxx;

Esto solo afecta a las tablas que ya se han creado. Más poderosamente, puede tener automáticamente roles predeterminados asignados a nuevos objetos en el futuro:

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

Tenga en cuenta que, de manera predeterminada, esto solo afectará a los objetos (tablas) creados por el usuario que emitió este comando: aunque también se puede establecer en cualquier rol del que sea miembro el usuario emisor. Sin embargo, no obtienes privilegios predeterminados para todos los roles de los que eres miembro al crear nuevos objetos ... por lo que todavía hay algunas dudas. Si adopta el enfoque de que una base de datos tiene un rol propietario, y los cambios de esquema se realizan como ese rol propietario, entonces debe asignar privilegios predeterminados a ese rol propietario. En mi humilde opinión, todo esto es un poco confuso y es posible que deba experimentar para obtener un flujo de trabajo funcional.

Múltiples tablas / vistas (versiones de PostgreSQL anteriores a 9.0)

Para evitar errores en los largos cambios de varias tablas, se recomienda utilizar el siguiente proceso 'automático' para generar lo requerido GRANT SELECTpara cada tabla / 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');

Esto debería generar los comandos GRANT relevantes para GRANT SELECT en todas las tablas, vistas y secuencias en público, para copiar y pegar amor. Naturalmente, esto solo se aplicará a las tablas que ya se han creado.

araqnid
fuente
22
Debes poner tu edición sobre PG9 en la parte superior de la publicación.
Danilo Bargen
55
Agradable. Una cosa que agregaría es que también es posible que deba permitir que este usuario lea las secuencias; entonces: OTORGAR SELECCIONAR EN TODAS LAS SECUENCIAS EN SCHEMA public TO xxx;
JJC
26
Tenga en cuenta que para evitar que este usuario pueda crear nuevas tablas, tuve que hacerlo REVOKE CREATE ON SCHEMA public FROM PUBLIC;. Sin eso, el usuario "solo lectura" no podría modificar las tablas existentes, pero podría crear nuevas tablas en el esquema y agregar / eliminar datos de esas tablas.
Ajedi32
3
@ Ajedi32 ¡Esto debería ser parte de la respuesta aceptada! Gracias
Asfand Qazi
12
Para los novatos como yo, creo que vale la pena mencionar que deberías iniciar la consola usando de lo psql mydbcontrario la mayoría de estas manipulaciones no lo harían. Personalmente me llevó una cantidad considerable de tiempo resolverlo por mi cuenta. Espero que esto ayude a alguien.
Anass
41

Tenga en cuenta que PostgreSQL 9.0 (hoy en pruebas beta) tendrá una forma simple de hacerlo :

test=> GRANT SELECT ON ALL TABLES IN SCHEMA public TO joeuser;
bortzmeyer
fuente
3
Tenía que estar en la base de datos específica para que esto funcione. Postgresql 9.5.
user1158559
8
Esto funciona solo para tablas existentes en el esquema. Si el usuario de escritura luego crea o reemplaza tablas, el usuario de solo lectura no tendrá acceso a ellas
anneb
33

Referencia tomada de este blog:

Script para crear usuario de solo lectura:

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

Asigne permiso a este usuario de solo lectura:

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;

Asigne permisos para leer todas las tablas nuevas creadas en el futuro

ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User;
Anvesh
fuente
66
Esta es una muy buena respuesta, excepto una cosa que falta: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO Read_Only_User; que también permitiría leer todas las tablas creadas en el mismo DB en el futuro.
Ravbaker
2
Es inusual permitir que un usuario de solo lectura acceda a las secuencias. La lectura de la secuencia la actualiza y, por lo general, solo se necesitan para INSERTs.
jpmc26
Para completar, posiblemente agregue:GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA schema_name TO Read_Only_User;
Fabien Haddadi
@ jpmc26: ¿eso significa que usted recomienda GRANT ALL ON ALL SEQUENCES IN SCHEMA schema_name TO Read_Only_User:?
Fabien Haddadi
@FabienHaddadi Significa que, a menos que tenga algunos requisitos fuera de lo común, no veo la necesidad de otorgar ningún permiso sobre secuencias a un usuario de solo lectura.
jpmc26
24

Aquí está la mejor manera que he encontrado para agregar usuarios de solo lectura (usando PostgreSQL 9.0 o más reciente):

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

Luego, inicie sesión en todas las máquinas relacionadas (maestro + esclavo (s) de lectura / espera (s), etc.) y ejecute:

$ 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
Jay Taylor
fuente
2
Me gusta el enfoque, pero también necesitaba CONCEDER CONNECT ON DATABASE [thedatabase] TO [theuser o role]; y OTORGAR USO EN EL ESQUEMA público A [el usuario o rol];
Ian Connor
1
El esquema público todavía permite que dicho usuario cree tablas. Además, las nuevas tablas no están cubiertas, ni las secuencias. Desafortunadamente, todo esto es bastante más complicado que esto. : - / Publicaré lo que terminé haciendo una vez que lo haya validado un poco más.
JJC
En su script anterior, está tratando de crear el rol dos veces. Sospecho que tenía la intención de usar "ALTER ROLE ..." al habilitar el rol para iniciar sesión y establecer la contraseña
Bogdan
Si ya tiene el usuario, después de crear la función de solo lectura y otorgar permisos de selección, otorgue la nueva función al usuario: CONCESIÓN de solo lectura A <USUARIO>
gonz
18

Por defecto, los nuevos usuarios tendrán permiso para crear tablas. Si planea crear un usuario de solo lectura, esto probablemente no sea lo que desea.

Para crear un verdadero usuario de solo lectura con PostgreSQL 9.0+, ejecute los siguientes pasos:

# 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;

Si su usuario de solo lectura no tiene permiso para enumerar tablas (es decir, \dno devuelve resultados), probablemente sea porque no tiene USAGEpermisos para el esquema. USAGEes un permiso que permite a los usuarios usar realmente los permisos que se les han asignado. ¿Cuál es el punto de esto? No estoy seguro. Arreglar:

# 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;
Adrian Macneil
fuente
8

He creado un script conveniente para eso; pg_grant_read_to_db.sh . Este script otorga privilegios de solo lectura a un rol específico en todas las tablas, vistas y secuencias en un esquema de base de datos y los establece como predeterminados.

Jakub Jirutka
fuente
4

Leí todas las soluciones posibles, que están bien, si recuerdas conectarte a la base de datos antes de conceder las cosas;) ¡Gracias de todos modos a todas las demás soluciones!

user@server:~$ sudo su - postgres

crear usuario 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

inicie psql cli y establezca una contraseña para el usuario creado:

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

conectarse a la base de datos de destino:

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

otorgue todos los privilegios necesarios:

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

alterar los privilegios predeterminados para objetivos db public shema:

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

Si su base de datos está en el esquema público, es fácil (esto supone que ya ha creado el 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

Si su base de datos está usando customschema, ejecute lo anterior pero agregue un comando más:

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

La forma no directa de hacerlo sería otorgar select en cada tabla de la base de datos:

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

Puede automatizar eso generando sus declaraciones de concesión a partir de los metadatos de la base de datos.

Pablo Santa Cruz
fuente
1
CREATE USER username SUPERUSER  password 'userpass';
ALTER USER username set default_transaction_read_only = on;
Viktor Viktor
fuente
0

Tomado de un enlace publicado en respuesta al enlace de despesz .

Postgres 9.x parece tener la capacidad de hacer lo que se solicita. Vea el párrafo Grant on Database Objects de:

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

Donde dice: "También hay una opción para otorgar privilegios a todos los objetos del mismo tipo dentro de uno o más esquemas. Actualmente, esta funcionalidad solo es compatible con tablas, secuencias y funciones (pero tenga en cuenta que TODAS LAS TABLAS se considera que incluye vistas) y tablas extranjeras) ".

Esta página también trata el uso de ROLES y un PRIVILEGIO llamado "TODOS LOS PRIVILEGIOS".

También se presenta información sobre cómo las funcionalidades GRANT se comparan con los estándares SQL.

kbulgrien
fuente