Share via


Segurança em nível de linha

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 sistema de segurança.

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

  • Conceder acesso somente 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 RLS é habilitada em uma tabela, o acesso é totalmente substituído pela consulta 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 do RLS. A consulta RLS deve incluir explicitamente definições para todos os tipos de usuários aos quais você deseja dar 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 RLS não pode ser habilitada em uma tabela sob as seguintes circunstâncias:

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 no , habilite uma política de Segurança em SalesNí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 email:

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, poderá 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, convém 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 de Microsoft Entra

Se você tiver vários grupos de 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 recebe o nome da tabela como um parâmetro de cadeia de caracteres e referencie a tabela usando o table() operador .

Por exemplo:

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

Em seguida, configure o RLS em várias tabelas dessa forma:

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

Produzir um erro após o acesso não autorizado

Se você quiser que os usuários da tabela não autenticada 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 de Microsoft Entra e produzir um erro para todos os outros.

Controlar permissões em bancos de dados de seguidor

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

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 em consultas no cluster líder. O impacto no desempenho nas consultas nos clusters seguintes será afetado apenas pela complexidade de DataForFollowerClusters.

Mais casos de uso

  • Uma pessoa de suporte do 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 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 RLS que mascara informações de identificação pessoal (PII) e permite que os desenvolvedores consultem ambientes de produção para fins de solução de problemas sem violar regulamentos de conformidade.
  • Um hospital pode definir uma política de RLS que permite aos enfermeiros exibir linhas de dados apenas para seus pacientes.
  • Um banco pode definir uma política RLS para restringir o acesso a linhas de dados financeiros com base na divisão ou função de negócios 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 RLS para impor uma separação lógica das linhas de dados de cada locatário das linhas de cada locatário, para que cada locatário possa ver apenas suas linhas de dados.

Impacto no desempenho em consultas

Quando uma política RLS estiver habilitada em uma tabela, haverá algum impacto no desempenho nas 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 em Microsoft Entra ID: as verificações são eficientes. Você pode marcar associação em dezenas ou até mesmo centenas de grupos sem grande impacto no desempenho da consulta.
  • Filtros, junções e outras operações que são 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 avaliada como true, somente a consulta para PartialData será avaliada.

Melhorar o desempenho da consulta quando o RLS for usado

Impacto no desempenho na ingestão

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