CREATE POLICY

CREATE POLICY — define una nueva política de seguridad a nivel de fila para una tabla

Synopsis

CREATE POLICY nombre ON nombre_tabla
    [ AS { PERMISSIVE | RESTRICTIVE } ]
    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
    [ TO { nombre_rol | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
    [ USING ( expresión_using ) ]
    [ WITH CHECK ( expresión_check ) ]

Descripción

El comando CREATE POLICY define una nueva política de seguridad a nivel de fila para una tabla. Ten en cuenta que la seguridad a nivel de fila debe estar habilitada en la tabla (usando ALTER TABLE ... ENABLE ROW LEVEL SECURITY) para que se apliquen las políticas creadas.

Una política otorga el permiso para seleccionar, insertar, actualizar o eliminar filas que coincidan con la expresión de la política correspondiente. Las filas existentes de la tabla se comprueban contra la expresión especificada en USING, mientras que las filas nuevas que se crearían mediante INSERT o UPDATE se comprueban contra la expresión especificada en WITH CHECK. Cuando una expresión USING devuelve true para una fila determinada, esa fila es visible para el usuario, mientras que si devuelve false o null, la fila no es visible. Típicamente, no ocurre ningún error cuando una fila no es visible, pero consulta la Table 300 para ver las excepciones. Cuando una expresión WITH CHECK devuelve true para una fila, esa fila se inserta o actualiza, mientras que si devuelve false o null, se produce un error.

Para las sentencias INSERT, UPDATE y MERGE, las expresiones WITH CHECK se aplican después de que se disparen los disparadores (triggers) BEFORE, y antes de que se realicen las modificaciones reales de los datos. Por lo tanto, un disparador BEFORE ROW puede modificar los datos a insertar, afectando al resultado de la comprobación de la política de seguridad. Las expresiones WITH CHECK se aplican antes de cualquier otra restricción.

Los nombres de las políticas son por tabla. Por lo tanto, se puede usar un mismo nombre de política para muchas tablas diferentes y tener una definición para cada tabla que sea apropiada para esa tabla.

Las políticas se pueden aplicar para comandos específicos o para roles específicos. El valor predeterminado para las políticas recién creadas es que se apliquen a todos los comandos y roles, a menos que se especifique lo contrario. Se pueden aplicar múltiples políticas a un solo comando; consulta más abajo para más detalles. La Table 300 resume cómo se aplican los diferentes tipos de políticas a comandos específicos.

Para las políticas que pueden tener expresiones tanto USING como WITH CHECK (ALL y UPDATE), si no se define una expresión WITH CHECK, entonces la expresión USING se usará tanto para determinar qué filas son visibles (caso normal de USING) como para determinar qué filas nuevas se permitirán agregar (caso de WITH CHECK).

Si la seguridad a nivel de fila está habilitada para una tabla, pero no existen políticas aplicables, se asume una política de denegación por omisión (default deny), por lo que ninguna fila será visible ni actualizable.

Parámetros

nombre

El nombre de la política a crear. Este debe ser distinto del nombre de cualquier otra política para la tabla.

nombre_tabla

El nombre (opcionalmente calificado por esquema) de la tabla a la que se aplica la política.

PERMISSIVE

Especifica que la política se creará como una política permisiva. Todas las políticas permisivas que sean aplicables a una consulta determinada se combinarán utilizando el operador booleano OR. Al crear políticas permisivas, los administradores pueden ampliar el conjunto de registros a los que se puede acceder. Las políticas son permisivas por defecto.

RESTRICTIVE

Especifica que la política se creará como una política restrictiva. Todas las políticas restrictivas que sean aplicables a una consulta determinada se combinarán utilizando el operador booleano AND. Al crear políticas restrictivas, los administradores pueden reducir el conjunto de registros a los que se puede acceder, ya que se deben cumplir todas las políticas restrictivas para cada registro.

Ten en cuenta que debe haber al menos una política permisiva que otorgue acceso a los registros antes de que las políticas restrictivas puedan usarse de manera útil para reducir ese acceso. Si solo existen políticas restrictivas, ningún registro será accesible. Cuando hay una mezcla de políticas permisivas y restrictivas, un registro solo es accesible si se cumple al menos una de las políticas permisivas, además de todas las políticas restrictivas.

comando

El comando al que se aplica la política. Las opciones válidas son ALL, SELECT, INSERT, UPDATE y DELETE. ALL es el valor predeterminado. Consulta más abajo para ver los detalles sobre cómo se aplican.

nombre_rol

El rol o roles a los que se aplicará la política. El valor predeterminado es PUBLIC, lo que aplicará la política a todos los roles.

expresión_using

Cualquier expresión condicional de SQL (que devuelva boolean). La expresión condicional no puede contener funciones de agregación ni de ventana. Esta expresión se agregará a las consultas que hagan referencia a la tabla si la seguridad a nivel de fila está habilitada. Las filas para las cuales la expresión devuelva true serán visibles. Las filas para las cuales la expresión devuelva false o null no serán visibles para el usuario (en un SELECT), y no estarán disponibles para modificación (en un UPDATE o DELETE). Típicamente, tales filas se descartan silenciosamente; no se reporta ningún error (pero consulta la Table 300 para ver las excepciones).

expresión_check

Cualquier expresión condicional de SQL (que devuelva boolean). La expresión condicional no puede contener funciones de agregación ni de ventana. Esta expresión se usará en consultas INSERT y UPDATE contra la tabla si la seguridad a nivel de fila está habilitada. Solo se permitirán las filas para las cuales la expresión se evalúe como true. Se lanzará un error si la expresión se evalúa como false o null para cualquiera de los registros insertados o para cualquiera de los registros que resulten de la actualización. Ten en cuenta que la expresión_check se evalúa contra el nuevo contenido propuesto para la fila, no contra el contenido original.

Políticas por comando

ALL #

Usar ALL para una política significa que se aplicará a todos los comandos, independientemente del tipo de comando. Si existe una política ALL y existen políticas más específicas, entonces se aplicarán tanto la política ALL como la política (o políticas) más específicas. Además, las políticas ALL se aplicarán tanto al lado de selección de una consulta como al lado de modificación, usando la expresión USING para ambos casos si solo se ha definido una expresión USING.

Como ejemplo, si se ejecuta un UPDATE, la política ALL será aplicable tanto a lo que el UPDATE pueda seleccionar como filas a actualizar (aplicando la expresión USING), como a las filas actualizadas resultantes, para comprobar si se les permite agregarse a la tabla (aplicando la expresión WITH CHECK, si está definida, y la expresión USING en caso contrario). Si un comando INSERT o UPDATE intenta agregar filas a la tabla que no pasan la expresión WITH CHECK de la política ALL (o su expresión USING, si no tiene una expresión WITH CHECK), se abortará el comando completo.

SELECT #

Usar SELECT para una política significa que se aplicará a las consultas SELECT y siempre que se requieran permisos de SELECT en la relación para la cual se define la política. El resultado es que solo se devolverán aquellos registros de la relación que pasen la política SELECT durante una consulta SELECT, y que las consultas que requieren permisos de SELECT, como UPDATE, DELETE y MERGE, también solo verán aquellos registros permitidos por la política SELECT. Una política SELECT no puede tener una expresión WITH CHECK, ya que solo se aplica en casos donde se recuperan registros de la relación, excepto como se describe a continuación.

Si una consulta de modificación de datos tiene una cláusula RETURNING, se requieren permisos de SELECT en la relación, y cualquier fila recién insertada o actualizada de la relación debe cumplir con las políticas SELECT de la relación para estar disponible para la cláusula RETURNING. Si una fila recién insertada o actualizada no cumple con las políticas SELECT de la relación, se lanzará un error (las filas insertadas o actualizadas a devolver nunca se ignoran silenciosamente).

Si un INSERT tiene una cláusula ON CONFLICT DO UPDATE, o una cláusula ON CONFLICT DO NOTHING con una especificación de índice árbitro o restricción, entonces se requieren permisos de SELECT en la relación, y las filas propuestas para la inserción se comprueban utilizando las políticas SELECT de la relación. Si una fila propuesta para la inserción no cumple con las políticas SELECT de la relación, se lanza un error (la inserción nunca se evita silenciosamente). Además, si se toma la ruta de UPDATE, la fila a actualizar y la nueva fila actualizada se comprueban contra las políticas SELECT de la relación, y se lanza un error si no se cumplen (un UPDATE auxiliar nunca se evita silenciosamente).

Un comando MERGE requiere permisos de SELECT tanto en la relación de origen como en la de destino, por lo que las políticas SELECT de cada relación se aplican antes de que se unan, y las acciones de MERGE solo verán aquellos registros que estén permitidos por esas políticas. Además, si se ejecuta una acción UPDATE, las políticas SELECT de la relación de destino se aplican a la fila actualizada, al igual que para un UPDATE independiente, excepto que se lanza un error si no se cumplen.

INSERT #

Usar INSERT para una política significa que se aplicará a comandos INSERT y comandos MERGE que contengan acciones INSERT. Las filas que se estén insertando y no pasen esta política resultarán en un error de violación de política, y se abortará todo el comando INSERT. Una política INSERT no puede tener una expresión USING, ya que solo se aplica en casos donde se están agregando registros a la relación.

Ten en cuenta que un INSERT con una cláusula ON CONFLICT DO NOTHING/UPDATE comprobará las expresiones WITH CHECK de las políticas INSERT para todas las filas propuestas para inserción, independientemente de si terminan siendo insertadas o no.

UPDATE #

Usar UPDATE para una política significa que se aplicará a los comandos UPDATE, SELECT FOR UPDATE y SELECT FOR SHARE, así como a las cláusulas auxiliares ON CONFLICT DO UPDATE de los comandos INSERT, y a los comandos MERGE que contengan acciones UPDATE. Dado que un comando UPDATE implica extraer un registro existente y reemplazarlo con un nuevo registro modificado, las políticas UPDATE aceptan tanto una expresión USING como una expresión WITH CHECK. La expresión USING determina qué registros verá el comando UPDATE para operar sobre ellos, mientras que la expresión WITH CHECK define qué filas modificadas se permite almacenar de vuelta en la relación.

Cualquier fila cuyos valores actualizados no pasen la expresión WITH CHECK causará un error, y se abortará el comando completo. Si solo se especifica una cláusula USING, esa cláusula se usará tanto para los casos de USING como de WITH CHECK.

Típicamente, un comando UPDATE también necesita leer datos de las columnas de la relación que se está actualizando (por ejemplo, en una cláusula WHERE, en una cláusula RETURNING, o en una expresión en el lado derecho de la cláusula SET). En este caso, también se requieren derechos de SELECT en la relación que se está actualizando, y se aplicarán las políticas correspondientes de SELECT o ALL además de las políticas de UPDATE. Por lo tanto, el usuario debe tener acceso a las filas que se están actualizando a través de una política de SELECT o ALL, además de que se le otorgue permiso para actualizar las filas a través de una política de UPDATE o ALL.

Cuando un comando INSERT tiene una cláusula auxiliar ON CONFLICT DO UPDATE, si se toma la ruta de UPDATE, la fila a actualizar se comprueba primero contra las expresiones USING de cualquier política UPDATE, y luego la nueva fila actualizada se comprueba contra las expresiones WITH CHECK. Ten en cuenta, sin embargo, que a diferencia de un comando UPDATE independiente, si la fila existente no pasa las expresiones USING, se lanzará un error (la ruta de UPDATE nunca se evitará silenciosamente). Lo mismo se aplica a una acción UPDATE de un comando MERGE.

DELETE #

Usar DELETE para una política significa que se aplicará a comandos DELETE y comandos MERGE que contengan acciones DELETE. Para un comando DELETE, solo las filas que pasen esta política serán vistas por el comando DELETE. Puede haber filas que sean visibles a través de una política SELECT pero que no estén disponibles para su eliminación, si no pasan la expresión USING de la política DELETE. Ten en cuenta, sin embargo, que una acción DELETE en un comando MERGE verá las filas que son visibles a través de políticas SELECT, y si la política DELETE no se cumple para tal fila, se lanzará un error.

En la mayoría de los casos, un comando DELETE también necesita leer datos de las columnas de la relación de la que se está eliminando (por ejemplo, en una cláusula WHERE o en una cláusula RETURNING). En este caso, también se requieren derechos de SELECT en la relación, y se aplicarán las políticas correspondientes de SELECT o ALL además de las políticas de DELETE. Por lo tanto, el usuario debe tener acceso a las filas que se están eliminando a través de una política de SELECT o ALL, además de que se le otorgue permiso para eliminar las filas a través de una política de DELETE o ALL.

Una política DELETE no puede tener una expresión WITH CHECK, ya que solo se aplica en casos donde se están eliminando registros de la relación, por lo que no hay una nueva fila que comprobar.

La Table 300 resume cómo se aplican los diferentes tipos de políticas a comandos específicos. En la tabla, check (comprobar) significa que se comprueba la expresión de la política y se lanza un error si devuelve false o null, mientras que filter (filtrar) significa que la fila se ignora silenciosamente si la expresión de la política devuelve false o null.

Table 300. Políticas aplicadas por tipo de comando

ComandoPolítica SELECT/ALLPolítica INSERT/ALLPolítica UPDATE/ALLPolítica DELETE/ALL
Expresión USINGExpresión WITH CHECKExpresión USINGExpresión WITH CHECKExpresión USING
SELECT / COPY ... TOFiltrar fila existente
SELECT FOR UPDATE/SHAREFiltrar fila existenteFiltrar fila existente
INSERT Comprobar nueva fila [a] Comprobar nueva fila
UPDATE Filtrar fila existente [a] & comprobar nueva fila [a] Filtrar fila existenteComprobar nueva fila
DELETE Filtrar fila existente [a] Filtrar fila existente
INSERT ... ON CONFLICT Comprobar nueva fila [b][c] Comprobar nueva fila [c]
ON CONFLICT DO UPDATE Comprobar filas existentes y nuevas [d] Comprobar fila existente Comprobar nueva fila [d]
MERGEFiltrar filas de origen y destino
MERGE ... THEN INSERT Comprobar nueva fila [a] Comprobar nueva fila
MERGE ... THEN UPDATEComprobar nueva filaComprobar fila existenteComprobar nueva fila
MERGE ... THEN DELETEComprobar fila existente

[a] Si se requiere acceso de lectura a la fila existente o nueva (por ejemplo, una cláusula WHERE o RETURNING que haga referencia a columnas de la relación).

[b] Si se especifica un índice árbitro o una restricción.

[c] La fila propuesta para inserción se comprueba independientemente de si ocurre un conflicto o no.

[d] Nueva fila del comando UPDATE auxiliar, que podría ser diferente de la nueva fila del comando INSERT original.


Aplicación de múltiples políticas

Cuando múltiples políticas de diferentes tipos de comandos se aplican al mismo comando (por ejemplo, políticas de SELECT y UPDATE aplicadas a un comando UPDATE), el usuario debe tener ambos tipos de permisos (por ejemplo, permiso para seleccionar filas de la relación así como permiso para actualizarlas). Por lo tanto, las expresiones de un tipo de política se combinan con las expresiones del otro tipo de política utilizando el operador AND.

Cuando múltiples políticas del mismo tipo de comando se aplican al mismo comando, debe haber al menos una política PERMISSIVE que otorgue acceso a la relación, y deben cumplirse todas las políticas RESTRICTIVE. Por lo tanto, todas las expresiones de las políticas PERMISSIVE se combinan utilizando OR, todas las expresiones de las políticas RESTRICTIVE se combinan utilizando AND, y los resultados se combinan utilizando AND. Si no hay políticas PERMISSIVE, se deniega el acceso.

Ten en cuenta que, a efectos de combinar múltiples políticas, las políticas ALL se tratan como si tuvieran el mismo tipo que cualquier otro tipo de política que se esté aplicando.

Por ejemplo, en un comando UPDATE que requiera permisos tanto de SELECT como de UPDATE, si hay múltiples políticas aplicables de cada tipo, se combinarán de la siguiente manera:

expresión de la política RESTRICTIVE SELECT/ALL 1
AND
expresión de la política RESTRICTIVE SELECT/ALL 2
AND
...
AND
(
  expresión de la política PERMISSIVE SELECT/ALL 1
  OR
  expresión de la política PERMISSIVE SELECT/ALL 2
  OR
  ...
)
AND
expresión de la política RESTRICTIVE UPDATE/ALL 1
AND
expresión de la política RESTRICTIVE UPDATE/ALL 2
AND
...
AND
(
  expresión de la política PERMISSIVE UPDATE/ALL 1
  OR
  expresión de la política PERMISSIVE UPDATE/ALL 2
  OR
  ...
)

Notas

Debes ser el propietario de una tabla para crear o cambiar políticas para ella.

Aunque las políticas se aplicarán para consultas explícitas contra las tablas de la base de datos, no se aplican cuando el sistema realiza comprobaciones internas de integridad referencial o valida restricciones. Esto significa que existen formas indirectas de determinar que un valor dado existe. Un ejemplo de esto es intentar insertar un valor duplicado en una columna que es clave primaria o tiene una restricción única. Si la inserción falla, el usuario puede inferir que el valor ya existe (este ejemplo asume que la política permite al usuario insertar registros que no se le permite ver). Otro ejemplo es cuando a un usuario se le permite insertar en una tabla que hace referencia a otra tabla que de otro modo estaría oculta. La existencia puede ser determinada por el usuario al insertar valores en la tabla de referencia, donde el éxito indicaría que el valor existe en la tabla referenciada. Estos problemas se pueden abordar diseñando cuidadosamente las políticas para evitar que los usuarios puedan insertar, eliminar o actualizar registros que puedan indicar un valor que de otro modo no pueden ver, o utilizando valores generados (por ejemplo, claves subrogadas) en lugar de claves con significados externos.

Generalmente, el sistema aplicará las condiciones de filtrado impuestas mediante las políticas de seguridad antes que las cualificaciones que aparecen en las consultas de los usuarios, con el fin de evitar la exposición involuntaria de los datos protegidos a funciones definidas por el usuario que podrían no ser confiables. Sin embargo, las funciones y operadores marcados por el sistema (o por el administrador del sistema) como LEAKPROOF pueden evaluarse antes de las expresiones de la política, ya que se asume que son confiables.

Dado que las expresiones de la política se agregan directamente a la consulta del usuario, se ejecutarán con los derechos del usuario que ejecuta la consulta general. Por lo tanto, los usuarios que estén utilizando una política determinada deben poder acceder a cualquier tabla o función a la que se haga referencia en la expresión, o simplemente recibirán un error de permiso denegado al intentar realizar consultas en la tabla que tiene habilitada la seguridad a nivel de fila. Sin embargo, esto no cambia el funcionamiento de las vistas. Al igual que con las consultas y vistas normales, las comprobaciones de permisos y las políticas para las tablas a las que hace referencia una vista utilizarán los derechos del propietario de la vista y cualquier política que se aplique al propietario de la vista, a menos que la vista esté definida con la opción security_invoker (consulta CREATE VIEW).

No existe una política separada para MERGE. En su lugar, las políticas definidas para SELECT, INSERT, UPDATE y DELETE se aplican al ejecutar MERGE, dependiendo de las acciones que se realicen.

Se pueden encontrar más discusiones y ejemplos prácticos en la Section 5.9.

Compatibilidad

CREATE POLICY es una extensión de PostgreSQL.

Consulte también

ALTER POLICY, DROP POLICY, ALTER TABLE