Seguridad de nivel de fila

Use la pertenencia a grupos o el contexto de ejecución para controlar el acceso a las filas de una tabla de base de datos.

La Seguridad de nivel de fila (RLS) simplifica el diseño y la codificación de la seguridad. Permite aplicar restricciones en el acceso a las filas de datos en la aplicación. Por ejemplo, limite el acceso de los usuarios a las filas pertinentes para su departamento o restrinja el acceso de los clientes solo a los datos pertinentes para su empresa.

La lógica de la restricción de acceso está ubicada en el nivel de base de datos en lugar de estar alejada de los datos en otra capa de aplicación. El sistema de base de datos aplica las restricciones de acceso cada vez que se intenta acceder a los datos desde cualquier nivel. Esta lógica hace que el sistema de seguridad sea más confiable y sólido al reducir el área expuesta del sistema de seguridad.

RLS le permite proporcionar acceso a otras aplicaciones y usuarios, solo a una parte determinada de una tabla. Por ejemplo, puedes:

  • Conceder acceso solo a las filas que cumplen algunos criterios
  • Anonimizar datos en algunas de las columnas
  • Todo lo anterior

Nota

Cuando se habilita una directiva de RLS en una tabla, el acceso se reemplaza por completo por la consulta RLS definida en la tabla. La restricción de acceso se aplica a todos los usuarios, incluidos los administradores de bases de datos y el creador de RLS. La consulta de RLS debe incluir explícitamente definiciones para todos los tipos de usuarios a los que desea conceder acceso.

Para obtener más información, consulte Comandos de administración para administrar la directiva de seguridad de nivel de fila.

Sugerencia

Estas funciones suelen ser útiles para row_level_security consultas:

Limitaciones

  • No hay ningún límite en el número de tablas en las que se puede configurar la directiva de seguridad de nivel de fila.
  • La directiva de seguridad de nivel de fila no se puede configurar en tablas externas.
  • La directiva RLS no se puede habilitar en una tabla en las siguientes circunstancias:

Ejemplos

Limitar el acceso a la tabla Sales

En una tabla denominada Sales, cada fila contiene detalles sobre una venta. Una de las columnas contiene el nombre del vendedor. En lugar de conceder a los vendedores acceso a todos los registros de Sales, habilite una directiva de seguridad de nivel de fila en esta tabla para devolver solo los registros en los que el vendedor es el usuario actual:

Sales | where SalesPersonAadUser == current_principal()

También puede enmascarar la dirección de correo electrónico:

Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"

Si desea que todas las personas de ventas vean todas las ventas de un país o región específicos, puede definir una consulta similar a la siguiente:

let UserToCountryMapping = datatable(User:string, Country:string)
[
  "john@domain.com", "USA",
  "anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))

Si tiene un grupo que contiene los administradores, es posible que desee concederles acceso a todas las filas. Esta es la consulta de la directiva seguridad de nivel de fila.

let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData

Exposición de datos diferentes a miembros de diferentes grupos de Microsoft Entra

Si tiene varios grupos de Microsoft Entra y desea que los miembros de cada grupo vean un subconjunto diferente de datos, use esta estructura para una consulta RLS.

Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
        (current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
        (current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)

Aplicación de la misma función RLS en varias tablas

En primer lugar, defina una función que reciba el nombre de la tabla como parámetro de cadena y haga referencia a la tabla mediante el table() operador .

Por ejemplo:

.create-or-alter function RLSForCustomersTables(TableName: string) {
    table(TableName)
    | ...
}

A continuación, configure RLS en varias tablas de esta manera:

.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"

Generar un error tras el acceso no autorizado

Si desea que los usuarios de la tabla nonauthorized reciban un error en lugar de devolver una tabla vacía, use la assert() función . En el ejemplo siguiente se muestra cómo generar este error en una función RLS:

.create-or-alter function RLSForCustomersTables() {
    MyTable
    | where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}

Puede combinar este enfoque con otros ejemplos. Por ejemplo, puede mostrar resultados diferentes a los usuarios en diferentes grupos de Microsoft Entra y generar un error para todos los demás.

Permisos de control en las bases de datos del seguidor

La directiva RLS que configure en la base de datos de producción también surtirá efecto en las bases de datos del seguidor. No se pueden configurar directivas RLS diferentes en las bases de datos de producción y seguidor. Sin embargo, puede usar la función en la current_cluster_endpoint() consulta de RLS para lograr el mismo efecto, ya que tiene consultas RLS diferentes en las tablas del seguidor.

Por ejemplo:

.create-or-alter function RLSForCustomersTables() {
    let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
    let DataForProductionCluster = TempTable | where IsProductionCluster;
    let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
    union DataForProductionCluster, DataForFollowerClusters
}

Nota

La función RLS anterior no tiene ningún impacto en el rendimiento en las consultas del clúster líder. El impacto en el rendimiento de las consultas en los clústeres del seguidor solo se verá afectado por la complejidad de DataForFollowerClusters.

Más casos de uso

  • Una persona de soporte técnico del centro de llamadas puede identificar a los autores de llamadas por varios dígitos de su número de seguro social. Este número no debe exponerse completamente a la persona de soporte técnico. Se puede aplicar una directiva RLS en la tabla para enmascarar todos los cuatro últimos dígitos del número de seguro social en el conjunto de resultados de cualquier consulta.
  • Establezca una directiva de RLS que enmascara la información de identificación personal (PII) y permita a los desarrolladores consultar entornos de producción con fines de solución de problemas sin infringir las regulaciones de cumplimiento.
  • Un hospital puede establecer una directiva de RLS que permita a las enfermeras ver las filas de datos solo para sus pacientes.
  • Un banco puede establecer una directiva de RLS para restringir el acceso a las filas de datos financieros en función de la división o el rol de un empleado.
  • Una aplicación multiinquilino puede almacenar datos de muchos inquilinos en un único conjunto de tablas (que es eficaz). Usarían una directiva de RLS para aplicar una separación lógica de las filas de datos de cada inquilino de las filas de cada otro inquilino, por lo que cada inquilino solo puede ver sus filas de datos.

Impacto en el rendimiento en las consultas

Cuando se habilita una directiva de RLS en una tabla, habrá algún impacto en el rendimiento en las consultas que acceden a esa tabla. El acceso a la tabla se reemplazará por la consulta RLS definida en esa tabla. El impacto en el rendimiento de una consulta RLS normalmente constará de dos partes:

  • Comprobaciones de pertenencia en Microsoft Entra ID: las comprobaciones son eficaces. Puede comprobar la pertenencia a decenas o incluso cientos de grupos sin un impacto importante en el rendimiento de las consultas.
  • Filtros, combinaciones y otras operaciones que se aplican a los datos: el impacto depende de la complejidad de la consulta.

Por ejemplo:

let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData

Si el usuario no forma parte de some_group@domain.com, IsRestrictedUser se evalúa como false. La consulta que se evalúa es similar a esta:

let AllData = MyTable;           // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData       // this will just return AllData, as PartialData is empty

Del mismo modo, si IsRestrictedUser se trueevalúa como , solo se evaluará la consulta de PartialData .

Mejora del rendimiento de las consultas cuando se usa RLS

Impacto en el rendimiento en la ingesta

No hay ningún impacto en el rendimiento en la ingesta.