¿Qué hace exactamente GRANT USAGE ON SCHEMA?

121

Estoy tratando de crear por primera vez una base de datos de Postgres, por lo que probablemente esta sea una pregunta estúpida. Asigné permisos básicos de solo lectura al rol db que debe acceder a la base de datos desde mis scripts php, y tengo una curiosidad: si ejecuto

GRANT some_or_all_privileges ON ALL TABLES IN SCHEMA schema TO role;

¿Hay alguna necesidad de ejecutar también

GRANT USAGE ON SCHEMA schema TO role;

?

De la documentación :

USO: Para esquemas, permite el acceso a los objetos contenidos en el esquema especificado (asumiendo que también se cumplen los requisitos de privilegios propios de los objetos). Básicamente, esto permite al beneficiario "buscar" objetos dentro del esquema.

Creo que si puedo seleccionar o manipular cualquier dato contenido en el esquema, puedo acceder a cualquier objeto del esquema en sí. ¿Me equivoco? Si no es así, ¿ GRANT USAGE ON SCHEMApara qué se utiliza? ¿Y qué significa exactamente la documentación con "asumir que también se cumplen los requisitos de privilegios de los objetos"?

Marco Sulla
fuente

Respuestas:

126

GRANTs en diferentes objetos están separados. GRANTing en una base de datos no tiene GRANTderechos sobre el esquema dentro. De manera similar, usar GRANTun esquema no otorga derechos sobre las tablas que contiene.

Si tiene derechos para SELECTacceder a una tabla, pero no el derecho para verla en el esquema que la contiene, no podrá acceder a la tabla.

Las pruebas de derechos se realizan en orden:

Do you have `USAGE` on the schema? 
    No:  Reject access. 
    Yes: Do you also have the appropriate rights on the table? 
        No:  Reject access. 
        Yes: Check column privileges.

Su confusión puede surgir del hecho de que el publicesquema tiene un valor predeterminado GRANTde todos los derechos sobre el rol public, del cual todos los usuarios / grupos son miembros. Entonces, todos ya tienen uso en ese esquema.

La frase:

(suponiendo que también se cumplan los requisitos de privilegios propios de los objetos)

Está diciendo que debe tener USAGEun esquema para usar objetos dentro de él, pero tener USAGEun esquema no es suficiente por sí mismo para usar los objetos dentro del esquema, también debe tener derechos sobre los objetos en sí.

Es como un árbol de directorios. Si crea un directorio somedircon un archivo somefiledentro de él, configúrelo para que solo su propio usuario pueda acceder al directorio o al archivo (modo rwx------en el directorio, modo rw-------en el archivo), entonces nadie más puede listar el directorio para ver que el archivo existe.

Si concediera derechos de lectura mundial sobre el archivo (modo rw-r--r--) pero no cambiara los permisos del directorio, no habría ninguna diferencia. Nadie pudo ver el archivo para leerlo, porque no tiene los derechos para listar el directorio.

Si, en cambio, establece rwx-r-xr-xel directorio, configurándolo para que las personas puedan enumerar y recorrer el directorio pero sin cambiar los permisos del archivo, las personas podrían enumerar el archivo pero no podrían leerlo porque no tendrían acceso al archivo.

Debe establecer ambos permisos para que las personas puedan ver el archivo.

Lo mismo en la pág. Necesita tanto USAGEderechos de esquema como derechos de objeto para realizar una acción en un objeto, como SELECTdesde una tabla.

(La analogía cae un poco en el sentido de que PostgreSQL aún no tiene seguridad a nivel de fila, por lo que el usuario aún puede "ver" que la tabla existe en el esquema al SELECTingresar pg_classdirectamente. No pueden interactuar con ella de ninguna manera , sin embargo, es solo la parte de la "lista" la que no es exactamente la misma).

Craig Ringer
fuente
2
Ahora está muy claro con el ejemplo del directorio :) Debo decir que esto es un problema si inserta alguna tabla o fila con un superusuario, por ejemplo cuando agrega postGIS usando CREATE EXTENSION. Es más o menos el mismo problema con los archivos creados en Linux mientras estás su. Sería bueno si hay una especie de sudo -edeclaraciones for en pqsl.
Marco Sulla
De todos modos ahora me di cuenta de que las GRANTdeclaraciones que no son específicas para tablas no son lo que quiero, ya que afectan a todas las bases de datos ...: s
Marco Sulla
1
@LucasMalor Er ... no, no lo hacen. GRANTen un esquema afecta a ese esquema. GRANT ... ON ALL TABLES IN SCHEMA ...afecta a todas las tablas de un esquema en una base de datos en particular. No hay correos GRANTelectrónicos que afecten a todas las bases de datos (está bien, excepto GRANTla pertenencia a un rol de un usuario).
Craig Ringer
Ah, perdón, ejecuté las declaraciones cuando estaba registrado como superusuario "postgres" y afectaron la base de datos "postgres". Pensé que si corres psqlsin -d dbestar operando "fuera" de cualquier base de datos, pero siempre estás conectado a una base de datos y de forma predeterminada estás conectado a la base de datos con el mismo nombre de tu función. db = role = user = group ... es un poco confuso: D
Marco Sulla
@LucasMalor Piénsalo de esta manera. De forma predeterminada, se conecta a una base de datos con el mismo nombre que el rol de inicio de sesión ("usuario") con el que se conecta. Los "usuarios" son solo roles que tienen WITH LOGIN; Básicamente, todo puede ser un grupo, y los grupos se pueden configurar para poder iniciar sesión.
Craig Ringer
72

