Allgemeine Muster für Zeilenfilterung und Spaltenmaskierung

Auf dieser Seite werden allgemeine Muster für die Implementierung von ABAC-Zeilenfilter- und Spaltenformatrichtlinien beschrieben.

Cast-kompatible Maskierungsfunktionen

Azure Databricks wandelt die Ausgabe der Maskierungsfunktion automatisch in den Datentyp der Zielspalte um. Weitere Informationen finden Sie unter Automatische Typumwandlung für Spaltenmasken.

Die folgenden Muster helfen Ihnen beim Entwerfen von casting-kompatiblen Maskierungsfunktionen.

Zurückgeben eines umwandlungsfähigen Typs

Wenn Sie eine Spalte maskieren, verwenden Sie denselben Datentyp oder einen Typ, der in diesen Typ konvertiert werden kann. Überprüfen Sie die Datentypen der Spalten, auf die Ihre Richtlinienziele ausgerichtet sind, und überprüfen Sie, ob jede Verzweigung der Funktion einen kompatiblen Wert zurückgibt.

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

Vermeiden eines numerischen Überlaufs

Wenn eine Maskenfunktion einen breiteren numerischen Typ als die Zielspalte akzeptiert und zurückgibt, wird das Ergebnis automatisch in den Spaltentyp zurückgeworfen. Wenn der zurückgegebene Wert den Bereich des schmaleren Typs überschreitet, überläuft die Umwandlung und die Abfrage scheitert während der Laufzeit.

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

Verwenden von VARIANT für mehrere Spaltentypen

Siehe VARIANT-basierte Maskierungsfunktionen für mehrere Spaltentypen.

Testen der Cast-Kompatibilität

Testen Sie Maskierungsfunktionen mit unterschiedlichen Datenmustern.

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;

VARIANT-basierte Maskierungsfunktionen für mehrere Spaltentypen

Wenn Sie Spalten unterschiedlicher Datentypen (z.B. INT, DOUBLE, DECIMAL(10,2), DECIMAL(15,5) usw.) maskieren müssen, können Sie eine einzelne maskierende Funktion schreiben, die einen VARIANT Typ akzeptiert und zurückgibt. Azure Databricks konvertiert die Ausgabe der Spaltenmaskierungsfunktion automatisch, sodass sie mit dem Datentyp der Zielspalte übereinstimmt, gemäß den ANSI SQL-Standards.

Dieser Ansatz reduziert die Anzahl der UDFs und Richtlinien, die erforderlich sind. Anstatt separate Maskierungsfunktionen für jeden Spaltentyp zu schreiben, behandelt eine Funktion alle Typen.

Mehrere numerische Typen mit einer einzigen Funktion maskieren

Anstatt eine separate Maskenfunktion für jede numerische Genauigkeit zu erstellen, können Sie sie alle mit einer einzelnen Funktion behandeln: VARIANT

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

Diese Funktion gibt 0 als VARIANT zurück, wodurch Azure Databricks automatisch in den Typ der Zielspalte konvertiert. Eine einzelne ABAC-Richtlinie, die diese Funktion verwendet, kann die Spalten INT, DOUBLE und DECIMAL maskieren, ohne separate Funktionen für jede Präzision zu erfordern.

Wenn Sie den Typ explizit innerhalb der Funktion beibehalten möchten, können Sie den Typ abzweigen und für jeden einen geeigneten maskierten Wert mithilfe von schema_of_variant() zurückgeben.

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

Strukturspalten maskieren mit VARIANT

Für Databricks Runtime 18.1 und höher können Sie Strukturspalten auch maskieren, indem Sie sie in VARIANT innerhalb einer ABAC-Richtlinie konvertieren. Verzweigen Sie die Form der Struktur, um selektiv Felder zu redigieren:

Note

Umwandlung von Strukturen zu VARIANT für die Maskierung wird nur in ABAC-Spaltenmaskenrichtlinien unterstützt.

Im folgenden Beispiel wird schema_of_variant() verwendet, um zwei unterschiedliche Strukturschablonen zu identifizieren und vertrauliche Felder in jeder zu schwärzen.

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;

Verhindern des Zugriffs, bis vertrauliche Spalten markiert sind

