Uso de tablas de mapeo para el control de acceso dinámico

En este tutorial se muestra cómo usar una tabla de mapeo para controlar el acceso a nivel de fila y columna sin gestionar un gran número de grupos. Una sola tabla de búsqueda controla el filtrado de filas y el enmascaramiento de columnas. Los cambios de acceso solo requieren una actualización de una fila. No es necesario crear nuevos grupos ni volver a escribir directivas.

En este tutorial también se muestra el enmascaramiento condicional: las columnas PII se enmascaran de forma diferente en función del valor de otra columna de la misma fila. Los pedidos marcados confidential tienen su PII completamente censurado independientemente del nivel de autorización del usuario.

Para obtener instrucciones generales sobre el diseño de tablas de asignación, consulte Uso de tablas de asignación para crear una lista de control de acceso.

Prerrequisitos

  • Databricks Runtime 16.4 o superior, o computación sin servidor.
  • Permisos de administrador de cuenta o administrador del área de trabajo (para crear etiquetas reguladas).
  • MANAGE permiso de acceso en el catálogo o esquema de destino.
  • EXECUTE en las UDF.
  • Un cuaderno de SQL o un editor de consultas.

Escenario

Su organización tiene empleados en cuatro regiones (Este de EE. UU., Oeste de EE. UU., EU, APAC) y cuatro departamentos. Cada usuario debe ver solo las filas que coinciden con su región y departamento, y las columnas PII deben enmascararse en función de dos factores: el nivel de autorización del usuario (full, masked o none), que se almacena en una tabla de mapeo, y el del pedido order_priority.

Con un enfoque basado en grupos, necesita un grupo para cada combinación de región y departamento. Por ejemplo, necesita 16 grupos para cuatro regiones y cuatro departamentos. Agregar niveles de autorización de información personal identificable triplica esa cantidad. Cada nueva región o departamento requiere nuevos grupos y actualizaciones de directivas.

El enfoque de tabla de mapeo lo reemplaza por una sola tabla de búsqueda: una fila por usuario, una columna por la dimensión de acceso. Para cambiar el acceso de un usuario, actualice una fila.

Paso 1: Crear etiquetas reguladas

Antes de ejecutar cualquier SQL, cree las siguientes etiquetas reguladas en la interfaz de usuario del Explorador de Catálogo (Catálogo>Regular>Etiquetas Reguladas>Crear etiqueta regulada):

Clave de etiqueta Valores permitidos
region (etiqueta solo clave)
department (etiqueta solo clave)
pii name, email
priority (etiqueta solo clave)

Las etiquetas region y department indican a la política del filtro de fila qué columnas se deben pasar a la UDF de filtro. La pii etiqueta indica a las directivas de máscara de columna qué columnas se van a enmascarar y qué tipo de PII contienen. La priority etiqueta permite que las directivas de máscara de columna pasen el order_priority valor a la UDF de máscara para el enmascaramiento condicional.

Advertencia

Los datos de etiqueta se almacenan como texto sin formato y se pueden replicar globalmente. No use nombres de etiqueta, valores ni descriptores que puedan poner en peligro la seguridad de los recursos. Por ejemplo, no use nombres de etiqueta, valores o descriptores que contengan información personal o confidencial.

Paso 2: Compilación de datos de ejemplo

Cree una tabla de catálogos, esquemas y pedidos. La order_priority columna controla el enmascaramiento condicional: los pedidos marcados confidential tienen su información de identificación personal (IIP) completamente redactada, incluso para usuarios con un alto nivel de autorización.

CREATE CATALOG IF NOT EXISTS abac_tutorial;
USE CATALOG abac_tutorial;

CREATE SCHEMA IF NOT EXISTS mapping_demo;
USE SCHEMA mapping_demo;
CREATE OR REPLACE TABLE orders (
  order_id INT,
  customer_name STRING,
  customer_email STRING,
  sales_region STRING,
  dept STRING,
  amount DOUBLE,
  order_date DATE,
  order_priority STRING
);

