Partilhar via


Política de segurança no nível da linha

Aplica-se a: ✅Microsoft FabricAzure Data Explorer

Use a associação de grupo ou o contexto de execução para controlar o acesso a linhas em uma tabela de banco de dados.

A RLS (Segurança em Nível de Linha) simplifica o design e a codificação de segurança. Ela permite que você aplique restrições ao acesso de linha de dados em seu aplicativo. Por exemplo, limite o acesso do usuário a linhas relevantes para seu departamento ou restrinja o acesso do cliente apenas aos dados relevantes para sua empresa.

A lógica de restrição de acesso está localizada na camada de banco de dados, e não longe dos dados em outra camada de aplicativo. O sistema de banco de dados aplica as restrições de acesso sempre que o acesso a dados é tentado de qualquer camada. Essa lógica torna seu sistema de segurança mais confiável e robusto, reduzindo a área de superfície do seu sistema de segurança.

A RLS permite que você forneça acesso a outros aplicativos e usuários, apenas a uma determinada parte de uma tabela. Por exemplo, você pode querer:

  • Conceder acesso apenas a linhas que atendam a alguns critérios
  • Anonimizar dados em algumas das colunas
  • Todas as opções acima

Observação

Quando uma política de RLS é habilitada em uma tabela, o acesso é totalmente substituído pela consulta de RLS definida na tabela. A restrição de acesso se aplica a todos os usuários, incluindo administradores de banco de dados e o criador da RLS. A consulta RLS deve incluir explicitamente definições para todos os tipos de usuários aos quais você deseja conceder acesso.

Para obter mais informações, consulte comandos de gerenciamento para gerenciar a política de Segurança em Nível de Linha.

Dica

Essas funções geralmente são úteis para consultas row_level_security:

Limitações

  • Não há limite para o número de tabelas nas quais a política de Segurança em Nível de Linha pode ser configurada.
  • A política de Segurança em Nível de Linha não pode ser configurada em Tabelas Externas.
  • A política de RLS não pode ser habilitada em uma tabela nas seguintes circunstâncias:
    • Quando é referenciado por uma consulta de política de atualização, enquanto a política de atualização não está configurada com uma identidade gerenciada.
    • Quando é referenciado por uma exportação contínua que usa um método de autenticação diferente da representação.
    • Quando uma política de acesso de exibição restrita é configurada para a tabela.
  • A consulta RLS não pode fazer referência a tabelas localizadas em outros bancos de dados.

Exemplos

Limitar o acesso à tabela Vendas

Em uma tabela chamada Sales, cada linha contém detalhes sobre uma venda. Uma das colunas contém o nome do vendedor. Em vez de dar aos vendedores acesso a todos os registros do Sales, ative uma política de segurança em nível de linha nesta tabela para retornar apenas registros em que o vendedor é o usuário atual:

Sales | where SalesPersonAadUser == current_principal()

Você também pode mascarar o endereço de e-mail:

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

Se você quiser que cada vendedor veja todas as vendas de um país/região específico, você pode definir uma consulta semelhante a:

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))

Se você tiver um grupo que contenha os gerentes, talvez queira dar a eles acesso a todas as linhas. Aqui está a consulta para a política de Segurança em Nível de Linha.

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

Expor dados diferentes a membros de diferentes grupos do Microsoft Entra

Se você tiver vários grupos do Microsoft Entra e quiser que os membros de cada grupo vejam um subconjunto diferente de dados, use essa estrutura para uma 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>)

Aplicar a mesma função RLS em várias tabelas

Primeiro, defina uma função que receba o nome da tabela como um parâmetro de cadeia de caracteres e faça referência à tabela usando o table() operador.

Por exemplo:

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

Em seguida, configure a RLS em várias tabelas desta maneira:

.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')"

Produza um erro no acesso não autorizado

Se você quiser que usuários de tabela não autorizados recebam um erro em vez de retornar uma tabela vazia, use a assert() função. O exemplo a seguir mostra como produzir esse erro em uma função RLS:

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

Você pode combinar essa abordagem com outros exemplos. Por exemplo, você pode exibir resultados diferentes para usuários em diferentes grupos do Microsoft Entra e produzir um erro para todos os outros.

Controlar permissões em bancos de dados de seguidores

A política de RLS que você configura no banco de dados de produção também entrará em vigor nos bancos de dados seguidores. Não é possível configurar políticas de RLS diferentes nos bancos de dados de produção e seguidores. No entanto, você pode usar a current_cluster_endpoint() função em sua consulta RLS para obter o mesmo efeito, como ter diferentes consultas RLS em tabelas seguidoras.

Por exemplo:

.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
}

Observação

A função RLS acima não tem nenhum impacto no desempenho nas consultas no cluster líder. O impacto no desempenho das consultas nos clusters seguidores será afetado apenas pela complexidade do DataForFollowerClusters.

Controlar permissões em bancos de dados de atalhos

A política de RLS que você configura no banco de dados de produção também entrará em vigor nos bancos de dados de atalho. Você não pode configurar políticas de RLS diferentes nos bancos de dados de produção e atalho. No entanto, você pode usar a current_cluster_endpoint() função em sua consulta RLS para obter o mesmo efeito, como ter diferentes consultas RLS em tabelas de atalho.

Por exemplo:

.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
}

Observação

A função RLS acima não tem nenhum impacto no desempenho das consultas no banco de dados de origem. O impacto no desempenho das consultas nos bancos de dados de atalho será afetado apenas pela complexidade do DataForFollowerClusters.

Mais casos de uso

  • Uma pessoa de suporte de call center pode identificar os chamadores por vários dígitos de seu número de seguro social. Esse número não deve ser totalmente exposto à pessoa de suporte. Uma política de RLS pode ser aplicada na tabela para mascarar todos, exceto os últimos quatro dígitos do número do seguro social no conjunto de resultados de qualquer consulta.
  • Defina uma política de RLS que mascare informações de identificação pessoal (PII) e permita que os desenvolvedores consultem ambientes de produção para fins de solução de problemas sem violar os regulamentos de conformidade.
  • Um hospital pode definir uma política de SPI que permite que os enfermeiros visualizem linhas de dados apenas para seus pacientes.
  • Um banco pode definir uma política de RLS para restringir o acesso a linhas de dados financeiros com base na divisão de negócios ou função de um funcionário.
  • Um aplicativo multilocatário pode armazenar dados de muitos locatários em um único conjunto de tabelas (o que é eficiente). Eles usariam uma política de RLS para impor uma separação lógica das linhas de dados de cada locatário das linhas de todos os outros locatários, para que cada locatário possa ver apenas suas linhas de dados.

Impacto no desempenho das consultas

Quando uma política de RLS é habilitada em uma tabela, haverá algum impacto no desempenho das consultas que acessam essa tabela. O acesso à tabela será substituído pela consulta RLS definida nessa tabela. O impacto no desempenho de uma consulta RLS normalmente consistirá em duas partes:

  • Verificações de associação na ID do Microsoft Entra: as verificações são eficientes. Você pode verificar a associação em dezenas ou até centenas de grupos sem grande impacto no desempenho da consulta.
  • Filtros, junções e outras operações aplicadas aos dados: o impacto depende da complexidade da consulta

Por exemplo:

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

Se o usuário não fizer parte do some_group@domain.com, será IsRestrictedUser avaliado como false. A consulta avaliada é semelhante 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

Da mesma forma, se IsRestrictedUser for avaliado como true, somente a consulta for PartialData será avaliada.

Melhorar o desempenho da consulta quando a RLS é usada

Impacto no desempenho na ingestão

Não há impacto no desempenho na ingestão.