¿Cómo administrar PRIVILEGIOS PREDETERMINADOS para USUARIOS en una BASE DE DATOS vs ESQUEMA?

48

Quiero migrar una aplicación bastante simple, interna, impulsada por bases de datos de SQLite3 a PostgreSQL 9.3 y ajustar los permisos en la base de datos a medida que avanzo.

La aplicación actualmente consiste en un comando para actualizar los datos; y uno para consultarlo. Naturalmente, también necesitaré mantener la base de datos de otras maneras (crear nuevas tablas, vistas, disparadores, etc.).

Si bien esta aplicación será la única alojada en el servidor al principio, preferiría hornear asumiendo que podría estar alojada en un servidor con otras bases de datos en el futuro, en lugar de tener que codificar más tarde si es necesario. el futuro.

Creo que estos serían un conjunto de requisitos bastante común, pero tengo problemas para encontrar un tutorial simple que explique cómo configurar una nueva base de datos en PostgreSQL, con este tipo de separación de usuario / privilegio. Las referencias continúan extensamente sobre grupos, usuarios, roles, bases de datos, esquemas y dominio; pero los encuentro confusos.

Esto es lo que he intentado hasta ahora (desde adentro psqlcomo 'postgres'):

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;
\connect hostdb
CREATE SCHEMA hostdb;
CREATE USER hostdb_admin WITH PASSWORD 'youwish';
CREATE USER hostdb_mgr   WITH PASSWORD 'youwish2';
CREATE USER hostdb_usr WITH PASSWORD 'youwish3';

GRANT ALL PRIVILEGES ON DATABASE hostdb TO hostdb_admin;
GRANT CONNECT ON DATABASE hostdb TO hostdb_mgr, hostdb_usr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO hostdb_mgr;
ALTER DEFAULT PRIVILEGES IN SCHEMA hostdb GRANT SELECT ON TABLES TO hostdb_usr;

Pero no entiendo la semántica prevista. Quiero tenerlo configurado para que solo el hostdb_adminpueda crear (y soltar y alterar) tablas; la hostdb_mgrpuede leer, insertar, actualizar y borrar en todas las tablas por defecto; y hostdb_usrsolo puede leer todas las tablas (y vistas).

Cuando probé esto, descubrí que podía crear tablas hostdbcomo cualquiera de estos usuarios; pero, para cada usuario, solo podía leer o modificar tablas creadas por ese usuario, a menos que use un explícito GRANT.

Supongo que falta algo entre CREATE DATABASEy CREATE SCHEMA, algo para aplicar SCHEMAel DATABASE?

(A medida que las cosas avanzan, también tendré preguntas para aplicar restricciones similares TRIGGERS, procedimientos almacenados VIEWSy quizás otros objetos).

¿Dónde puedo encontrar una guía decente, un tutorial o una serie de videos sobre esto?

Jim Dennis
fuente
2
Creo que (al menos una parte de) su problema radica en el publicpseudorole. Se puede considerar como un rol del que es miembro cualquier otro rol (usuario, grupo, todos iguales). Intente quitarle los privilegios, por ejemplo REVOKE CREATE ON SCHEMA hostdb FROM public,. Revocar los derechos en el nivel de la base de datos, como lo hizo, solo deshabilita algunos permisos de nivel de base de datos, sin efecto en los esquemas o tablas.
dezso
@dezso: puede haber una idea errónea sobre los privilegios predeterminados para los esquemas. Solo el esquema predeterminado publicocurre con privilegios para PUBLIC. Aparte de eso, hay no hay privilegios por defecto para los nuevos esquemas. Por lo tanto, esto no afecta el caso de uso demostrado. Vea el capítulo en mi respuesta.
Erwin Brandstetter

Respuestas:

86

¿Dónde puedo encontrar una guía decente, un tutorial o una serie de videos sobre esto?

Encontrarás todo en el manual. Enlaces a continuación.
Por supuesto, el asunto no es trivial y, a veces, confuso. Aquí hay una receta para el caso de uso:

Receta

Quiero tenerlo configurado para que solo el hostdb_adminpueda crear (y soltar y alterar) tablas;
la hostdb_mgrpuede leer, insertar, actualizar y borrar en todas las tablas por defecto;
y hostdb_usrsolo puede leer todas las tablas (y vistas).