Ein gängiges Governancemuster besteht darin, den Zugriff basierend darauf zu steuern, ob Daten klassifiziert wurden. Sie können dies mit einem standardmäßigen restriktiven Tag und Richtlinien implementieren, die je nach Klassifizierungsstatus unterschiedliche Schutzebenen erzwingen.

  1. Wenden Sie ein Tag wie classification : unverified standardmäßig auf alle neuen Objekte an, über automatisierungs- oder tagvererbung, indem Sie das Tag auf Katalog- oder Schemaebene anwenden, sodass alle neuen Tabellen, die dem Katalog oder Schema hinzugefügt werden, automatisch das Tag erben.
  2. Erstellen Sie eine Zeilenfilterrichtlinie, die den Zugriff auf markierte classification : unverifiedTabellen blockiert.
  3. Erstellen Sie eine Spaltenmaskierungsrichtlinie, die vertrauliche Spalten in Tabellen maskiert, in denen das classification : unverified Tag nicht mehr existiert.
  4. Wenn ein Data Steward die Klassifizierung abgeschlossen hat, aktualisiert der Data Steward das Etikett. Die Blockierungsrichtlinie stimmt nicht mehr überein, und die Maskierungsrichtlinie wird wirksam.
-- 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');

Um vertrauliche Daten nach der Einstufung zu schützen, definieren Sie eine Spaltenmaskierungsrichtlinie, die wirksam wird, wenn das classification : unverified Tag nicht mehr vorhanden ist.

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;

Partielle Anzeige ohne regex

Zeigen Sie einen Teil eines vertraulichen Werts mithilfe von Zeichenfolgenvorgängen anstelle von regex an. Regex-basierte Maskierung überprüft den gesamten Wert für jede Zeile, was für große Textfelder teuer ist (siehe Vermeiden der Regex-Maskierung für große Textfelder).

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

Konsistentes Hashing (deterministische Pseudonymisierung)

Durch konsistentes Hashing (auch als deterministische Pseudonymisierung bezeichnet) werden vertrauliche Daten durch einen Hashwert ersetzt, der in mehreren Tabellen identisch ist. Indem eine Funktion als DETERMINISTIC markiert wird, wird der Engine mitgeteilt, dass die Funktion bei derselben Eingabe immer dasselbe Ergebnis liefert, was hilft, die Abfrage zu optimieren. Siehe Verwenden von deterministischen, fehlersicheren Ausdrücken.

Die folgende Funktion erstellt konsistent einen Hash-Wert für eine Zeichenfolge und verwendet einen version Parameter, um die Schlüsselrotation zu unterstützen. Erhöhen Sie die version-Anzahl durch die Klausel der Richtlinie USING COLUMNS, um neue Hashes zu generieren, ohne historische Daten zu unterbrechen, die die vorherige Version verwendet haben. Die Funktion verkettet den ursprünglichen Wert mit der Versionsnummer vor dem Hashing, sodass dieselbe Eingabe mit derselben Version immer denselben Hash erzeugt.

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

Maskieren Sie eine Spalte basierend auf den Attributen des anfragenden Benutzers

Important

Die Identitätsattribute in ABAC-Richtlinien befinden sich in der Betaphase. Um sie zu verwenden, muss der Kontoadministrator die Vorschaufunktion Identitätsattribute in ABAC-Richtlinien auf der Seite Vorschauen der Kontokonsole aktivieren. Siehe Verwalten von Vorschauen auf Kontoebene.

Eine Spaltenmaskenrichtlinie kann die Identitätsattribute des abfragenden Benutzers verwenden, um sensible Daten zu maskieren, ohne dass dedizierte Gruppen erforderlich sind. Zum Beispiel kann es Daten für Benutzer mit department = HR unmaskiert lassen und sie für alle anderen maskieren.

Diese Muster erfordern Identitätsattribute, die Ihren Nutzern von Ihrem Identitätsanbieter bereitgestellt werden, und die Funktionen verhalten sich anders als Tag-only-Bedingungen in einer Weise, die beeinflussen, wie Sie die Policy schreiben. Bevor Sie sie verwenden, überprüfen Sie die Funktionen von Identitätsattributen und Identitätsattributen.

Important

