Padrões comuns para filtragem de linhas e mascaramento de coluna

Esta página descreve padrões comuns para implementar políticas de filtro de linha ABAC e máscara de coluna.

Funções de mascaramento compatíveis com conversão

Azure Databricks converte automaticamente a saída da função de mascaramento para corresponder ao tipo de dados da coluna de destino. Consulte Conversão automática de tipo para máscaras de coluna.

Os padrões a seguir ajudam você a criar funções de mascaramento compatíveis com casting.

Retornar um tipo que possa ser convertido

Ao mascarar uma coluna, retorne o mesmo tipo de dados ou um tipo que pode ser convertido nela. Verifique os tipos de dados das colunas visadas pela política e assegure-se de que cada ramificação da função retorna um valor compatível.

-- Succeeds: Masks a DOUBLE column, returns DOUBLE in every branch
CREATE FUNCTION mask_salary(salary DOUBLE, user_role STRING)
RETURNS DOUBLE
RETURN CASE
  WHEN user_role IN ('admin', 'hr') THEN salary
  WHEN user_role = 'manager' THEN ROUND(salary / 1000) * 1000
  ELSE 0.0
END;

-- Fails: 'CONFIDENTIAL' cannot be cast to a DOUBLE column type
CREATE FUNCTION mask_salary_as_text(salary DOUBLE, user_role STRING)
RETURNS STRING
RETURN CASE
  WHEN user_role IN ('admin', 'hr') THEN CAST(salary AS STRING)
  ELSE 'CONFIDENTIAL'
END;

Evitar estouro numérico

Quando uma função de máscara aceita e retorna um tipo numérico mais amplo do que a coluna de destino, o resultado é convertido automaticamente para o tipo da coluna. Se o valor exibido exceder o intervalo do tipo mais restrito, a conversão resultará em estouro e a consulta falhará em runtime.

-- The target column is TINYINT (max 127). The input is upcast to BIGINT
-- for the function. Adding 1000 produces a BIGINT result that overflows
-- when cast back to TINYINT.
CREATE FUNCTION mask_score(score BIGINT)
RETURNS BIGINT
RETURN score + 1000;

Usar VARIANT para vários tipos de coluna

Consulte funções de mascaramento baseadas em VARIANT para vários tipos de coluna.

Compatibilidade de conjunto de testes

Teste funções de mascaramento com diferentes padrões de dados.

SELECT CAST(mask_salary(salary, 'admin') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'manager') AS DOUBLE) FROM employees;
SELECT CAST(mask_salary(salary, 'viewer') AS DOUBLE) FROM employees;

Funções de mascaramento baseadas em VARIANT para vários tipos de coluna

Quando você precisa mascarar colunas de diferentes tipos de dados (por exemplo, INT, DOUBLE, DECIMAL(10,2), DECIMAL(15,5), e assim por diante), você pode escrever uma única UDF de máscara que aceita e retorna um tipo VARIANT. O Azure Databricks converte automaticamente a saída da função de máscara de coluna para corresponder ao tipo de dados da coluna de destino seguindo os padrões SQL ANSI.

Essa abordagem reduz o número de UDFs e políticas necessárias. Em vez de escrever funções de mascaramento separadas para cada tipo de coluna, uma função manipula todos os tipos.

Mascarar vários tipos numéricos com uma única função

Em vez de criar uma função de máscara separada para cada precisão numérica, você pode usar VARIANT para lidar com todas elas com uma única função:

CREATE FUNCTION mask_numeric(val VARIANT)
RETURNS VARIANT
DETERMINISTIC
RETURN 0::VARIANT;

Essa função retorna 0 como um VARIANT, que o Azure Databricks converte automaticamente para o tipo da coluna de destino. Uma única política ABAC usando essa função pode mascarar INT, DOUBLEe DECIMAL colunas sem exigir funções separadas para cada precisão.