Como superusuario postgres:

CREATE USER schma_admin WITH PASSWORD 'youwish';
-- CREATE USER schma_admin WITH PASSWORD 'youwish' CREATEDB CREATEROLE; -- see below
CREATE USER schma_mgr   WITH PASSWORD 'youwish2';
CREATE USER schma_usr   WITH PASSWORD 'youwish3';

Si desea un administrador más poderoso que también pueda administrar bases de datos y roles, agregue los atributosCREATEDBCREATEROLE del rol y más arriba.

Otorgue cada rol al siguiente nivel superior, de modo que todos los niveles "hereden" al menos el conjunto de privilegios del siguiente nivel inferior (en cascada):

GRANT schma_usr TO schma_mgr;
GRANT schma_mgr TO schma_admin;

CREATE DATABASE hostdb;
REVOKE ALL ON DATABASE hostdb FROM public;  -- see notes below!

GRANT CONNECT ON DATABASE hostdb TO schma_usr;  -- others inherit

\connect hostdb  -- psql syntax

Estoy nombrando el esquema schma( hostdbque no sería confuso). Elige cualquier nombre. Opcionalmente, haga que schma_adminel propietario del esquema:

CREATE SCHEMA schma AUTHORIZATION schma_admin;

SET search_path = schma;  -- see notes

ALTER ROLE schma_admin IN DATABASE hostdb SET search_path = schma; -- not inherited
ALTER ROLE schma_mgr   IN DATABASE hostdb SET search_path = schma;
ALTER ROLE schma_usr   IN DATABASE hostdb SET search_path = schma;

GRANT USAGE  ON SCHEMA schma TO schma_usr;
GRANT CREATE ON SCHEMA schma TO schma_admin;

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT SELECT                           ON TABLES TO schma_usr;  -- only read

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT INSERT, UPDATE, DELETE, TRUNCATE ON TABLES TO schma_mgr;  -- + write, TRUNCATE optional

ALTER DEFAULT PRIVILEGES FOR ROLE schma_admin
GRANT USAGE, SELECT, UPDATE ON SEQUENCES TO schma_mgr;  -- SELECT, UPDATE are optional 

Para and drop and alterver las notas a continuación.

A medida que las cosas avanzan, también tendré preguntas para aplicar restricciones similares TRIGGERS, procedimientos almacenados VIEWSy quizás otros objetos.

Las vistas son especiales. Para uno:

... (pero tenga en cuenta que ALL TABLESse considera que incluye vistas y tablas foráneas).

Y para vistas actualizables :

Tenga en cuenta que el usuario que realiza la inserción, actualización o eliminación en la vista debe tener el privilegio correspondiente de inserción, actualización o eliminación en la vista. Además, el propietario de la vista debe tener los privilegios relevantes en las relaciones básicas subyacentes, pero el usuario que realiza la actualización no necesita ningún permiso en las relaciones básicas subyacentes (consulte la Sección 38.5 ).

Los disparadores también son especiales. Necesita el TRIGGERprivilegio sobre la mesa y:

Pero ya estamos ampliando demasiado el alcance de esta pregunta ...

Notas importantes

Propiedad

Si desea permitir schma_admin(solo) soltar y modificar tablas, haga que el rol sea el propietario de todos los objetos. La documentación:

El derecho a soltar un objeto, o alterar su definición de alguna manera, no se trata como un privilegio otorgable; es inherente al propietario y no puede otorgarse ni revocarse. (Sin embargo, se puede obtener un efecto similar al otorgar o revocar la membresía en el rol que posee el objeto; ver más abajo). El propietario también tiene implícitamente todas las opciones de concesión para el objeto.

ALTER TABLE some_tbl OWNER TO schma_admin;

O cree todos los objetos con el rolschma_adminpara comenzar, entonces no necesita establecer el propietario explícitamente. También simplifica los privilegios predeterminados, que luego solo debe establecer para el rol:

Objetos preexistentes

Los privilegios predeterminados solo se aplican a los objetos recién creados y solo a la función particular con la que se crean. También querrá adaptar los permisos para los objetos existentes :

