Patrones comunes para el filtrado de filas y el enmascaramiento de columnas

En esta página se describen patrones comunes para implementar directivas de filtro de fila y máscara de columna de ABAC.

Funciones de enmascaramiento compatibles con conversión

Azure Databricks convierte automáticamente la salida de la función de enmascaramiento para que coincida con el tipo de datos de la columna de destino. Consulte Conversión automática de tipos para máscaras de columna.

Los patrones siguientes ayudan a diseñar funciones de enmascaramiento compatibles con conversión.

Devolver un tipo que se puede convertir

Al enmascarar una columna, devuelva el mismo tipo de datos o un tipo que se pueda convertir a él. Compruebe los tipos de datos de las columnas que tiene como destino la directiva y compruebe que cada rama de la función devuelve un valor compatible.

-- 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 desbordamiento numérico

Cuando una función mask acepta y devuelve un tipo numérico más amplio que la columna de destino, el resultado se devuelve automáticamente al tipo de columna. Si el valor devuelto supera el rango del tipo más estrecho, la conversión se desborda y la consulta falla en tiempo de ejecución.

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

Uso de VARIANT para varios tipos de columna

Consulte Funciones de enmascaramiento basadas en VARIANTEs para varios tipos de columna.

Compatibilidad de conversión de pruebas

Pruebe las funciones de enmascaramiento con diferentes patrones de datos.

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;

Funciones de enmascaramiento basadas en VARIANT para varios tipos de columnas

Cuando necesite enmascarar columnas de distintos tipos de datos (por ejemplo, INT, DOUBLEDECIMAL(10,2), DECIMAL(15,5), , etc.), puede escribir una UDF de enmascaramiento única que acepte y devuelva un VARIANT tipo. Azure Databricks convierte automáticamente el resultado de la función de máscara de columna para que coincida con el tipo de datos de la columna de destino siguiendo los estándares de ANSI SQL.

Este enfoque reduce el número de UDFs y directivas necesarias. En lugar de escribir funciones de enmascaramiento independientes para cada tipo de columna, una función controla todos los tipos.

Enmascarar varios tipos numéricos con una sola función

En lugar de crear una función de máscara independiente para cada precisión numérica, puede usar VARIANT para gestionarlas todas con una sola función.

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

Esta función devuelve 0 como VARIANT, y Azure Databricks lo convierte automáticamente al tipo de la columna de destino. Una sola política de ABAC que use esta función puede enmascarar las columnas INT, DOUBLE y DECIMAL sin la necesidad de funciones separadas para cada exactitud.

Si prefiere conservar el tipo explícitamente dentro de la función, puede realizar una bifurcación basada en el tipo y devolver un valor enmascarado adecuado para cada tipo mediante 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;

Enmascarar columnas de estructuras con VARIANT

Para Databricks Runtime 18.1 y versiones posteriores, también puede enmascarar las columnas de estructura convirtiéndolas a VARIANT en una directiva de ABAC. Establezca una rama en la forma de la estructura para censurar campos de forma selectiva:

Note

La conversión de estructuras a VARIANT para enmascaramiento solo se admite en directivas de máscara de columna de ABAC.

En el ejemplo siguiente se usa schema_of_variant() para identificar dos formas struct diferentes y redactar campos confidenciales en cada uno de ellos:

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 el acceso hasta que se etiquetan las columnas confidenciales

Un patrón de gobernanza común es controlar el acceso en función de si los datos se han clasificado. Puede implementarlo con una etiqueta y directivas restrictivas predeterminadas que apliquen distintos niveles de protección en función del estado de clasificación.

  1. Aplique una etiqueta como classification : unverified a todos los objetos nuevos de forma predeterminada, mediante la automatización o la herencia de etiquetas aplicando la etiqueta en el nivel de catálogo o esquema, de modo que las nuevas tablas agregadas al catálogo o esquema hereden automáticamente la etiqueta.
  2. Cree una directiva de filtro de fila que bloquee el acceso a las tablas etiquetadas classification : unverified.
  3. Cree una directiva de máscara de columna que enmascara columnas confidenciales en tablas donde la classification : unverified etiqueta ya no esté presente.
  4. Cuando un administrador de datos completa la clasificación, actualiza la etiqueta. La directiva de bloqueo ya no coincide y la directiva de enmascaramiento surte efecto.
-- 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 los datos confidenciales después de clasificarlos, defina una directiva de máscara de columna que surte efecto cuando la classification : unverified etiqueta ya no esté 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;

Revelado parcial sin regex

