Utilisez les tables de mappage pour le contrôle d'accès dynamique.
Ce tutoriel montre comment utiliser une table de mappage pour contrôler l'accès au niveau des lignes et des colonnes sans gérer un grand nombre de groupes. Une seule table de correspondance gère le filtrage des lignes et le masquage des colonnes. Les modifications d'accès ne nécessitent qu'une mise à jour de ligne. Vous n'avez pas besoin de créer de nouveaux groupes ou de réécrire des politiques.
Ce didacticiel démontre également le masquage conditionnel : les colonnes PII sont masquées différemment selon la valeur d’une autre colonne sur la même ligne. Les commandes marquées confidential voient leurs PII entièrement expurgées, quel que soit le niveau d'habilitation de l'utilisateur.
Pour des conseils généraux sur la conception des tables de mappage, voir Utiliser des tables de mappage pour créer une liste de contrôle d'accès.
Prérequis
- Databricks Runtime 16.4 ou version supérieure, ou compute serverless.
- Autorisations d'administrateur de compte ou d'administrateur de Workspace (pour créer des tags gouvernés).
MANAGEautorisation sur le catalogue ou le schéma cible.EXECUTEsur les UDF.- Un Notebook SQL ou un éditeur de query.
Scénario
Votre organisation compte des employés dans quatre régions (US East, US West, EU, APAC) et quatre services. Chaque utilisateur ne devrait voir que les lignes qui correspondent à sa région et à son service, et les colonnes PII devraient être masquées selon deux facteurs : le niveau d'habilitation de l'utilisateur (full, masked ou none) stocké dans une table de correspondance, et le order_priority de la commande.
Avec une approche basée sur les groupes, vous avez besoin d'un groupe pour chaque combinaison région-département. Par exemple, vous avez besoin de 16 groupes pour quatre régions et quatre départements. L'ajout de niveaux d'autorisation PII triple ce nombre. Chaque nouvelle région ou nouveau département nécessite de nouveaux groupes et des mises à jour de la politique.
L'approche de la table de mappage la remplace par une table de recherche unique : une ligne par utilisateur, une colonne par dimension d'accès. Pour modifier l'accès d'un utilisateur, vous mettez à jour une ligne.
Étape 1 : Créer des balises gouvernées.
Avant d'exécuter n'importe quel SQL, créez les tags gouvernés suivants dans l'interface utilisateur de Catalog Explorer (**Catalogue** > **Gouverner** > **Tags gouvernés** > **Créer un tag gouverné **):
Clé de tag | Valeurs autorisées |
|---|---|
| (balise à clé uniquement) |
| (balise à clé uniquement) |
|
|
| (balise à clé uniquement) |
Les balises region et department indiquent à la politique de filtrage des lignes quelles colonnes transmettre à la UDF de filtrage. La balise pii indique aux politiques de masquage de colonne quelles colonnes masquer et quel type de PII elles contiennent. La balise priority permet aux politiques de masquage de colonne de transmettre la valeur order_priority à la UDF de masquage pour un masquage conditionnel.
Les données des tags sont stockées en texte brut et peuvent être répliquées à l’échelle mondiale. N’utilisez pas de noms de tags, de valeurs ou de descripteurs qui pourraient compromettre la sécurité de vos ressources. Par exemple, n’utilisez pas de noms de tags, de valeurs ou de descripteurs contenant des informations personnelles ou sensibles.
Étape 2 : Créez des exemples de données.
Créez un catalogue, un schéma et une table de commandes. La colonne order_priority pilote le masquage conditionnel : les commandes marquées confidential ont leurs PII entièrement expurgées, même pour les utilisateurs avec une autorisation élevée.
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');
Étape 3 : Appliquer des tags gouvernés
Étiquetez les colonnes afin que les politiques ABAC puissent les découvrir automatiquement. La colonne order_priority est étiquetée avec le tag priority (clé uniquement) afin que les politiques de masquage de colonne puissent le faire correspondre via MATCH COLUMNS et transmettre sa valeur à l'UDF de masque.
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' = '');
Étape 4 : Créez la table de mappage
Au lieu de créer des groupes pour chaque combinaison de région, de département et d'habilitation, vous maintenez une table avec une ligne par utilisateur. La colonne pii_access contrôle la façon dont les colonnes PII apparaissent :
full— voir la valeur réelle (pour les commandes de priorité standard)masked— voir une valeur partielle telle queA***ouo***@acme.comnone— voir***REDACTED***
La colonne expires_on définit une date d'expiration pour chaque entrée d'accès. Après cette date, l'UDF de filtre de ligne cesse de correspondre à l'entrée et l'utilisateur perd silencieusement l'accès sans qu'une révocation manuelle ne soit nécessaire. Ceci est utile pour les contractuels, les accords de Data Sharing temporaires ou les projets à durée limitée.
Si un utilisateur doit accéder à plusieurs combinaisons de régions et de départements, ajoutez des lignes supplémentaires.
Gardez les tables de mappage petites et simples. Chaque query exécutée sur une table protégée exécute les UDF de filtre de ligne et de masque de colonne, qui, à leur tour, interrogent la table de mappage. De grandes tables de mappage et une logique UDF complexe peuvent avoir un impact sur les performances des requêtes. Utilisez des schémas étroits et limitez la logique UDF à une seule recherche lorsque cela est possible.
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');
Étape 5 : créer l’UDF de filtre de lignes
Cette UDF reçoit les valeurs sales_region et dept d'une ligne (transmises par la politique via la correspondance des balises), recherche l'utilisateur actuel dans la table de mappage, et renvoie TRUE uniquement si une entrée correspondante existe et n'a pas expiré. Les utilisateurs qui ne figurent pas dans la table de mappage, ou dont l’accès a expiré, ne voient aucune ligne (conception fail-closed).
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()
);
Étape 6 : Créez l'UDF de masque de colonne
Cette UDF contrôle la façon dont les colonnes PII sont affichées. Il prend trois arguments : la valeur de la colonne, le type de PII ('name' ou 'email') et le order_priority de la ligne. La logique de masquage comporte deux couches :
- Couche 1 (masquage conditionnel) : Si
order_priorityestconfidential, les PII sont toujours entièrement expurgées, quel que soit le niveau d'habilitation de l'utilisateur. - Couche 2 (habilitation de l'utilisateur) : Pour les lignes standard, l'UDF vérifie la table de mappage pour le niveau
pii_accessde l'utilisateur et applique le masque correspondant. Si un utilisateur a plusieurs entrées dans la table de correspondance (accès multirégion), l'habilitation la plus élevée parmi toutes les lignes s'applique.
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;
Étape 7 : créez les politiques
Créez trois stratégies, toutes pilotées par la même table de mappage. Les deux politiques de masquage de colonne utilisent la même fonction pii_mask. L'argument pii_type indique à la fonction le style de masquage à appliquer, vous n'avez donc pas besoin d'une UDF distincte par type de colonne.
Le tag gouverné priority est utilisé dans MATCH COLUMNS pour correspondre à la colonne order_priority et transmettre sa valeur à l’UDF de masque en tant que order_pri. Voici comment le masquage conditionnel est implémenté : la politique transmet la valeur de priorité de la ligne à l’UDF au moment de la query.
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);
Étape 8 : Vérifier les résultats
Votre entrée de table de correspondance vous donne accès à us_east / engineering avec un niveau d'autorisation masked. Exécutez la query suivante pour vérifier que vous ne voyez que la commande n°1, avec des informations personnelles partiellement masquées.
SELECT * FROM abac_tutorial.mapping_demo.orders;
La commande n° 1 a order_priority = 'standard', de sorte que votre autorisation masked s'applique.
Résultat attendu pour votre utilisateur :
order_id | customer_name | customer_email | région de vente | département | Montant | order_date | order_priority |
|---|---|---|---|---|---|---|---|
1 |
|
| us_east | Data Engineering | 50 000 | 15.01.2025 | Standard |
Ce que voient les autres utilisateurs :
Utilisateur | Ordres visibles | order_priority | Comportement des PII |
|---|---|---|---|
bob@example.com ( | N° 4 (us_west, Ventes) | Confidentiel |
|
carol@example.com ( | #5 (EU, engineering) | Standard |
|
david@example.com ( | #7 (apac, marketing) | Confidentiel |
|
(propriétaire du catalogue) | Tous les 10 | — | Tout démasqué (le propriétaire est exempté des politiques) |
(utilisateur non répertorié) | Aucun | — | Le filtre de ligne ne renvoie aucune ligne. |
Notez que Bob a full d'habilitation mais voit toujours ***REDACTED*** parce que la commande nº 4 est confidential. C'est un masquage conditionnel : la valeur de priorité de la ligne remplace l'habilitation de l'utilisateur.
Étape 9 : Mettre à jour l’accès dynamiquement
Le principal avantage de l'approche de la table de mappage est que vous pouvez modifier l'accès en mettant à jour les lignes de la table. Vous n'avez pas besoin de mettre à jour les stratégies, les UDF ou les adhésions à des groupes.
Réassigner à un autre service
Modifier votre service de engineering à sales. La commande n° 2 (Beta Inc) est une commande de vente confidential, de sorte que ses PII sont entièrement masquées même avec une autorisation masked.
UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'sales'
WHERE user_email = current_user();
Exécutez la query suivante pour vérifier. Vous devriez voir la commande n°2 avec ***REDACTED*** PII.
SELECT * FROM abac_tutorial.mapping_demo.orders;
Annulez la modification :
UPDATE abac_tutorial.mapping_demo.user_access
SET department = 'engineering'
WHERE user_email = current_user();
Mettre à niveau le niveau de classification PII
Modifiez votre habilitation de masked à full. Pour les lignes à priorité standard, vous voyez désormais les valeurs PII réelles.
UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'full'
WHERE user_email = current_user();
Exécutez la query suivante pour vérifier. La Commande n° 1 est de priorité standard, donc avec une autorisation full, vous devriez voir Acme Corp et orders@acme.com.
SELECT * FROM abac_tutorial.mapping_demo.orders;
Annulez la modification :
UPDATE abac_tutorial.mapping_demo.user_access
SET pii_access = 'masked'
WHERE user_email = current_user();
Accorder l'accès à une région supplémentaire
Insérer une deuxième ligne pour accorder l'accès à la Data Engineering de l'UE. Aucun nouveau groupe ou politique n'est requis.
INSERT INTO abac_tutorial.mapping_demo.user_access
VALUES (current_user(), 'eu', 'engineering', 'masked', '2099-12-31');
Exécutez la query suivante pour vérifier. Vous devriez maintenant voir les commandes n°1 (us_east, ingénierie des données) et n°5 (eu, ingénierie des données), avec des informations personnelles partiellement masquées.
SELECT * FROM abac_tutorial.mapping_demo.orders;
Supprimer l'accès supplémentaire :
DELETE FROM abac_tutorial.mapping_demo.user_access
WHERE user_email = current_user() AND region = 'eu';
Faire expirer l'accès
Définissez votre entrée d'accès à une date antérieure. L'UDF de filtre de ligne vérifie expires_on >= current_date(), de sorte que les entrées expirées sont ignorées et l'accès est automatiquement révoqué. Ceci est utile pour les sous-traitants, les accords de Data Sharing à durée déterminée ou les projets à durée limitée.
UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = current_date() - INTERVAL 1 DAY
WHERE user_email = current_user();
Exécutez la query suivante pour vérifier que vous ne voyez aucune ligne.
SELECT * FROM abac_tutorial.mapping_demo.orders;
Rétablissez l'accès avec une date d'expiration future :
UPDATE abac_tutorial.mapping_demo.user_access
SET expires_on = '2099-12-31'
WHERE user_email = current_user();
Exécutez la requête suivante pour vérifier que l'accès est restauré.
SELECT * FROM abac_tutorial.mapping_demo.orders;
Résumé
Ce didacticiel a démontré trois modèles :
- Modèle de table de mappage : une seule table de recherche contrôle à la fois le filtrage des lignes et le masquage des colonnes. Les modifications d'accès sont effectuées en mettant à jour les lignes, sans qu'aucune modification de politique ou de groupe ne soit nécessaire.
- Masquage conditionnel : la UDF de masque vérifie la colonne
order_prioritysur chaque ligne pour décider comment masquer les PII. Les lignes confidentielles sont toujours entièrement expurgées, quel que soit le niveau d'habilitation de l'utilisateur, et ce, en taguantorder_priorityet en le transmettant à la UDF viaMATCH COLUMNS. - Expiration de l'accès : la table de mappage inclut une date
expires_on. L'UDF de filtre de ligne vérifie cette date par rapport àcurrent_date(), ainsi les entrées expirées sont ignorées silencieusement et l'accès est automatiquement révoqué sans intervention manuelle.
Nettoyer
Pour supprimer tous les objets créés dans ce tutoriel, exécutez ce qui suit.
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;
Pour supprimer les tags gouvernés region, department, pii et priority, utilisez l'interface utilisateur de l'Explorateur de catalogues.