INSERT INTO orders VALUES
  (1,  'Acme Corp',     'orders@acme.com',    'us_east', 'engineering', 50000,  '2025-01-15', 'standard'),
  (2,  'Beta Inc',      'sales@beta.com',     'us_east', 'sales',       75000,  '2025-02-01', 'confidential'),
  (3,  'Gamma LLC',     'info@gamma.com',     'us_west', 'engineering', 30000,  '2025-01-20', 'standard'),
  (4,  'Delta Co',      'deals@delta.com',    'us_west', 'sales',       95000,  '2025-03-01', 'confidential'),
  (5,  'Epsilon GmbH',  'kontakt@epsilon.de', 'eu',      'engineering', 45000,  '2025-02-15', 'standard'),
  (6,  'Zeta SA',       'contact@zeta.fr',    'eu',      'sales',       62000,  '2025-01-30', 'standard'),
  (7,  'Eta Ltd',       'hello@eta.sg',       'apac',    'marketing',   28000,  '2025-03-10', 'confidential'),
  (8,  'Theta Corp',    'biz@theta.com',      'us_east', 'marketing',   55000,  '2025-02-20', 'standard'),
  (9,  'Iota KK',       'info@iota.jp',       'apac',    'engineering', 41000,  '2025-01-25', 'standard'),
  (10, 'Kappa Inc',     'sales@kappa.com',    'us_west', 'marketing',   33000,  '2025-03-05', 'standard');

Paso 3: Aplicar etiquetas reguladas

Etiquete las columnas para que las directivas de ABAC puedan detectarlas automáticamente. La order_priority columna se etiqueta con la etiqueta de solo clave priority para que las políticas de máscara de columna puedan coincidir mediante MATCH COLUMNS y pasar su valor a la UDF de máscara.

ALTER TABLE abac_tutorial.mapping_demo.orders
  ALTER COLUMN sales_region SET TAGS ('region' = '');
ALTER TABLE abac_tutorial.mapping_demo.orders
  ALTER COLUMN dept SET TAGS ('department' = '');
ALTER TABLE abac_tutorial.mapping_demo.orders
  ALTER COLUMN customer_name SET TAGS ('pii' = 'name');
ALTER TABLE abac_tutorial.mapping_demo.orders
  ALTER COLUMN customer_email SET TAGS ('pii' = 'email');
ALTER TABLE abac_tutorial.mapping_demo.orders
  ALTER COLUMN order_priority SET TAGS ('priority' = '');

Paso 4: Crear la tabla de asignación

En lugar de crear grupos para cada región, departamento y combinación de liquidación, se mantiene una tabla con una fila por usuario. La pii_access columna controla cómo aparecen las columnas PII:

  • full — consulte el valor real (para los pedidos de prioridad estándar)
  • masked — ver un valor parcial como A*** o o***@acme.com
  • none — ver ***REDACTED***

La expires_on columna establece una fecha de expiración para cada entrada de acceso. Después de esta fecha, la UDF del filtro de fila deja de coincidir con la entrada y el usuario pierde silenciosamente el acceso sin necesidad de revocación manual. Esto es útil para contratistas, contratos de uso compartido de datos temporales o proyectos limitados por tiempo.

Si un usuario necesita acceso a varias combinaciones de regiones y departamentos, agregue filas adicionales.

Note

Mantenga las tablas de asignación pequeñas y sencillas. Cada consulta en una tabla protegida ejecuta las UDF de filtro de fila y máscara de columna, que a su vez consultan la tabla de asignación. Las tablas de asignación grandes y la lógica compleja de UDF pueden afectar al rendimiento de las consultas. Use esquemas estrechos y mantenga la lógica de UDF en una sola búsqueda siempre que sea posible.

CREATE OR REPLACE TABLE abac_tutorial.mapping_demo.user_access (
  user_email STRING,
  region STRING,
  department STRING,
  pii_access STRING,
  expires_on DATE
);

INSERT INTO abac_tutorial.mapping_demo.user_access VALUES
  (current_user(),      'us_east', 'engineering', 'masked', '2099-12-31'),
  ('bob@example.com',   'us_west', 'sales',       'full',   '2099-12-31'),
  ('carol@example.com', 'eu',      'engineering', 'none',   '2099-12-31'),
  ('david@example.com', 'apac',    'marketing',   'masked', '2099-12-31');

Paso 5: Crear el filtro de fila UDF

Esta UDF recibe los valores de sales_region y dept de una fila (pasados por la directiva a través de la coincidencia de etiquetas), busca el usuario actual en la tabla de correspondencia y devuelve TRUE siempre que exista una entrada coincidente y no haya expirado. Los usuarios que no están en la tabla de asignación o cuyo acceso ha expirado, no ven ninguna fila (diseño con error cerrado).

CREATE OR REPLACE FUNCTION abac_tutorial.mapping_demo.access_filter(
  region_val STRING,
  dept_val STRING
)
RETURNS BOOLEAN
RETURN EXISTS (
  SELECT 1 FROM abac_tutorial.mapping_demo.user_access
  WHERE user_email = current_user()
    AND region = region_val
    AND department = dept_val
    AND expires_on >= current_date()
);

Paso 6: Crear la UDF de máscara de columna