Se preferir preservar o tipo explicitamente dentro da função, você poderá ramificar no tipo e retornar um valor mascarado apropriado para cada um usando schema_of_variant():

-- Use VARIANT to accommodate different data types
CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
  WHEN schema_of_variant(data) = 'INT' THEN 0::VARIANT
  WHEN schema_of_variant(data) = 'DATE' THEN DATE'1970-01-01'::VARIANT
  WHEN schema_of_variant(data) = 'DOUBLE' THEN 0.00::VARIANT
  ELSE NULL::VARIANT
END;

Mascarar colunas struct com VARIANT

Para o Databricks Runtime 18.1 e posterior, você também pode mascarar colunas struct convertendo-as em VARIANT em uma política ABAC. Ramificação na forma do struct para editar seletivamente os campos:

Observação

A conversão de structs em VARIANT durante o mascaramento tem suporte apenas nas políticas de máscara de coluna ABAC.

O exemplo a seguir usa schema_of_variant() para identificar duas formas de struct diferentes e redigir campos confidenciais em cada uma:

CREATE FUNCTION flexible_mask(data VARIANT)
RETURNS VARIANT
RETURN CASE
WHEN schema_of_variant(data) = 'OBJECT<age: BIGINT, email: STRING>' THEN
  to_variant_object(named_struct('age', data:age, 'email', 'redacted'))
WHEN schema_of_variant(data) = 'OBJECT<id: BIGINT, ssn: STRING>' THEN
  to_variant_object(named_struct('id', data:id, 'ssn', 'xxx-xx-xxxx'))
ELSE NULL::VARIANT
END;

Impedir o acesso até que colunas confidenciais sejam marcadas

Um padrão de governança comum é controlar o acesso com base em se os dados foram classificados. Você pode implementá-lo com uma marca restritiva padrão e políticas que impõem diferentes níveis de proteção, dependendo do status de classificação.

  1. Aplique uma marca como classification : unverified a todos os novos objetos por padrão, por meio da automação ou por meio da herança da marca aplicando a marca no nível de catálogo ou esquema, de modo que quaisquer novas tabelas adicionadas ao catálogo ou esquema herdem automaticamente a marca.
  2. Crie uma política de filtro de linha que bloqueia o acesso a tabelas marcadas classification : unverified.
  3. Crie uma política de máscara para coluna que oculte colunas confidenciais em tabelas onde a tag classification : unverified não está mais presente.
  4. Quando um administrador de dados conclui a classificação, ele atualiza a etiqueta. A política de bloqueio não corresponde mais e a política de mascaramento entra em vigor.
-- Block access to unverified tables for all non-admin users
CREATE FUNCTION catalog.schema.block_all() RETURNS BOOLEAN
  RETURN FALSE;

CREATE POLICY block_unverified
ON CATALOG my_catalog
ROW FILTER catalog.schema.block_all
TO `account users` EXCEPT `data_admins`
FOR TABLES
WHEN has_tag_value('classification', 'unverified');

Para proteger dados confidenciais depois de classificados, defina uma política de máscara de coluna que se aplica quando a marca classification : unverified não estiver mais presente:

CREATE FUNCTION catalog.schema.mask_pii(val STRING)
RETURNS STRING
RETURN '***';

CREATE POLICY mask_reviewed_pii
ON CATALOG my_catalog
COLUMN MASK catalog.schema.mask_pii
TO `account users`
EXCEPT `data_admins`
FOR TABLES
WHEN NOT has_tag_value('classification', 'unverified')
MATCH COLUMNS (has_tag_value('pii', 'name') OR has_tag_value('pii', 'address')) AS m
ON COLUMN m;

Revelação parcial sem regex

Revele parte de um valor confidencial usando operações de cadeia de caracteres em vez de regex. O mascaramento baseado em Regex verifica todo o valor de cada linha, que é caro em campos de texto grandes (consulte Evitar máscara regex em campos de texto grandes).