Mostrar parte de un valor confidencial mediante operaciones de cadena en lugar de regex. El enmascaramiento basado en expresiones regulares examina todo el valor de cada fila, lo cual es costoso en campos de texto grandes (consulte Evitar enmascaramiento de expresiones regulares en campos de texto grandes).

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

Hash coherente (pseudonimización determinista)

El hash coherente (también denominado seudonimización determinista) reemplaza los datos confidenciales por un valor hash que es el mismo en varias tablas. Al marcar una función como DETERMINISTIC se indica al motor que la función siempre devuelve el mismo resultado para la misma entrada, lo que ayuda a optimizar la consulta. Consulte Uso de expresiones deterministas y seguras para errores.

La siguiente función aplica un hash coherente a un valor de cadena y usa un version parámetro para admitir la rotación de claves. Incremente el version número mediante la cláusula de la directiva USING COLUMNS para generar nuevos hashes sin interrumpir los datos históricos que usaron la versión anterior. La función concatena el valor original con el número de versión antes de aplicar hash, por lo que la misma entrada con la misma versión siempre genera el mismo hash.

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

Enmascarar una columna basada en los atributos del usuario que consulta

Importante

Los atributos de identidad en las políticas ABAC están en Beta. Para utilizarlos, un administrador de cuenta debe habilitar los Atributos de Identidad en la vista previa de Políticas ABAC desde la página de Previsualizaciones de la consola de cuentas. Consulte Gestionar previsualizaciones a nivel de cuenta.

Una política de mascarilla en columna puede usar los atributos de identidad del usuario que consulta para enmascarar datos sensibles sin requerir grupos dedicados. Por ejemplo, puede mantener los datos sin enmascarar para los usuarios con department = HR y enmascararlos para todos los demás.

Estos patrones requieren atributos de identidad provisibles a tus usuarios desde tu proveedor de identidad, y las funciones se comportan de forma diferente a las condiciones solo de etiqueta en aspectos que afectan a cómo escribes la política. Antes de usarlos, revisa las funciones de atributos de identidad y atributos de identidad.

Importante

Las funciones devuelven false cuando el usuario no tiene ningún valor para el atributo o cuando la clave del atributo no existe. Escribe la condición de modo que este false resultado restrinja el acceso en lugar de concederlo. Niega la coincidencia con NOT para que la máscara se aplique a menos que el atributo coincida. Por ejemplo, WHEN NOT has_identity_attribute_value('department', 'HR') enmascara la columna para todos excepto para los usuarios cuyo departamento es HR, y, como un valor ausente también es false, los usuarios que no tienen atributo de departamento también quedan enmascarados. Evita lo contrario: una condición que enmascara solo cuando el atributo coincide deja sin enmascarar a los usuarios que no tienen valor para el atributo.

Para el comportamiento de evaluación, véase Condiciones de atributo de identidad. Para limitaciones, véase Atributos de identidad en condiciones de política.

Coincidir con un valor fijo

Ocultar ssn para todos cuyo departamento no sea 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;

En este ejemplo, un usuario cuyo departamento HR pertenece ve valores reales. Un usuario de cualquier otro departamento, y un usuario sin atributo de departamento, ambos ven la máscara.

Coincidencia con una etiqueta regulada

El ejemplo anterior nombra un valor de atributo específico (HR) en la política, por lo que cubrir varios departamentos significaría redactar una política separada para cada uno. Para cubrir todos los departamentos con una única política, etiqueta cada tabla con el departamento que la posee y luego compara el atributo del department usuario que consulta con esa etiqueta. La columna se muestra solo cuando el departamento del usuario coincide con el valor de dept_tag de la tabla:

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;

Tanto las claves como los valores de los atributos distinguen entre mayúsculas y minúsculas, y los valores se comparan de forma exacta: Finance y finance no coinciden.

Restringir el acceso para agentes externos que actúan en nombre de un usuario

Importante

Los atributos de contexto en las políticas ABAC están en Beta. Para utilizarlos, un administrador de cuenta debe activar la vista previa de Atributos de Contexto UC ABAC desde la página de Previsualizaciones de la consola de cuentas. Consulte Gestionar previsualizaciones a nivel de cuenta.

Los atributos de contexto pueden usarse para restringir el acceso a los datos de solicitudes realizadas en nombre de un usuario a través de una aplicación OAuth. Si los agentes están conectados mediante OAuth, esta configuración puede usarse para evitar que accedan a los datos cuando actúan en nombre de un usuario, aunque el usuario pueda seguir leyendo los datos cuando los consulta directamente en el espacio de trabajo.

