Gerenciar a autorização por meio de segurança em nível de linha e coluna

Concluído

Neste tópico, veremos como você pode gerenciar a autorização por meio da segurança em nível de linha e coluna no Azure Synapse Analytics. Vamos começar falando sobre a segurança em nível de coluna no Azure Synapse Analytics e terminar com a segurança em nível de linha.

Segurança em nível de coluna no Azure Synapse Analytics

Em termos gerais, a segurança em nível de coluna está simplificando o design e codificando para a segurança em seu aplicativo. Ela permite restringir o acesso a colunas para proteger dados confidenciais. Por exemplo, se você quiser garantir que um usuário específico 'Leo' só possa acessar determinadas colunas de uma tabela porque ele está em um departamento específico. A lógica para “Leo” somente para acessar as colunas especificadas para o departamento no qual ele trabalha é uma lógica que está localizada na camada de banco de dados, e não na camada de dados de nível de aplicativo. Se ele precisar acessar dados de qualquer camada, o banco de dados deverá aplicar a restrição de acesso toda vez que tentar acessar dados de outra camada. O motivo para fazer isso é garantir que sua segurança seja confiável e robusta, já que estamos reduzindo a área de superfície do sistema de segurança geral. A segurança em nível de coluna também eliminará a necessidade da introdução da exibição, em que você filtrará as colunas, para impor restrições de acesso a 'Leo'

A maneira de implementar a segurança no nível da coluna é usar a instrução GRANT do T-SQL. Usando essa instrução, o SQL e o Microsoft Entra ID oferecem suporte à autenticação.

Como mostrar segurança em nível de coluna

Sintaxe

A sintaxe a ser usada para implementar a segurança em nível de coluna tem a seguinte aparência:

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

Então, quando você usaria a segurança em nível de coluna? Digamos que você seja uma empresa de serviços financeiros e apenas o gerente de conta deve ter permissão para acessar o número do seguro social, os números de telefone ou outras informações de identificação pessoal de um cliente. É imperativo distinguir a função de um gerente de conta em relação ao gerente dos gerentes de contas.

Outro caso de uso pode estar relacionado ao setor de saúde. Digamos que você tenha um prestador de serviços de saúde específico. Esse prestador de serviços de saúde quer apenas que os médicos e os enfermeiros possam acessar os registros médicos. O departamento de cobrança não deve ter acesso para visualizar esses dados. A segurança em nível de coluna pode ser a opção ideal.

Então, como a segurança em nível de coluna difere da segurança em nível de linha? Vamos examinar isso.

Segurança em nível de linha no Azure Synapse Analytics

A RLS (segurança em nível de linha) pode ajudá-lo a criar uma associação de grupo ou contexto de execução para controlar não apenas colunas em uma tabela de banco de dados, mas também as linhas. A RLS, assim como a segurança em nível de coluna, pode simplesmente ajudar e habilitar o design e a codificação da segurança do seu aplicativo. No entanto, em comparação à segurança em nível de coluna em que ela se concentra nas colunas (parâmetros), a RLS ajuda a implementar restrições no acesso à linha de dados. Digamos que seu funcionário só possa acessar linhas de dados que são importantes para o departamento; você deve implementar a RLS. Se você quiser restringir, por exemplo, o acesso a dados do cliente que é relevante apenas para a empresa, poderá implementar a RLS. A restrição ao acesso das linhas é uma lógica localizada na camada de banco de dados, em vez de na camada de dados no nível do aplicativo. Se o 'Leo' precisar acessar dados de qualquer camada, o banco de dados deverá aplicar a restrição de acesso sempre que tentar acessar dados de outra camada. O motivo para fazer isso é garantir que sua segurança seja confiável e robusta, já que estamos reduzindo a área de superfície do sistema de segurança geral.

A maneira de implementar a RLS é usando a instrução CREATE SECURITY POLICY[!INCLUDEtsql]. Os predicados são criados como funções com valor de tabela embutida. É imperativo entender que, no Azure Synapse, há suporte apenas para predicados de filtro. Se você precisar usar um predicado de bloqueio, não conseguirá encontrar suporte no Azure Synapse no momento.

Esquema de RLS

Descrição da segurança em nível de linha em relação aos predicados de filtro

A RLS no Azure Synapse dá suporte a um tipo de predicados de segurança, que são predicados de filtro, não predicados de bloco.
O que os predicados de filtro fazem é filtrar silenciosamente as linhas que estão disponíveis para operações de leitura, como SELECT, UPDATE e DELETE.

O acesso a dados no nível da linha em uma tabela é restrito como uma função com valor de tabela embutida, que é um predicado de segurança. Essa função com valor de tabela será invocada e imposta pela política de segurança de que você precisa. Um aplicativo não está ciente de linhas que são filtradas do conjunto de resultados para predicados de filtro. Então, o que acontecerá é que, se todas as linhas forem filtradas, um conjunto nulo será retornado.

