Administración de la autorización mediante la seguridad de nivel de columna y de fila
En este tema, veremos cómo puede administrar la autorización mediante la seguridad de nivel de fila y de columna en Azure Synapse Analytics. Comenzaremos hablando sobre la seguridad de nivel de columna en Azure Synapse Analytics y finalizaremos con la seguridad de nivel de fila.
Seguridad de nivel de columna en Azure Synapse Analytics
En general, la seguridad en el nivel de columna consiste en simplificar el diseño y la codificación de la seguridad en una aplicación. Permite restringir el acceso a ciertas columnas con el fin de proteger los datos confidenciales. Por ejemplo, en el caso de que quiera asegurarse de que un usuario específico, David, solo pueda acceder a determinadas columnas de una tabla porque trabaja un departamento concreto. La lógica para que David solo acceda a las columnas especificadas para el departamento en el que trabaja se encuentra en el nivel de base de datos, en lugar de en la capa de datos del nivel de aplicación. Si David necesita acceder a los datos de cualquier nivel, la base de datos debería aplicar la restricción de acceso cada vez que trate de acceder a los datos de otro nivel. El motivo es garantizar que la seguridad sea confiable y robusta, ya que estamos reduciendo el área expuesta del sistema de seguridad general. La seguridad de nivel de columna también eliminará la necesidad de introducir vistas, donde filtraría las columnas, para imponer restricciones de acceso a David.
La forma de implementar la seguridad de nivel de columna es mediante la instrucción T-SQL GRANT. Con esta instrucción, SQL y Microsoft Entra ID admiten la autenticación.
Sintaxis
La sintaxis que se usa para implementar la seguridad de nivel de columna tiene el siguiente aspecto:
GRANT <permission> [ ,...n ] ON
[ OBJECT :: ][ schema_name ]. object_name [ ( column [ ,...n ] ) ] // specifying the column access
TO <database_principal> [ ,...n ]
[ WITH GRANT OPTION ]
[ AS <database_principal> ]
<permission> ::=
SELECT
| UPDATE
<database_principal> ::=
Database_user // specifying the database user
| Database_role // specifying the database role
| Database_user_mapped_to_Windows_User
| Database_user_mapped_to_Windows_Group
¿Cuándo usaría la seguridad de nivel de columna? Supongamos que tiene una empresa de servicios financieros y que solo puede permitir que un administrador de cuentas tenga acceso al número del seguro social, al número de teléfono o a otra información de identificación personal de un cliente. Es imprescindible distinguir el rol de un administrador de cuentas del de un administrador de administradores de cuentas.
Otro caso de uso podría estar relacionado con el sector sanitario. Supongamos que tiene un proveedor de atención sanitaria concreto. Este proveedor solo quiere que los médicos y enfermeros puedan acceder a los registros médicos. El departamento de facturación no debería tener acceso para ver estos datos. La seguridad de nivel de columna podría ser la opción más adecuada que usar.
Entonces, ¿en qué se distingue la seguridad de nivel de columna de la de nivel de fila? Veámoslo.
Seguridad de nivel de fila en Azure Synapse Analytics
La seguridad de nivel de fila (RLS) puede ayudarle a crear una pertenencia a un grupo o un contexto de ejecución para controlar no solo las columnas de una tabla de base de datos, sino también las filas. RLS, al igual que la seguridad de nivel de columna, puede ayudarle a diseñar y codificar la seguridad de la aplicación. No obstante, en comparación con la seguridad de nivel de columna, que se centra en las columnas (parámetros), RLS ayuda a implementar restricciones en el acceso a las filas de datos. Supongamos que su empleado solo puede acceder a las filas de datos que son importantes para el departamento; en ese caso, debe implementar RLS. Si desea restringir, por ejemplo, el acceso a los datos del cliente que solo son pertinentes para la empresa, puede implementar RLS. La restricción en el acceso a las filas es una lógica que se encuentra en la capa de la base de datos, en lugar de en la capa de datos del nivel de aplicación. Si David necesita acceder a los datos de cualquier nivel, la base de datos debería aplicar la restricción de acceso cada vez que trate de acceder a los datos de otro nivel. El motivo es garantizar que la seguridad sea confiable y robusta, ya que estamos reduciendo el área expuesta del sistema de seguridad general.
La manera de implementar RLS es usando la instrucción CREATE SECURITY POLICY[!INCLUDEtsql]. Los predicados se crean como funciones insertadas con valores de tabla. Es importante comprender que Azure Synapse solo admite predicados de filtro. Si necesita usar un predicado de bloqueo, no podrá encontrar soporte en este momento en Azure Synapse.
Relación de la seguridad de nivel de fila con los predicados de filtro
RLS en Azure Synapse admite un tipo de predicado de seguridad, que son los predicados de filtro, pero no los de bloqueo.
Lo que hacen los predicados de filtro es filtrar silenciosamente las filas que están disponibles para operaciones de lectura como SELECT, UPDATE y DELETE.
El acceso a los datos de nivel de fila de una tabla se restringe como una función insertada con valores de tabla, que es un predicado de seguridad. Esta función con valores de tabla se invocará y aplicará mediante la directiva de seguridad que necesite. Una aplicación no conoce las filas que se filtran del conjunto de resultados cuando se usan los predicados de filtro. Por lo tanto, lo que ocurrirá es que, si se filtran todas las filas, se devolverá un conjunto nulo.
Si se utilizan predicados de filtro, se aplicarán cuando se lean los datos de la tabla base. El predicado de filtro afecta a todas las operaciones GET, como SELECT, DELETE y UPDATE. No se pueden seleccionar o eliminar filas que se han filtrado. Tampoco es posible actualizar una fila que se ha filtrado. Lo que se puede hacer es actualizar las filas de forma que se filtren después.
Casos de uso
Ya hemos mencionado algunos casos de uso de RLS. Otro caso de uso podría ser cuando se ha creado una aplicación multiinquilino en la que se crea una directiva en la que se aplican las separaciones lógicas de las filas de datos de un inquilino con las filas de datos de otro inquilino. Para implementar esto de forma eficaz, se recomienda almacenar los datos de muchos inquilinos en una sola tabla.
Al analizar los predicados de filtro de RLS, vemos que son funcionalmente equivalentes a anexar una cláusula WHERE.
El predicado puede ser tan sofisticado como dictan las prácticas empresariales o la cláusula puede ser tan simple como WHERE TenantId = 42
.
Si analizamos RLS de manera más formal, este introduce el control de acceso basado en predicados. La razón por la que RLS se puede usar para el control de acceso de predicados es porque se trata de una evaluación flexible, centralizada y basada en predicados. El predicado de filtro puede basarse en metadatos o en cualquier otro criterio que se determine como corresponda. El predicado se usa como un criterio para determinar si el usuario tiene el acceso adecuado a los datos según los atributos del usuario. El control de acceso basado en etiquetas se puede implementar mediante el control de acceso basado en predicados.
Permisos
Si desea crear, modificar o quitar las directivas de seguridad, tendría que usar el permiso ALTER ANY SECURITY POLICY. La razón es que, cuando se crea o elimina una directiva de seguridad, se requieren permisos ALTER en el esquema.
Además, hay otros permisos necesarios para cada predicado que agregaría:
Los permisosSELECT y REFERENCES de la función insertada con valores de tabla que se usa como predicado.
El permiso REFERENCES en la tabla de destino que se va a enlazar a la directiva.
El permisoREFERENCES de cada columna desde la tabla de destino que se usa como argumento.
Una vez que haya configurado las directivas de seguridad, se aplicarán a todos los usuarios (incluidos los usuarios DBO de la base de datos) y, aunque los usuarios DBO pueden modificar o quitar directivas de seguridad, se podrán auditar los cambios en las directivas de seguridad. Si tiene circunstancias especiales por las que los usuarios con privilegios elevados, como sysadmin o db_owner, necesitan ver todas las filas para solucionar problemas o validar datos, todavía tendría que escribir la directiva de seguridad para permitirlo.
Si ha creado una directiva de seguridad en SCHEMABINDING = OFF
, para consultar la tabla de destino, el usuario debe tener el permiso SCHEMABINDING = OFF
o EXECUTE en la función de predicado.
También necesitan permisos para las tablas, vistas o funciones adicionales que se usan en la función de predicado.
Si se crear una directiva de seguridad con SCHEMABINDING = ON
(el valor predeterminado), entonces estas comprobaciones de permiso se omiten cuando los usuarios consultan la tabla de destino.
Procedimientos recomendados
Hay algunos procedimientos recomendados que se deben tener en cuenta cuando se desea implementar RLS. Se recomienda crear un esquema independiente para los objetos RLS. Los objetos RLS en este contexto serían las funciones de predicado y las directivas de seguridad. ¿Por qué se recomienda? Porque ayuda a separar los permisos que son necesarios en estos objetos especiales de las tablas de destino. Además, la separación de las distintas directivas y funciones de predicado puede ser necesaria en las bases de datos multiinquilino. Sin embargo, no es una norma para todos los casos.
Otro procedimiento recomendado es tener en cuenta que el permiso ALTER ANY SECURITY POLICY solo debe estar pensado para usuarios con privilegios elevados (como un administrador de directivas de seguridad). El administrador de directivas de seguridad no debería necesitar el permiso SELECT en las tablas que protege.
Para evitar posibles errores en tiempo de ejecución, debe tener en cuenta las conversiones de tipo en las funciones de predicado que escriba. Además, debe intentar evitar la recursividad en las funciones de predicado. El motivo es evitar la degradación del rendimiento. Aunque el optimizador de consultas intentará detectar las recursividades directas, no hay ninguna garantía de encontrar las indirectas. Con la recursividad indirecta, queremos decir que una segunda función llama a la función de predicado.
También se recomienda evitar el uso de combinaciones de tablas excesivas en las funciones de predicado, ya que esto podría maximizar el rendimiento.
Por lo general, cuando llega a la lógica de predicado, debe intentar evitar la lógica que depende de las opciones SET específicas de la sesión. Aunque es bastante improbable que se usen en aplicaciones prácticas, las funciones de predicado cuya lógica depende de determinadas opciones SET específicas de la sesión pueden perder información si los usuarios pueden ejecutar consultas arbitrarias. Por ejemplo, una función de predicado que convierte implícitamente una cadena en datetime podría filtrar filas diferentes según la opción SET DATEFORMAT de la sesión actual.