Cualquier acceso autenticado por OAuth a través de la CLI de Azure Databricks, los SDKs o la API de Ejecución de Sentencias SQL se establece request.is_on_behalf_of en 'true', incluso cuando un usuario consulta manualmente. El acceso autenticado con un token de acceso personal (PAT) no lo hace. El acceso a Genie no se puede capturar a través de este mecanismo porque no establece request.is_on_behalf_of en 'true'.

Estos patrones utilizan las funciones de atributo contextual. Para los atributos y comportamientos disponibles, véase Funciones de atributos de contexto (Beta).

Configura un agente para enviar atributos de contexto

Para usar atributos contextuales, conecta el agente a Azure Databricks usando una aplicación OAuth personalizada:

  1. Un administrador de la cuenta activa la vista previa de atributos de contexto de UC ABAC en la consola de la cuenta. Consulte Administrar versiones preliminares de Azure Databricks.
  2. Un administrador de cuenta registra una aplicación OAuth personalizada en la consola de cuenta y anota su ID de cliente. Consulte Habilitar o deshabilitar aplicaciones de OAuth asociadas.
  3. Conecta el agente al MCP gestionado por Azure Databricks a través de esa aplicación OAuth. Consulte Conectar clientes mediante la autenticación OAuth.

Un agente que utiliza el cliente integrado databricks-cli sigue autenticándose sobre OAuth, por lo que request.is_on_behalf_of lee 'true'. Sin embargo, no puedes distinguir sus peticiones del uso manual de la CLI, porque ambas comparten el ID del databricks-cli cliente. Para gobernar una aplicación específica, registra una aplicación OAuth personalizada y conecta el agente a través de ella.

Para conceptos de OAuth, véase Autorizar el acceso del usuario a Azure Databricks con OAuth.

Warning

Asegúrate de que un agente no pueda acceder a los datos por una ruta que tu póliza no cubra:

  • Si restringes el acceso en función de request.is_on_behalf_of, asegúrate de que el agente no pueda autenticarse con un PAT. Un PAT no configura request.is_on_behalf_of con el valor 'true', por lo que una condición sobre ese atributo no lo restringe.
  • Si restringes el acceso en función de request.client_id, asegúrate de que el agente no pueda conectarse a través de un cliente que tu condición no cubra, como el cliente genérico databricks-cli .

Ocultar una columna para solicitudes en nombre de otro

Oculte ssn para las solicitudes que se ejecutan en nombre de un usuario, como un agente que actúa a través de una aplicación OAuth registrada, mientras que lo deja visible para las consultas directas:

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;

En este ejemplo, una consulta directa devuelve valores reales y una solicitud en nombre de otro muestra los valores enmascarados. Usando la CLI y la API de ejecución de instrucciones SQL, request.is_on_behalf_of también lee 'true', así que esta política enmascara la columna para esas solicitudes también. Para dirigirse a una aplicación específica, compara request.client_id con el ID de cliente de esa aplicación.

Restringir una columna a una solicitud aprobada

Oculta ssn para todas las solicitudes externas, excepto las de tu aplicación aprobada, identificada por su 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 qué aplicación ha hecho una solicitud, inspecciona el identity_metadata.acting_resource campo en los registros de auditoría.

Filtrado de filas con predicados que utilizan columnas exclusivamente

Filtre las filas mediante una lógica booleana simple que haga referencia solo a columnas de tabla. Los predicados de solo columna habilitan la delegación de predicados, lo que permite al motor omitir datos irrelevantes durante los análisis (consulte Descripción de la delegación de predicados en tablas protegidas).

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

Use con una directiva que pase las regiones permitidas como 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');

Filtrado de filas entre varias columnas relacionadas

Cuando una tabla tiene varias columnas que representan atributos relacionados (por ejemplo, ship_to_country y bill_to_country), puede coincidir con condiciones de etiqueta independientes y pasar ambas a una sola UDF. Esto evita la creación de directivas independientes para cada columna. Una directiva puede incluir hasta tres expresiones de columna en la MATCH COLUMNS cláusula (consulte Cuotas de directiva).

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

Un analista solo ve pedidos en los que el país de envío o de facturación está en su lista permitida.

Tablas de búsqueda en las UDFs de políticas ABAC

Cuando las reglas de acceso varían por usuario y no se pueden expresar solo a través de las cláusulas de TO/EXCEPT la directiva, puede comprobar los derechos de acceso en una tabla de búsqueda pequeña. Utilice TO/EXCEPT siempre que sea posible, ya que es el enfoque preferido para las entidades de seguridad de destino (consulte Enfoque para entidades de seguridad de destino). Mantenga pequeña la tabla de búsqueda para que el optimizador convierta la subconsulta en una unión de hash de difusión (consulte Mantener pequeñas las tablas de búsqueda).

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