Esta UDF controla cómo se muestran las columnas PII. Toma tres argumentos: el valor de columna, el tipo PII ('name' o 'email') y la fila.order_priority La lógica de enmascaramiento tiene dos capas:

  • Capa 1 (enmascaramiento condicional): Si order_priority es confidential, el PII siempre se redacta completamente independientemente del nivel de autorización del usuario.
  • Nivel 2 (autorización del usuario): En el caso de las filas estándar, la UDF comprueba la tabla de asignación para el nivel del pii_access usuario y aplica la máscara correspondiente. Si un usuario tiene varias entradas en la tabla de mapeo (acceso a múltiples regiones), se aplica el mayor nivel de autorización entre todas las filas.
CREATE OR REPLACE FUNCTION abac_tutorial.mapping_demo.pii_mask(
  val STRING,
  pii_type STRING,
  order_pri STRING
)
RETURNS STRING
RETURN CASE
  WHEN order_pri = 'confidential' THEN '***REDACTED***'
  WHEN EXISTS (
    SELECT 1 FROM abac_tutorial.mapping_demo.user_access
    WHERE user_email = current_user() AND pii_access = 'full'
  ) THEN val
  WHEN EXISTS (
    SELECT 1 FROM abac_tutorial.mapping_demo.user_access
    WHERE user_email = current_user() AND pii_access = 'masked'
  ) THEN
    CASE pii_type
      WHEN 'email' THEN CONCAT(LEFT(val, 1), '***@', SUBSTRING_INDEX(val, '@', -1))
      WHEN 'name'  THEN CONCAT(LEFT(val, 1), '***')
      ELSE CONCAT(LEFT(val, 1), '***')
    END
  ELSE '***REDACTED***'
END;

Paso 7: Crear las directivas

Cree tres políticas, todas controladas por la misma tabla de asignación. Ambas directivas de máscara de columna usan la misma pii_mask función. El pii_type argumento indica a la función qué estilo de enmascaramiento se va a aplicar, por lo que no necesita una UDF independiente por tipo de columna.

La priority etiqueta gobernada se usa en MATCH COLUMNS para coincidir con la order_priority columna y pasar su valor a la máscara UDF como order_pri. Así es como se implementa el enmascaramiento condicional: la directiva pasa el valor de prioridad de la fila a la UDF en el momento de la consulta.

CREATE POLICY user_access_filter
ON SCHEMA abac_tutorial.mapping_demo
ROW FILTER abac_tutorial.mapping_demo.access_filter
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag('region') AS r, has_tag('department') AS d
USING COLUMNS (r, d);
CREATE POLICY pii_mask_name
ON SCHEMA abac_tutorial.mapping_demo
COLUMN MASK abac_tutorial.mapping_demo.pii_mask
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'name') AS m,
  has_tag('priority') AS pri
ON COLUMN m
USING COLUMNS ('name', pri);

CREATE POLICY pii_mask_email
ON SCHEMA abac_tutorial.mapping_demo
COLUMN MASK abac_tutorial.mapping_demo.pii_mask
TO `account users`
FOR TABLES
MATCH COLUMNS has_tag_value('pii', 'email') AS m,
  has_tag('priority') AS pri
ON COLUMN m
USING COLUMNS ('email', pri);

Paso 8: Comprobar los resultados

Tu entrada en la tabla de asignación te da acceso a us_east / engineering con autorización masked. Ejecute la consulta siguiente para comprobar que usted solo vea el pedido n.º 1, con la Información de Identificación Personal (PII) parcialmente enmascarada.

SELECT * FROM abac_tutorial.mapping_demo.orders;

El pedido n.º 1 tiene order_priority = 'standard', por lo tanto, su autorización masked se aplica.

Resultado esperado para el usuario:

identificador_de_pedido customer_name customer_email región_de_ventas departamento importe fecha_de_pedido prioridad_de_pedido
1 A*** o***@acme.com us_east ingeniería 50 000 2025-01-15 Estándar

Qué otros usuarios ven:

Usuario Pedidos visibles prioridad_de_pedido Comportamiento de la Información de Identificación Personal (PII)
bob@example.com (full despeje) #4 (us_west, ventas) confidencial ***REDACTED***: las anulaciones confidenciales prevalecen sobre la autorización full
carol@example.com (none espacio libre) #5 (eu, ingeniería) Estándar ***REDACTED***none la autorización significa una redacción completa.
david@example.com (masked holgura) #7 (APAC, marketing) confidencial ***REDACTED***: autorización de invalidaciones confidenciales masked
(propietario del catálogo) Todos los 10 Todos sin máscara (el propietario está exento de políticas)
(usuario sin incluir en la lista) Ninguno El filtro de fila no devuelve ninguna fila

Observe que bob tiene full autorización pero sigue viendo ***REDACTED*** porque la orden n.º 4 es confidential. Este es el enmascaramiento condicional: el valor de prioridad de la fila invalida la autorización del usuario.