Quando você estiver usando predicados de filtro, ele será aplicado quando os dados forem lidos da tabela base. O predicado de filtro afeta todas as operações get, como SELECT, DELETE, UPDATE. Você não pode selecionar nem excluir linhas filtradas. Não é possível atualizar uma linha filtrada. O que você pode fazer é atualizar as linhas de uma forma que elas sejam filtradas posteriormente.

Casos de uso

Já mencionamos alguns casos de uso para RLS. Outro caso de uso pode ser criar um aplicativo multilocatário em que você cria uma política na qual as separações lógicas de linhas de dados de locatários de outras linhas de dados de locatários são impostas. Para implementar isso com eficiência, é altamente recomendável armazenar dados para muitos locatários em uma só tabela.

Os predicados de filtro RLS são funcionalmente equivalentes a acrescentar uma cláusula WHERE. O predicado pode ser tão sofisticado como ditam as práticas comerciais, ou a cláusula pode ser tão simples quanto WHERE TenantId = 42.

Quando examinamos a RLS mais formalmente, a RLS apresenta o controle de acesso baseado em predicado. O motivo pelo qual a RLS pode ser usada para controle de acesso de predicado é que é uma avaliação flexível, centralizada e baseada em predicado. O predicado de filtro pode ser baseado em metadados ou em outros critérios que você determine como sendo adequado. O predicado é usado como critério para determinar se o usuário tem acesso apropriado aos dados com base nos atributos de usuário. O controle de acesso baseado em rótulo pode ser implementado usando o controle de acesso baseado em predicado.

Permissões

Se você quiser criar, alterar ou remover as políticas de segurança, precisará usar a permissão ALTER ANY SECURITY POLICY. O motivo disso é que, quando você está criando ou descartando uma política de segurança, é necessário alterar (ALTER) as permissões no esquema.

Além disso, há outras permissões necessárias para cada predicado que você adiciona:

  • As permissões SELECT e REFERENCES na função com valor de tabela embutida sendo usada como predicado.

  • A permissão REFERENCES na tabela que você deseja associar à política.

  • permissãoREFERENCES em todas as colunas da tabela de destino usadas como argumentos.

Depois de configurar as políticas de segurança, elas serão aplicadas a todos os usuários (incluindo os usuários DBO no banco de dados) mesmo que os usuários DBO possam alterar ou remover políticas de segurança, suas alterações nas políticas de segurança podem ser auditadas. Se você tiver circunstâncias especiais em que usuários altamente privilegiados, como um sysadmin ou db_owner, precisam ver todas as linhas para solucionar problemas ou validar dados, ainda precisará escrever a política de segurança para permitir isso.

Se você tiver criado uma política de segurança em que SCHEMABINDING = OFF, para consultar a tabela de destino, o usuário precisará ter a permissão SCHEMABINDING = OFF ou EXECUTE na função de predicado. Ele também precisará de permissões para todas as tabelas, exibições ou funções adicionais usadas na função de predicado. Se uma política de segurança for criada com SCHEMABINDING = ON (o padrão), essas verificações de permissão serão ignoradas quando os usuários consultarem a tabela de destino.

Práticas recomendadas

É preciso considerar algumas práticas recomendadas quando você deseja implementar a RLS. Recomendamos criar um esquema separado para os objetos RLS. Os objetos RLS neste contexto seriam as funções de predicado e as políticas de segurança. Por que é uma prática recomendada? Isso ajuda a separar as permissões que são exigidas por esses objetos especiais das tabelas de destino. Além disso, a separação para diferentes políticas e funções de predicado pode ser necessária em bancos de dados multilocatários. No entanto, não é um padrão para todos os casos.

Outra prática recomendada a ser lembrada é que a permissão ALTER ANY SECURITY POLICY só deve ser destinada a usuários altamente privilegiados (como um Gerenciador de política de segurança). O gerenciador de política de segurança não exige permissão SELECT nas tabelas que ele protege.

Para evitar possíveis erros de runtime, você deve ter em mente as conversões de tipo em funções de predicado que você grava. Além disso, você deve tentar evitar a recursão em funções de predicado. O motivo disso é evitar a degradação do desempenho. Embora o otimizador de consulta tente detectar as recorrências diretas, não há nenhuma garantia de encontrar as recorrências indiretas. Com recursão indireta, estamos nos referindo a quando uma segunda função chama a função de predicado.

Também seria recomendável evitar o uso de junções de tabela excessivas em funções de predicado. Isso maximizaria o desempenho.

Falando de um modo geral, quando se trata da lógica dos predicados, você deve tentar evitar a lógica que depende das opções SET específicas da sessão. Embora seja muito improvável que elas sejam usadas em aplicações práticas, as funções de predicado cuja lógica depende de determinadas opções SET específicas da sessão podem perder informações se os usuários conseguem executar consultas arbitrárias. Por exemplo, uma função de predicado que implicitamente converte uma cadeia de caracteres em datetime poderia filtrar linhas diferentes com base na opção SET DATEFORMAT da sessão atual.