CREATE POLICY — define una nueva política de seguridad a nivel de fila para una tabla
CREATE POLICYnombreONnombre_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) ]
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.
nombreEl nombre de la política a crear. Este debe ser distinto del nombre de cualquier otra política para la tabla.
nombre_tablaEl nombre (opcionalmente calificado por esquema) de la tabla a la que se aplica la política.
PERMISSIVEEspecifica 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.
RESTRICTIVEEspecifica 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.
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
| Comando | Política SELECT/ALL | Política INSERT/ALL | Política UPDATE/ALL | Política DELETE/ALL | |
|---|---|---|---|---|---|
Expresión USING | Expresión WITH CHECK | Expresión USING | Expresión WITH CHECK | Expresión USING | |
SELECT / COPY ... TO | Filtrar fila existente | — | — | — | — |
SELECT FOR UPDATE/SHARE | Filtrar fila existente | — | Filtrar fila existente | — | — |
INSERT | Comprobar nueva fila [a] | Comprobar nueva fila | — | — | — |
UPDATE | Filtrar fila existente [a] & comprobar nueva fila [a] | — | Filtrar fila existente | Comprobar 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] | — |
MERGE | Filtrar filas de origen y destino | — | — | — | — |
MERGE ... THEN INSERT | Comprobar nueva fila [a] | Comprobar nueva fila | — | — | — |
MERGE ... THEN UPDATE | Comprobar nueva fila | — | Comprobar fila existente | Comprobar nueva fila | — |
MERGE ... THEN DELETE | — | — | — | — | Comprobar fila existente |
[a]
Si se requiere acceso de lectura a la fila existente o nueva (por
ejemplo, una cláusula [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 | |||||
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ónde la política RESTRICTIVE SELECT/ALL 1 ANDexpresiónde la política RESTRICTIVE SELECT/ALL 2 AND ... AND (expresiónde la política PERMISSIVE SELECT/ALL 1 ORexpresiónde la política PERMISSIVE SELECT/ALL 2 OR ... ) ANDexpresiónde la política RESTRICTIVE UPDATE/ALL 1 ANDexpresiónde la política RESTRICTIVE UPDATE/ALL 2 AND ... AND (expresiónde la política PERMISSIVE UPDATE/ALL 1 ORexpresiónde la política PERMISSIVE UPDATE/ALL 2 OR ... )
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.
CREATE POLICY es una extensión de PostgreSQL.