CREATE FUNCTION mask_ssn(ssn STRING, show_last INT) RETURNS STRING
DETERMINISTIC
  RETURN CONCAT('***-**-', RIGHT(ssn, show_last));

Hashing consistente (pseudonimização determinística)

O hash consistente (também chamado de pseudonimização determinística) substitui dados confidenciais por um valor hash que é o mesmo em várias tabelas. Marcar uma função informa DETERMINISTIC ao mecanismo que a função sempre retorna o mesmo resultado para a mesma entrada, o que a ajuda a otimizar a consulta. Consulte Usar expressões determinísticas e protegidas contra erros.

A função a seguir faz um hash consistente de um valor de string e usa um parâmetro version para dar suporte à rotação de chaves. Incremente o número version mediante a cláusula USING COLUMNS da política para gerar novos hashes sem afetar dados históricos que usaram a versão anterior. A função concatena o valor original com o número de versão antes do hash, portanto, a mesma entrada com a mesma versão sempre produz o mesmo hash.

CREATE FUNCTION pseudonymize(val STRING, version INT) RETURNS STRING
DETERMINISTIC
  RETURN SHA2(CONCAT(val, CAST(version AS STRING)), 256);

Mascarar uma coluna com base nos atributos do usuário que está consultando

Importante

Os atributos de identidade nas políticas ABAC estão em Beta. Para usá-los, um administrador da conta deve habilitar a prévia Atributos de Identidade em Políticas ABAC na página Prévias do console da conta. Consulte Gerenciar visualizações no nível da conta.

Uma política de máscara de coluna pode usar os atributos de identidade do usuário que consulta para mascarar dados sensíveis sem exigir grupos dedicados. Por exemplo, ele pode manter os dados sem máscara para usuários com department = HR e mascará-los para todos os outros.

Esses padrões exigem atributos de identidade fornecidos aos seus usuários pelo seu provedor de identidade, e as funções se comportam de forma diferente das condições apenas de tags, afetando a forma como você escreve a política. Antes de usá-los, consulte as funções de atributos de identidade e atributos de identidade.

Importante

As funções resultam em false quando o usuário não tem valor para o atributo ou quando a chave do atributo não existe. Escreva a condição de forma que esse false resultado restrinja o acesso em vez de concedê-lo. Negue a correspondência com NOT para que a máscara se aplique, a menos que o atributo corresponda. Por exemplo, WHEN NOT has_identity_attribute_value('department', 'HR') mascara a coluna para todos, exceto para usuários cujo departamento é HR, e, como um valor ausente também é false, os usuários sem o atributo de departamento também são mascarados. Evite o contrário: uma condição que mascara apenas quando o atributo corresponde deixa usuários que não têm valor para o atributo desmascarados.

Para comportamento de avaliação, veja Condições de atributo de identidade. Para limitações, veja Atributos de Identidade em condições de política.

Corresponda a um valor fixo

Mascarar ssn para todos cujo departamento não é HR:

CREATE FUNCTION hr_catalog.people.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_ssn_non_hr
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_identity_attribute_value('department', 'HR')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

Neste exemplo, um usuário cujo departamento é HR vê valores reais. Um usuário em qualquer outro departamento e um usuário sem o atributo de departamento ambos veem a máscara.

Luta contra uma tag governada

O exemplo anterior nomeia um valor de atributo específico (HR) na política, então cobrir vários departamentos significaria escrever uma política separada para cada um. Para cobrir todos os departamentos com uma única política, marque cada tabela com o departamento que a possui e compare o atributo do department usuário que faz a consulta com essa tag. A coluna é revelada apenas quando o departamento do usuário corresponde ao valor da dept_tag tabela:

CREATE FUNCTION prod.sales.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_unless_dept_matches
ON SCHEMA prod.sales
COLUMN MASK prod.sales.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_identity_attribute_tag_match('department', 'dept_tag')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

Chaves de atributos e valores são ambos sensíveis a maiúsculas e minúsculas, e os valores são comparados exatamente: Finance e finance não correspondem.