Die Funktionen ergeben false, wenn für das Attribut beim Benutzer kein Wert festgelegt ist oder wenn der Attributschlüssel nicht existiert. Schreibe die Bedingung so, dass dieses false Ergebnis den Zugriff einschränkt statt gewährt. Die Übereinstimmung wird mit NOT negiert, sodass die Maske nur dann angewendet wird, wenn das Attribut übereinstimmt. Zum Beispiel blendet WHEN NOT has_identity_attribute_value('department', 'HR') die Spalte für alle Nutzer außer denen aus, deren Abteilung HR ist, und da ein fehlender Wert ebenfalls false ist, wird die Spalte auch für Benutzer ohne Abteilungsattribut ausgeblendet. Vermeiden Sie das Gegenteil: Eine Bedingung, die nur maskiert, wenn das Attribut übereinstimmt, sodass Benutzer, die keinen Wert für das Attribut haben, unmaskiert werden.

Für das Bewertungsverhalten siehe Identitätsattributbedingungen. Für Einschränkungen siehe Identitätsattribute in Richtlinienbedingungen.

Einen festen Wert abgleichen

Maskieren ssn für alle, deren Abteilung nicht HR ist:

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;

In diesem Beispiel sieht ein Nutzer, dessen Abteilung HR ist, echte Werte. Ein Nutzer in einer anderen Abteilung und ein Nutzer ohne Abteilungsattribut sehen beide die Maske.

Übereinstimmung gegen einen regulierten Tag

Das vorherige Beispiel nennt einen bestimmten Attributwert (HR) in der Richtlinie, sodass mehrere Abteilungen zu decken bedeuten würden, für jede eine eigene Richtlinie zu schreiben. Um alle Abteilungen mit einer einzigen Richtlinie abzudecken, taggen Sie jede Tabelle mit der Abteilung, die sie besitzt, und vergleichen Sie dann das department Attribut des absuchenden Benutzers mit diesem Tag. Die Spalte wird nur angezeigt, wenn die Abteilung des Benutzers mit dem dept_tag Wert der Tabelle übereinstimmt:

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;

Bei Attributschlüsseln und -werten wird zwischen Groß- und Kleinschreibung unterschieden, und Werte werden exakt verglichen: Finance und finance stimmen nicht überein.

Beschränken Sie den Zugriff für externe Agenten, die im Namen eines Benutzers handeln

Important

Kontextattribute in ABAC-Richtlinien befinden sich in der Beta-Phase. Um sie zu verwenden, muss ein Kontoadministrator die Vorabversion UC ABAC Context Attributes auf der Seite Previews der Kontokonsole aktivieren. Siehe Verwalten von Vorschauen auf Kontoebene.

Kontextattribute können verwendet werden, um den Datenzugriff für Anfragen im Namen eines Benutzers über eine OAuth-Anwendung einzuschränken. Wenn Agenten über OAuth verbunden sind, kann diese Konfiguration genutzt werden, um zu verhindern, dass sie auf Daten zugreifen, wenn sie im Namen eines Benutzers handeln, obwohl der Benutzer die Daten auch beim direkten Abfragen im Arbeitsbereich lesen kann.

Jeder OAuth-authentifizierte Zugriff über die Azure Databricks CLI, die SDKs oder die SQL Statement Execution API setzt request.is_on_behalf_of auf 'true', selbst wenn ein Benutzer manuell eine Abfrage stellt. Zugang, der mit einem persönlichen Zugangstoken (PAT) authentifiziert wird, tut dies nicht. Genie-Zugriff kann über diesen Mechanismus nicht erfasst werden, da dabei 'true' nicht auf request.is_on_behalf_of gesetzt wird.

Diese Muster verwenden die Kontextattributfunktionen. Für verfügbare Attribute und Verhalten siehe Kontextattributfunktionen (Beta).

Richte einen Agenten ein, der Kontextattribute sendet.

Um Kontextattribute zu verwenden, verbinde den Agent mit Azure Databricks über eine benutzerdefinierte OAuth-Anwendung:

  1. Ein Kontoadministrator aktiviert die UC ABAC Context Attributes Vorschau in der Kontokonsole. Siehe Manage Azure Databricks Previews.
  2. Ein Kontoadministrator registriert eine benutzerdefinierte OAuth-Anwendung in der Kontokonsole und notiert deren Client-ID. Weitere Informationen unter Aktivieren oder Deaktivieren von OAuth-Partneranwendungen.
  3. Verbinden Sie den Agenten über diese OAuth-Anwendung mit dem von Azure Databricks verwalteten MCP. Siehe Clients mithilfe der OAuth-Authentifizierung verbinden.