Lo mismo se aplica si crea objetos con un rol que no tiene DEFAULT PRIVILEGESestablecido, como el superusuario postgres. Reasignar la propiedad de schma_adminy privilegios establecer manualmente - o conjunto DEFAULT PRIVILEGESpara postgresasí (mientras está conectado a la base de datos correcto!):

ALTER DEFAULT PRIVILEGES FOR ROLE postgres GRANT ...  -- etc.

Privilegios predeterminados

Te estabas perdiendo un aspecto importante del ALTER DEFAULT PRIVILEGEScomando. Se aplica al rol actual a menos que se especifique lo contrario:

Los privilegios predeterminados solo se aplican a la base de datos actual. Por lo tanto, no te metas con otras bases de datos en el clúster de base de datos. La documentación:

para todos los objetos creados en la base de datos actual

También es posible que desee establecer privilegios predeterminados para FUNCTIONSy TYPES(no solo TABLESy SEQUENCES), pero es posible que no sean necesarios.

Privilegios predeterminados para PUBLIC

Los privilegios predeterminados otorgados PUBLICson rudimentarios y sobreestimados por algunos. La documentación:

PostgreSQL otorga privilegios predeterminados en algunos tipos de objetos a PUBLIC. No se otorgan privilegios PUBLICpor defecto en las tablas, columnas, esquemas o espacios de tablas. Para otros tipos, los privilegios predeterminados otorgados PUBLICson los siguientes: CONNECTy CREATE TEMP TABLEpara bases de datos; EXECUTEprivilegio para funciones; y USAGE privilegio para los idiomas.

El énfasis en negrita es mío. Por lo general, el comando anterior es suficiente para cubrir todo:

REVOKE ALL ON DATABASE hostdb FROM public;

En particular, no se otorgan privilegios predeterminados PUBLICpara nuevos esquemas. Puede ser confuso que el esquema predeterminado llamado "público" comience con ALLprivilegios para PUBLIC. Esa es solo una característica conveniente para facilitar el inicio con bases de datos recién creadas. No afecta a otros esquemas de ninguna manera. Usted puede revocar estos privilegios en la base de datos de plantilla template1, a continuación, bases de datos de todos los recién creados en este grupo comienzan sin ellos:

\connect template1
REVOKE ALL ON SCHEMA public FROM public;

El privilegio TEMP

Como hemos revocado todos los privilegios hostdbdesde PUBLIC, los usuarios normales no pueden crear tablas temporales a menos que lo permitamos explícitamente. Es posible que desee o no agregar esto:

GRANT TEMP ON DATABASE hostdb TO schma_mgr;

search_path

No olvides configurar el search_path. Si solo obtuvo una base de datos en el clúster, puede establecer el valor predeterminado global en postgresql.conf. De lo contrario (más probable), configúrelo como propiedad de la base de datos, o solo para los roles involucrados o incluso la combinación de ambos. Detalles:

Es posible que desee configurarlo schma, publicsi también usa el esquema público, o incluso (menos probable) $user, schma, public...

Una alternativa sería utilizar el esquema predeterminado "público" que debería funcionar con la configuración predeterminada para, a search_pathmenos que lo haya cambiado. Recuerde revocar los privilegios PUBLICen este caso.

Relacionado

Erwin Brandstetter
fuente
Estaba buscando cómo agregar privilegios de administrador predeterminados al superusuario recién creado, por lo que no necesitaría darle más opciones directamente en cada tabla. Y si encontré esto. Y thisparece una instrucción para la nave espacial ...
Denis Matafonov
@DenisMatafonov: los superusuarios tienen todos los privilegios automáticamente. Le sugiero que comience una nueva pregunta con detalles de su caso. Los comentarios no son el lugar. Siempre puede vincular a preguntas / respuestas relacionadas para el contexto.
Erwin Brandstetter
Sí, los superusuarios tienen acceso, pero no puede generalizar sus privilegios predeterminados. Sería realmente bueno establecer privilegios predeterminados para un rol en un esquema y hacer que esos valores predeterminados se apliquen a todos los miembros del rol a medida que crean tablas en el esquema. Por ejemplo, para decir "asegúrese de que cualquier tabla creada en este esquema por cualquier persona en el equipo de ingeniería sea legible por cualquiera en el equipo de informes". En resumen, quiero que los miembros de un rol de creación de tablas hereden sus privilegios predeterminados.
combinatorista