Paso 9: Actualizar el acceso dinámicamente

La principal ventaja del enfoque de la tabla de mapeo es que puede cambiar los permisos de acceso actualizando las filas en la tabla. No es necesario actualizar las directivas, las UDF, ni las pertenencias a grupos.

Reasignar a otro departamento

Cambie el departamento de engineering a sales. Order #2 (Beta Inc) es un confidential pedido de venta, por lo que su PII está completamente anonimizada incluso con el masked permiso.

UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'sales'
WHERE user_email = current_user();

Ejecute la consulta siguiente para comprobarlo. Deberías ver la orden n.º 2 con ***REDACTED*** PII.

SELECT * FROM abac_tutorial.mapping_demo.orders;

Revertir el cambio:

UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'engineering'
WHERE user_email = current_user();

Actualización de la autorización de PII

Cambie el permiso de masked a full. En el caso de las filas de prioridad estándar, ahora ves los valores de PII reales.

UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'full'
WHERE user_email = current_user();

Ejecute la consulta siguiente para comprobarlo. Con la autorización full, el orden n.º 1 es standard prioritario, por lo que debería ver Acme Corp y orders@acme.com.

SELECT * FROM abac_tutorial.mapping_demo.orders;

Revertir el cambio:

UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'masked'
WHERE user_email = current_user();

Concesión de acceso a una región adicional

Inserte una segunda fila para conceder acceso a ingeniería de la UE. No se requieren nuevos grupos ni directivas.

INSERT INTO abac_tutorial.mapping_demo.user_access
VALUES (current_user(), 'eu', 'engineering', 'masked', '2099-12-31');

Ejecute la consulta siguiente para comprobarlo. Ahora debería ver tanto el pedido n.º 1 (us_east, ingeniería) como el pedido n.º 5 (eu, ingeniería), con PII parcialmente enmascarado.

SELECT * FROM abac_tutorial.mapping_demo.orders;

Quite el acceso adicional:

DELETE FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user() AND region = 'eu';

Expiración del acceso

Establezca la entrada de acceso en una fecha pasada. La UDF del filtro de fila comprueba expires_on >= current_date(), por lo que las entradas expiradas se omiten de forma silenciosa y el acceso se revoca automáticamente. Esto resulta útil para contratistas, contratos de uso compartido de datos con una duración fija o proyectos limitados por tiempo.

UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = current_date() - INTERVAL 1 DAY
WHERE user_email = current_user();

Ejecute la consulta siguiente para comprobar que no ve ninguna fila.

SELECT * FROM abac_tutorial.mapping_demo.orders;

Restaure el acceso con una fecha de expiración futura:

UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = '2099-12-31'
WHERE user_email = current_user();

Ejecute la consulta siguiente para comprobar que se restaura el acceso.

SELECT * FROM abac_tutorial.mapping_demo.orders;

Resumen

En este tutorial se muestran tres patrones:

  • Patrón de tabla de mapeo: una única tabla de consulta controla tanto el filtrado de filas como el enmascaramiento de columnas. Los cambios de acceso se realizan mediante la actualización de filas, sin necesidad de cambios de directiva ni de grupo.
  • Enmascaramiento condicional: la UDF de máscara comprueba la columna order_priority de cada fila para decidir cómo enmascarar PII. Las filas confidenciales siempre se eliminan por completo independientemente del nivel de autorización del usuario, implementadas mediante el marcado order_priority y su paso a la UDF a través de MATCH COLUMNS.
  • Expiración del acceso: la tabla de asignación incluye una expires_on fecha. El filtro de fila UDF comprueba esta fecha con current_date(), por lo que las entradas expiradas se omiten silenciosamente y el acceso se revoca automáticamente sin intervención manual.

Limpieza

Para quitar todos los objetos creados en este tutorial, ejecute lo siguiente.

DROP POLICY user_access_filter ON SCHEMA abac_tutorial.mapping_demo;
DROP POLICY pii_mask_name ON SCHEMA abac_tutorial.mapping_demo;
DROP POLICY pii_mask_email ON SCHEMA abac_tutorial.mapping_demo;
DROP FUNCTION IF EXISTS abac_tutorial.mapping_demo.access_filter;
DROP FUNCTION IF EXISTS abac_tutorial.mapping_demo.pii_mask;
DROP TABLE IF EXISTS abac_tutorial.mapping_demo.orders;
DROP TABLE IF EXISTS abac_tutorial.mapping_demo.user_access;
DROP SCHEMA IF EXISTS abac_tutorial.mapping_demo CASCADE;

Para quitar las etiquetas reguladas region, department, pii y priority, use la interfaz de usuario del Explorador de Catálogos.