Restringa o acesso para agentes externos que atuam em nome de um usuário

Importante

Os atributos de contexto nas políticas ABAC estão em Beta. Para usá-los, um administrador de conta deve ativar a prévia dos Atributos de Contexto do UC ABAC na página de Pré-visualizações do console da conta. Consulte Gerenciar visualizações no nível da conta.

Atributos de contexto podem ser usados para restringir o acesso a dados em requisições feitas em nome do usuário por meio de uma aplicação OAuth. Se os agentes estiverem conectados via OAuth, essa configuração pode ser usada para impedir que eles acessem dados quando agem em nome de um usuário, mesmo que o usuário ainda possa ler os dados ao consultá-los diretamente no espaço de trabalho.

Qualquer acesso autenticado por OAuth através da CLI do Azure Databricks, dos SDKs ou da API de Execução de Instruções SQL define request.is_on_behalf_of para 'true', mesmo quando o usuário está consultando manualmente. O acesso autenticado com um token de acesso pessoal (PAT) não tem isso. O acesso do Genie não pode ser registrado por esse mecanismo porque ele não define request.is_on_behalf_of como 'true'.

Esses padrões utilizam as funções de atributo de contexto. Para atributos e comportamentos disponíveis, veja Funções de atributos de contexto (Beta).

Configure um agente para enviar atributos de contexto

Para usar atributos de contexto, conecte o agente ao Azure Databricks usando uma aplicação OAuth personalizada:

  1. Um administrador de conta ativa a pré-visualização dos Atributos de Contexto UC ABAC a partir do console da conta. Consulte Gerenciar visualizações do Azure Databricks.
  2. Um administrador de conta registra um aplicativo OAuth personalizado no console da conta e registra seu ID de cliente. Confira Habilitar ou desabilitar aplicativos OAuth de parceiros.
  3. Conecte o agente ao MCP gerenciado pelo Azure Databricks por meio dessa aplicação OAuth. Consulte Conectar clientes usando autenticação OAuth

Um agente que usa o cliente integrado databricks-cli ainda se autentica via OAuth, portanto request.is_on_behalf_of'true'. No entanto, você não pode distinguir suas solicitações do uso manual da CLI, porque ambas compartilham o ID de cliente databricks-cli. Para governar uma aplicação específica, registre uma aplicação OAuth personalizada e conecte o agente por meio dela.

Para conceitos de OAuth, veja Autorizar o acesso do usuário ao Azure Databricks com OAuth.

Warning

Certifique-se de que um agente não possa acessar os dados por um caminho que sua apólice não cobre:

  • Se você restringir o acesso com base em request.is_on_behalf_of, certifique-se de que o agente não possa autenticar com um PAT. Um PAT não define request.is_on_behalf_of como 'true', então uma condição sobre esse atributo não o restringe.
  • Se você restringir o acesso com base em request.client_id, certifique-se de que o agente não possa se conectar por meio de um cliente que não esteja coberto pela condição, como o cliente genérico databricks-cli.

Mascarar uma coluna para solicitações em nome de outra pessoa

Mascare ssn para solicitações executadas em nome de um usuário, como um agente agindo por meio de um aplicativo OAuth registrado, mantendo-o sem mascaramento para consultas diretas:

CREATE FUNCTION hr_catalog.people.mask_ssn(s STRING) RETURNS STRING RETURN '***-**-****';

CREATE OR REPLACE POLICY mask_ssn_for_agents
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN has_context_attribute_value('request.is_on_behalf_of', 'true')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

Neste exemplo, uma consulta direta retorna valores reais, e uma solicitação em nome de outra entidade exibe os valores mascarados. Usando a CLI e a API de Execução de Instruções SQL, request.is_on_behalf_of também lê 'true', então essa política também mascara a coluna para essas requisições. Para direcionar uma aplicação específica, compare request.client_id com o ID do cliente dessa aplicação.

Restringir uma coluna a um aplicativo aprovado