Ein Agent, der den eingebauten databricks-cli-Client verwendet, authentifiziert sich weiterhin über OAuth, sodass 'true'request.is_on_behalf_of liest. Allerdings kann man seine Anfragen nicht von der manuellen Nutzung der CLI unterscheiden, da beide die databricks-cli Client-ID teilen. Um eine bestimmte Anwendung zu steuern, registrieren Sie eine benutzerdefinierte OAuth-Anwendung und verbinden Sie den Agenten darüber.

Für OAuth-Konzepte siehe Authorize user access to Azure Databricks with OAuth.

Warning

Stellen Sie sicher, dass ein Agent die Daten nicht über einen Weg erreichen kann, den Ihre Police nicht abdeckt:

  • Wenn Sie den Zugriff aufgrund von request.is_on_behalf_ofeinschränken, stellen Sie sicher, dass der Agent sich nicht mit einem PAT authentifizieren kann. Ein PAT setzt request.is_on_behalf_of nicht auf 'true', sodass eine Bedingung auf diesem Attribut es nicht einschränkt.
  • Wenn du den Zugriff anhand von request.client_id beschränkst, stelle sicher, dass der Agent sich nicht über einen Client verbinden kann, den deine Bedingung nicht abdeckt, wie z. B. den generischen databricks-cli-Client.

Maskieren Sie eine Spalte für Anforderungen im Auftrag von

ssn für Anfragen maskieren, die im Namen eines Benutzers ausgeführt werden, z. B. wenn ein Agent über eine registrierte OAuth-Anwendung agiert, und es bei direkten Abfragen unmaskiert lassen:

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;

In diesem Beispiel liefert eine direkte Abfrage echte Werte zurück, und eine Anforderung im Namen eines Benutzers liefert die maskierten Werte. Mit der CLI und der SQL Statement Execution API liest request.is_on_behalf_of auch 'true', sodass diese Richtlinie die Spalte auch für diese Anfragen maskiert. Um stattdessen eine bestimmte Anwendung anzusprechen, vergleiche request.client_id sie mit der Client-ID dieser Anwendung.

Beschränken Sie eine Spalte auf eine genehmigte Anwendung

Maske ssn für jede externe Anfrage außer denen aus deiner genehmigten Anwendung, die durch die OAuth-Client-ID identifiziert wird:

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;

Um zu sehen, welche Anwendung eine Anfrage gestellt hat, überprüfen Sie das identity_metadata.acting_resource Feld in den Auditprotokollen.

Zeilenfilterung mit Nur-Spalten-Prädikaten

Filtern Sie Zeilen mithilfe einfacher boolescher Logik, die nur auf Tabellenspalten verweist. Nur Spaltenprädikate ermöglichen Prädikat-Pushdown, wodurch die Engine irrelevante Daten während Scans überspringen kann (siehe Grundlegendes zum Prädikat-Pushdown in geschützten Tabellen).

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

Wird mit einer Richtlinie verwendet, die die zulässigen Regionen als Konstante übergibt:

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

Zeilenfilterung über mehrere verwandte Spalten

Wenn eine Tabelle mehrere Spalten hat, die verwandte Attribute darstellen (z. B. ship_to_country und bill_to_country), können Sie diese mit separaten Tag-Bedingungen abgleichen und beide an eine einzelne UDF übergeben. Dadurch wird verhindert, dass für jede Spalte separate Richtlinien erstellt werden. Eine Richtlinie kann bis zu drei Spaltenausdrücke in der MATCH COLUMNS Klausel enthalten (siehe Richtlinienkontingente).

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

Ein Analyst sieht nur Bestellungen, bei denen sich entweder das Versand- oder Abrechnungsland in ihrer zulässigen Liste befindet.

Tabellenabfrage in ABAC-Richtlinien-UDFs

Wenn Zugriffsregeln je Benutzer variieren und nicht allein über die Klauseln der Richtlinie TO/EXCEPT ausgedrückt werden können, können Sie die Zugriffsrechte gegen eine kleine Nachschlagetabelle abgleichen. Verwenden Sie TO/EXCEPT nach Möglichkeit, da es sich um den bevorzugten Ansatz für Zielprinzipale handelt (siehe Ansatz für Zielprinzipale). Halten Sie die Lookup-Tabellen klein, damit der Optimierer die Unterabfrage in eine Broadcast-Hashverknüpfung konvertiert (siehe Lookup-Tabellen klein halten).

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