2011-02-07 16 views
6

Estoy usando un servidor postgresql y quiero prohibir a mis usuarios ver qué otras bases de datos están en el mismo servidor.Permitir que el usuario de postgres solo muestre su propia base de datos

Esencialmente un \l solo debe incluir su propia base de datos.

Estoy bastante seguro de que hay un derecho que debo revocar del usuario pero no puedo encontrarlo en los documentos.

+0

¿Por qué no tener varias instancias ejecutándose a la vez? –

+0

Necesito ejecutarlos todos en el mismo puerto. – Kai

Respuesta

4

Esto parece funcionar, pero podría tener consecuencias imprevistas. Requiere retoques con los catálogos del sistema, ¡lo cual no es realmente una buena idea!

En primer lugar, usted tiene que permitir superusuarios para actualizar los catálogos del sistema añadiendo esto a su configuración de PostgreSQL:

allow_system_table_mods = on 

y reinicie.

Ahora, puede usar las sentencias DDL para modificar los catálogos del sistema (debe tener miedo). Conectarse a una de las bases de datos de usuario (una prueba de uno sería una buena idea) y:

alter table pg_catalog.pg_database rename to pg_database_catalog; 
create view pg_catalog.pg_database as 
    select oid, 1262::oid as tableoid, pg_database_catalog.* 
    from pg_catalog.pg_database_catalog 
    where has_database_privilege(pg_database_catalog.oid, 'connect');  
grant select on pg_catalog.pg_database to public; 

Ahora debe encontrar que si se conecta a que base de datos como un usuario bajo priv, el comando \l se simplemente liste las bases de datos a las que ese usuario se puede conectar.

El problema es que ahora necesita adivinar a qué base de datos se conectan inicialmente los usuarios para recuperar su lista de bases de datos. Si se conectan a su propia base de datos inicialmente, entonces probablemente termines en este punto. Si se conectan primero al postgres o al template1, debe realizar este cambio en esa base de datos.

Me parece que esto debería funcionar, ya que el catálogo pg_database es referido por postgres backends directamente por oid, en lugar de por nombre, por lo que moverlo fuera del camino y cambiar las filas que se muestran en él debería ser invisible para ellos En particular, no puede evitar que el servidor distinga al usuario entre una base de datos que no existe y los que no tienen privilegio de conexión.

No voy a hacer ninguna promesa de que este tipo de cambio no arruine algo más en el futuro. Si se rompe, tienes que guardar las piezas.

Probablemente desee hacer este cambio en una base de datos de plantillas, y crear bases de datos de usuarios a partir de ese momento, y desactivar la configuración allow_system_table_mods cuando haya terminado (lo que requiere un reinicio del servidor, recuerde).

Además, probé esto en 9.0: me parece que también debería funcionar en algunas versiones anteriores, caveat emptor.

+0

Acabo de probar esto. Parece que está funcionando. Muchas muchas gracias. – Kai

+0

Ok, rompió algo :) pg_dump y pg_dumpall ya no funcionan. El error es "Mensaje de error del servidor: ERROR: la columna" tableoid "no existe" El comando fue: SELECCIONE tableoid, oid, (SELECT rolname FROM pg_catalog.pg_roles WHERE oid = datdba) AS dba, pg_encoding_to_char (codificación) COMO codificación, datcollate, datctype, datfrozenxid, (SELECCIONAR spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, shobj_description (oid, 'pg_database') AS description FROM pg_database WHERE datname = 'test_1' – Kai

+0

Sería realmente increíble si pudiera ayudarme para arreglar esto, porque aparte de esto, tu solución funciona simplemente genial. – Kai

1

No existe tal configuración en pgsql. Hay configuraciones para evitar que los usuarios se conecten a bases de datos que no deberían (otorgar/revocar conectar). Poder ver que hay una base de datos no es gran cosa. Poder conectar/tener derechos de edición, etc. es.

+0

Bueno, es algo malo si hay personas ejecutando el software frontend en estas bases de datos que, durante la configuración, obtiene una lista de todas las bases de datos disponibles y solicita al usuario para siempre una base de datos a la que no tiene derecho de acceso. El problema es que no puedo cambiar ese comportamiento y tengo que lidiar con él de alguna manera. – Kai

+5

Dependiendo del contexto que sea capaz de ver otras bases de datos _es_ un gran problema. Es una pérdida de datos. No veo por qué un usuario debería ver alguna vez una base de datos que no le interese ... – harmv

+0

Una declaración no necesariamente hace que su argumento sea correcto. Si el usuario no puede acceder a la base de datos entonces verlo no es gran cosa. Los datos no se están filtrando. Los datos son lo que almacena en un db, no el nombre del db. Si lo que necesita es que los usuarios no sepan qué otras bases de datos hay en un sistema, entonces necesita configurar un clúster para cada usuario, de modo que tengan su propio clúster de db para iniciar sesión. –

1

Me imagino que esto podría tener repercusiones negativas para el usuario, como no poder conectarse a la base de datos ya que el sistema no tiene acceso a las tablas del sistema, aunque no estoy seguro. Pero en cuanto a averiguar qué tabla revocar, esta es una buena manera general de ver qué hacen los comandos meta psql:

Para ver lo que \l está haciendo, también puede usar el indicador -E de la línea de comandos con psql .

~$ psql -E -c '\l' 
********* QUERY ********** 
SELECT d.datname as "Name", 
     pg_catalog.pg_get_userbyid(d.datdba) as "Owner", 
     pg_catalog.pg_encoding_to_char(d.encoding) as "Encoding", 
     d.datcollate as "Collation", 
     d.datctype as "Ctype", 
     pg_catalog.array_to_string(d.datacl, E'\n') AS "Access privileges" 
FROM pg_catalog.pg_database d 
ORDER BY 1; 
************************** 

lo tanto, si el usuario no tiene acceso a pg_database que no será capaz de utilizar el comando \ l.

Cuestiones relacionadas