Para un sistema de producción, puede utilizar esta configuración:

--ACCESS DB
REVOKE CONNECT ON DATABASE nova FROM PUBLIC;
GRANT  CONNECT ON DATABASE nova  TO user;

--ACCESS SCHEMA
REVOKE ALL     ON SCHEMA public FROM PUBLIC;
GRANT  USAGE   ON SCHEMA public  TO user;

--ACCESS TABLES
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC ;
GRANT SELECT                         ON ALL TABLES IN SCHEMA public TO read_only ;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write ;
GRANT ALL                            ON ALL TABLES IN SCHEMA public TO admin ;
bilelovitch
fuente
¿No admindebería otorgarse también CREATEen el esquema?
Dan
2
Los accesos se asignan según un modelo jerárquico: BD -> ESQUEMA -> TABLAS . Con GRANT USAGE ON SCHEMA, el usuario administrador no puede crear una tabla, pero puede hacerlo con ALL GRANT ALL ON SCHEMA....
bilelovitch
@bilelovitch: ¿quieres decir grant all on schema public to admin? PD: agregué también grant usage, select on all sequences in schema public to read_only/read_write; grant execute on all functions in schema public to read_only/read_write;
Marco Sulla
2

Bueno, esta es mi solución final para una base de datos simple, para Linux:

# Read this before!
#
# * roles in postgres are users, and can be used also as group of users
# * $ROLE_LOCAL will be the user that access the db for maintenance and
#   administration. $ROLE_REMOTE will be the user that access the db from the webapp
# * you have to change '$ROLE_LOCAL', '$ROLE_REMOTE' and '$DB'
#   strings with your desired names
# * it's preferable that $ROLE_LOCAL == $DB

#-------------------------------------------------------------------------------

//----------- SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - START ----------//

cd /etc/postgresql/$VERSION/main
sudo cp pg_hba.conf pg_hba.conf_bak
sudo -e pg_hba.conf

# change all `md5` with `scram-sha-256`
# save and exit

//------------ SKIP THIS PART UNTIL POSTGRES JDBC ADDS SCRAM - END -----------//

sudo -u postgres psql

# in psql:
create role $ROLE_LOCAL login createdb;
\password $ROLE_LOCAL
create role $ROLE_REMOTE login;
\password $ROLE_REMOTE

create database $DB owner $ROLE_LOCAL encoding "utf8";
\connect $DB $ROLE_LOCAL

# Create all tables and objects, and after that:

\connect $DB postgres

revoke connect on database $DB from public;
revoke all on schema public from public;
revoke all on all tables in schema public from public;

grant connect on database $DB to $ROLE_LOCAL;
grant all on schema public to $ROLE_LOCAL;
grant all on all tables in schema public to $ROLE_LOCAL;
grant all on all sequences in schema public to $ROLE_LOCAL;
grant all on all functions in schema public to $ROLE_LOCAL;

grant connect on database $DB to $ROLE_REMOTE;
grant usage on schema public to $ROLE_REMOTE;
grant select, insert, update, delete on all tables in schema public to $ROLE_REMOTE;
grant usage, select on all sequences in schema public to $ROLE_REMOTE;
grant execute on all functions in schema public to $ROLE_REMOTE;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on tables to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on sequences to $ROLE_LOCAL;

alter default privileges for role $ROLE_LOCAL in schema public
    grant all on functions to $ROLE_LOCAL;

alter default privileges for role $ROLE_REMOTE in schema public
    grant select, insert, update, delete on tables to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant usage, select on sequences to $ROLE_REMOTE;

alter default privileges for role $ROLE_REMOTE in schema public
    grant execute on functions to $ROLE_REMOTE;

# CTRL+D
Marco Sulla
fuente
1
¿Qué usuario debe usarse para "# Crear todas las tablas y objetos, y luego:"? ¿Quién es el dueño de las mesas y otros objetos en su caso?
Christophe Furmaniak
@ChristopheFurmaniak tienes razón, corregí el proceso. El propietario de la base de datos y sus objetos es $ ROLE_LOCAL y, después de crear la estructura de la base de datos, debemos volver al superusuario de postgres.
Marco Sulla
Creo que tiene un problema en los comandos "ALTER DEFAULT PRIVILEGES ...". Este comando se utiliza para activar la concesión de privilegios a un usuario (función) cuando un usuario diferente (función) crea un objeto. Consulte la página 11, sección 7.1, de este documento para obtener una aclaración. Actualmente, su ROLE_REMOTE no tendrá acceso a ningún objeto que ROLE_LOCAL crearía. Los comandos ROLE_LOCAL solo brindan privilegios que el rol ya tiene como propietario de esos objetos. Lo mismo ocurre con los comandos ROLE_REMOTE.
emispowder