Mascare ssn para todas as requisições externas, exceto as provenientes do seu aplicativo aprovado, identificado pelo seu ID de cliente OAuth:

CREATE OR REPLACE POLICY mask_ssn_unapproved_apps
ON SCHEMA hr_catalog.people
COLUMN MASK hr_catalog.people.mask_ssn
TO `account users`
FOR TABLES
WHEN NOT has_context_attribute_value('request.client_id', '<your-app-client-id>')
MATCH COLUMNS has_tag_value('pii', 'ssn') AS ssn_col
ON COLUMN ssn_col;

Para ver qual aplicação fez uma solicitação, inspecione o identity_metadata.acting_resource campo nos logs de auditoria.

Filtragem de linhas com predicados somente de coluna

Filtrar linhas usando uma lógica booliana simples que referencia apenas colunas de tabela. Os predicados de somente coluna permitem o processamento de predicado, o que possibilita que o mecanismo ignore dados irrelevantes durante as verificações (consulte Entender o processamento de predicado em tabelas protegidas).

CREATE FUNCTION filter_by_region(region STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
  RETURN array_contains(split(allowed, ','), lower(region));

Use com uma política que transmita as regiões permitidas como uma constante:

CREATE POLICY regional_access
ON CATALOG analytics
ROW FILTER filter_by_region
TO 'emea_team'
FOR TABLES
MATCH COLUMNS has_tag('region') AS rgn
USING COLUMNS (rgn, 'emea,apac');

Filtragem de linha em várias colunas relacionadas

Quando uma tabela tem várias colunas que representam atributos relacionados (por exemplo, ship_to_country e bill_to_country), você pode combiná-las com condições de marca separadas e passar ambas para uma única UDF. Isso evita a criação de políticas separadas para cada coluna. Uma política pode incluir até três expressões de coluna na cláusula MATCH COLUMNS (consulte cotas de política).

CREATE FUNCTION filter_by_countries(ship_country STRING, bill_country STRING, allowed STRING)
RETURNS BOOLEAN
DETERMINISTIC
  RETURN array_contains(split(allowed, ','), lower(ship_country))
      OR array_contains(split(allowed, ','), lower(bill_country));

CREATE POLICY regional_orders
ON SCHEMA prod.orders
ROW FILTER filter_by_countries
TO analysts
FOR TABLES
WHEN has_tag_value('sensitivity', 'high')
MATCH COLUMNS
  has_tag('ship_country') AS ship,
  has_tag('bill_country') AS bill
USING COLUMNS (ship, bill, 'us,ca,mx');

Um analista vê apenas pedidos em que o país de remessa ou cobrança está em sua lista autorizada.

Tabelas de pesquisa em UDFs de políticas ABAC

Quando as regras de acesso variam por usuário e não podem ser expressas apenas por meio das cláusulas da TO/EXCEPT política, você pode verificar os direitos de acesso em uma tabela de pesquisa pequena. Use TO/EXCEPT quando possível, pois é a abordagem preferencial para entidades principais de destino (consulte Abordagem para entidades principais de destino). Mantenha a tabela de pesquisa pequena para que o otimizador converta a subconsulta em uma junção de hash de transmissão (consulte Manter tabelas de pesquisa pequenas).

CREATE TABLE access_rules (
  principal VARCHAR(255),
  priority VARCHAR(64)
);

INSERT INTO access_rules VALUES
  ('alice@company.com', '1-URGENT'),
  ('alice@company.com', '2-HIGH'),
  ('bob@company.com', '1-URGENT');

CREATE FUNCTION priority_allowed(o_priority STRING) RETURNS BOOLEAN
RETURN EXISTS (
  SELECT 1 FROM access_rules
  WHERE principal = session_user() AND priority = o_priority
);

CREATE POLICY priority_filter
ON CATALOG operations
ROW FILTER priority_allowed
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('priority') AS pri
USING COLUMNS (pri);