Pola umum untuk pemfilteran baris dan masking kolom

Halaman ini menjelaskan pola umum untuk menerapkan filter baris ABAC dan kebijakan masker kolom.

Fungsi pemaskaan yang kompatibel dengan cast

Azure Databricks secara otomatis mentransmisikan output fungsi masking agar sesuai dengan jenis data kolom target. Lihat Perubahan tipe otomatis untuk masker kolom.

Pola-pola berikut membantu Anda merancang fungsi masking yang kompatibel dengan casting.

Mengembalikan jenis yang dapat dikonversi

Saat menyembunyikan kolom, kembalikan jenis data yang sama atau jenis yang dapat diubah menjadi kolom tersebut. Periksa jenis data kolom yang ditargetkan kebijakan Anda dan verifikasi bahwa setiap cabang fungsi mengembalikan nilai yang kompatibel.

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

Hindari luapan numerik

Saat fungsi mask menerima dan mengembalikan jenis numerik yang lebih luas daripada kolom target, hasilnya secara otomatis ditransmisikan kembali ke jenis kolom. Jika nilai yang dikembalikan melebihi rentang jenis yang lebih sempit, transmisi meluap dan kueri gagal pada 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;

Menggunakan VARIAN untuk beberapa jenis kolom

Lihat Fungsi masking berbasis VARIANT untuk beberapa jenis kolom.

Menguji kompatibilitas pemeran

Uji fungsi masking dengan pola data yang berbeda.

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;

Fungsi masking berbasis VARIANT untuk beberapa jenis kolom

Ketika Anda perlu menutupi kolom dari berbagai jenis data (misalnya, INT, DOUBLE, DECIMAL(10,2), DECIMAL(15,5), dan sebagainya), Anda dapat menulis satu UDF masking yang menerima dan mengembalikan tipe VARIANT. Azure Databricks secara otomatis mengonversi output fungsi masker kolom agar sesuai dengan jenis data kolom target mengikuti standar ANSI SQL.

Pendekatan ini mengurangi jumlah UDF dan kebijakan yang diperlukan. Alih-alih menulis fungsi masking terpisah untuk setiap jenis kolom, satu fungsi menangani semua jenis.

Menutupi beberapa jenis numerik dengan satu fungsi

Daripada membuat fungsi masker terpisah untuk setiap presisi numerik, Anda dapat menggunakan VARIANT untuk menangani semuanya dengan satu fungsi:

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

Fungsi ini mengembalikan 0 sebagai VARIANT, yang secara otomatis diubah oleh Azure Databricks ke tipe kolom target. Satu kebijakan ABAC yang menggunakan fungsi ini dapat menyembunyikan kolom INT, DOUBLE, dan DECIMAL tanpa memerlukan fungsi terpisah untuk setiap tingkat ketelitian.

Jika Anda lebih suka mempertahankan jenis secara eksplisit dalam fungsi, Anda dapat bercabang pada jenis dan mengembalikan nilai masked yang sesuai untuk masing-masing menggunakan 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;

Menutupi kolom struct dengan VARIAN

Untuk Databricks Runtime 18.1 dan versi yang lebih baru, Anda juga dapat menyamarkan kolom struct dengan mengubah tipe datanya menjadi VARIANT dalam kebijakan ABAC. Cabang pada bentuk struktur untuk meredaksi bidang secara selektif:

Note

Konversi struct ke VARIANT untuk masking hanya didukung dalam kebijakan masker kolom ABAC.

Contoh berikut menggunakan schema_of_variant() untuk mengidentifikasi dua bentuk struktur yang berbeda dan meredaksi bidang sensitif di masing-masing:

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;

Mencegah akses hingga kolom sensitif ditandai

Pola tata kelola umum adalah mengontrol akses berdasarkan apakah data telah diklasifikasikan. Anda dapat menerapkan ini dengan tag dan kebijakan pembatasan default yang memberlakukan tingkat perlindungan yang berbeda tergantung pada status klasifikasi.

  1. Terapkan tag seperti classification : unverified ke semua objek baru secara default, melalui otomatisasi atau melalui pewarisan tag dengan menerapkan tag di tingkat katalog atau skema, sehingga setiap tabel baru yang ditambahkan ke katalog atau skema secara otomatis mewarisi tag.
  2. Buat kebijakan filter baris yang memblokir akses ke tabel yang ditandai classification : unverified.
  3. Buat kebijakan masker kolom yang menutupi kolom sensitif pada tabel tempat classification : unverified tag tidak ada lagi.
  4. Saat pengurus data menyelesaikan klasifikasi, mereka memperbarui tag. Kebijakan pemblokiran tidak lagi cocok, dan kebijakan masking berlaku.
-- 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');

Untuk melindungi data sensitif setelah diklasifikasikan, tentukan kebijakan masker kolom yang berlaku ketika classification : unverified tag tidak ada lagi:

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;

Pengungkapan parsial tanpa regex

Ungkapkan bagian dari nilai sensitif menggunakan operasi string alih-alih regex. Masking berbasis regex memindai seluruh nilai untuk setiap baris, yang mahal pada bidang teks besar (lihat Menghindari masking regex pada bidang teks besar).

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

Hashing konsisten (pseudonimisasi deterministik)

Hashing yang konsisten (juga disebut pseudonymization deterministik) menggantikan data sensitif dengan nilai hash yang sama di beberapa tabel. Menandai fungsi sebagai DETERMINISTIC memberi tahu mesin bahwa fungsi selalu mengembalikan hasil yang sama untuk input yang sama, yang membantu mengoptimalkan kueri. Lihat Menggunakan ekspresi deterministik dan aman kesalahan.

Fungsi berikut secara konsisten melakukan hash nilai string, dengan menggunakan parameter version untuk mendukung pergantian kunci. Tingkatkan version angka melalui klausul kebijakan USING COLUMNS untuk menghasilkan hash baru tanpa merusak data historis yang menggunakan versi sebelumnya. Fungsi ini menggabungkan nilai asli dengan nomor versi sebelum hashing, sehingga input yang sama dengan versi yang sama selalu menghasilkan hash yang sama.

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

Masker kolom berdasarkan atribut pengguna yang melakukan kueri

Important

Atribut identitas dalam kebijakan ABAC berada dalam tahap Beta. Untuk menggunakannya, admin akun harus mengaktifkan pratinjau Atribut Identitas dalam ABAC Policies dari halaman Pratinjau konsol akun. Lihat Mengelola pratinjau tingkat akun.

Kebijakan column mask dapat menggunakan atribut identitas pengguna yang melakukan query untuk menyembunyikan data sensitif tanpa memerlukan grup khusus. Misalnya, data dapat tetap tersembunyi untuk pengguna dan department = HR menutupinya untuk semua orang lain.

Pola-pola ini memerlukan atribut identitas yang disediakan kepada pengguna Anda dari penyedia identitas Anda, dan fungsi-fungsi tersebut berperilaku berbeda dari kondisi tag-only dengan cara yang memengaruhi cara Anda menulis kebijakan. Sebelum Anda menggunakannya, tinjau fungsi atribut Identity dan atribut identitas.

Important

Fungsi-fungsi tersebut akan menghasilkan false ketika pengguna tidak memiliki nilai untuk atribut tersebut atau ketika kunci atribut tersebut tidak ada. Tulis kondisi sedemikian rupa sehingga hasil ini false membatasi akses, bukan memberikannya. Negate match dengan NOT sehingga masker berlaku kecuali atribut tersebut cocok. Misalnya, WHEN NOT has_identity_attribute_value('department', 'HR') menyamarkan kolom untuk semua orang kecuali pengguna yang atribut departemennya bernilai HR, dan karena nilai yang tidak ada juga false, pengguna tanpa atribut departemen juga disamarkan. Hindari kebalikannya: kondisi yang hanya menyamarkan saat atribut cocok akan membiarkan pengguna yang tidak memiliki nilai untuk atribut tersebut tetap tidak disamarkan.

Untuk perilaku evaluasi, lihat Kondisi atribut identitas. Untuk keterbatasan, lihat Atribut identitas dalam kondisi kebijakan.

Cocokkan nilai tetap

Sembunyikan ssn untuk semua orang yang departemennya bukan 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;

Dalam contoh ini, pengguna yang departemennya adalah HR melihat nilai nyata. Pengguna di departemen lain, dan pengguna tanpa atribut departemen, keduanya melihat masker.

Cocokkan dengan tag yang dikelola

Contoh sebelumnya menyebutkan nilai atribut spesifik (HR) dalam kebijakan, jadi mencakup beberapa departemen berarti menulis kebijakan terpisah untuk masing-masing. Untuk mencakup semua departemen dengan satu kebijakan, tandai setiap tabel dengan departemen yang memilikinya, lalu bandingkan atribut pengguna department yang melakukan query dengan tag tersebut. Kolom hanya akan ditampilkan ketika departemen pengguna sesuai dengan nilai tabel dept_tag :

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;

Kunci dan nilai atribut sama-sama peka terhadap huruf besar/kecil, dan nilainya dibandingkan secara persis: Finance dan finance tidak cocok.

Batasi akses untuk agen eksternal yang bertindak atas nama pengguna

Important

Atribut konteks dalam kebijakan ABAC berada dalam tahap Beta. Untuk menggunakannya, admin akun harus mengaktifkan pratinjau Atribut Konteks UC ABAC dari halaman Pratinjau konsol akun. Lihat Mengelola pratinjau tingkat akun.

Atribut konteks dapat digunakan untuk membatasi akses data atas permintaan yang dibuat atas nama pengguna melalui aplikasi OAuth. Jika agen terhubung melalui OAuth, pengaturan ini dapat digunakan untuk mencegah mereka mengakses data saat bertindak atas nama pengguna, meskipun pengguna masih dapat membaca data saat mereka melakukan query langsung di workspace.

Setiap akses yang diautentikasi OAuth melalui Azure Databricks CLI, SDK, atau SQL Statement Execution API menetapkan request.is_on_behalf_of ke 'true', bahkan saat pengguna menjalankan kueri secara manual. Akses yang diautentikasi dengan token akses pribadi (PAT) tidak. Akses Genie tidak dapat dicatat melalui mekanisme ini karena mekanisme ini tidak menyetel request.is_on_behalf_of ke 'true'.

Pola-pola ini menggunakan fungsi atribut konteks. Untuk atribut dan perilaku yang tersedia, lihat Fungsi atribut Konteks (Beta).

Siapkan agen untuk mengirim atribut konteks

Untuk menggunakan atribut konteks, hubungkan agen ke Azure Databricks menggunakan aplikasi OAuth khusus:

  1. admin akun mengaktifkan fitur pratinjau UC ABAC Context Attributes melalui konsol akun. Lihat Kelola Pratinjau Azure Databricks.
  2. Seorang admin akun mendaftarkan aplikasi OAuth khusus di konsol akun dan mencatat ID kliennya. Lihat Mengaktifkan atau menonaktifkan aplikasi OAuth mitra itu.
  3. Hubungkan agen ke MCP yang dikelola Azure Databricks melalui aplikasi OAuth tersebut. Lihat Hubungkan klien menggunakan otentikasi OAuth.

Agen yang menggunakan klien bawaan databricks-cli tetap mengautentikasi melalui OAuth, jadi request.is_on_behalf_of membaca 'true'. Namun, Anda tidak bisa membedakan permintaannya dari penggunaan manual CLI, karena keduanya berbagi databricks-cli ID klien. Untuk mengatur aplikasi tertentu, daftarkan aplikasi OAuth khusus dan hubungkan agen melalui aplikasi tersebut.

Untuk konsep OAuth, lihat Otorisasi akses pengguna ke Azure Databricks dengan OAuth.

Warning

Pastikan agen tidak dapat mengakses data melalui jalur yang tidak dicakup oleh kebijakan Anda:

  • Jika Anda membatasi akses berdasarkan request.is_on_behalf_of, pastikan agen tidak dapat mengautentikasi dengan PAT. PAT tidak menetapkan request.is_on_behalf_of ke 'true', sehingga syarat pada atribut tersebut tidak membatasinya.
  • Jika Anda membatasi akses berdasarkan request.client_id, pastikan agen tidak dapat terhubung melalui klien yang tidak tercakup oleh kondisi Anda, seperti klien generik databricks-cli .

Masking kolom untuk permintaan atas nama

Samarkan ssn untuk permintaan yang berjalan atas nama pengguna, seperti agen yang bertindak melalui aplikasi OAuth terdaftar, sambil membiarkannya tidak disamarkan untuk kueri langsung:

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;

Dalam contoh ini, kueri langsung mengembalikan nilai asli, dan permintaan atas nama pihak lain akan melihat nilai yang disamarkan. Dengan menggunakan CLI dan SQL Statement Execution API, request.is_on_behalf_of juga membaca 'true', sehingga kebijakan ini juga menyamarkan kolom untuk permintaan tersebut. Untuk menargetkan aplikasi tertentu, cocokkan request.client_id dengan ID klien aplikasi tersebut.

Batasi kolom hanya untuk aplikasi yang disetujui

Masker ssn untuk setiap permintaan eksternal kecuali yang berasal dari aplikasi yang Anda setujui, yang diidentifikasi dengan OAuth client ID-nya:

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;

Untuk melihat aplikasi mana yang membuat permintaan, periksa identity_metadata.acting_resource kolom di log audit.

Pemfilteran baris dengan predikat yang hanya berlaku pada kolom

Filter baris menggunakan logika boolean sederhana yang hanya mereferensikan kolom tabel. Predikat khusus kolom memungkinkan pushdown predikat, yang memungkinkan mesin melewati data yang tidak relevan selama pemindaian (lihat Memahami pushdown predikat pada tabel yang dilindungi).

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

Gunakan kebijakan yang menetapkan wilayah yang diizinkan sebagai konstanta:

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

Pemfilteran baris di beberapa kolom terkait

Saat tabel memiliki beberapa kolom yang mewakili atribut terkait (misalnya, ship_to_country dan bill_to_country), Anda dapat mencocokkannya dengan kondisi tag terpisah dan meneruskan keduanya ke satu UDF. Ini menghindari pembuatan kebijakan terpisah untuk setiap kolom. Kebijakan dapat menyertakan hingga tiga ekspresi kolom dalam MATCH COLUMNS klausa (lihat Kuota kebijakan).

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

Analis hanya melihat pesanan di mana negara pengiriman atau penagihan berada dalam daftar yang diizinkan.

Tabel pencarian dalam UDF kebijakan ABAC

Ketika aturan akses bervariasi per pengguna dan tidak dapat diekspresikan melalui klausul kebijakan TO/EXCEPT saja, Anda dapat memeriksa hak akses terhadap tabel pencarian kecil. Gunakan TO/EXCEPT jika memungkinkan, karena ini adalah pendekatan yang disukai untuk menargetkan prinsipal (lihat Pendekatan untuk menargetkan prinsipal). Jaga agar tabel pencarian tetap kecil sehingga pengoptimal mengonversi subkueri menjadi gabungan hash siaran (lihat Menjaga tabel pencarian tetap kecil).

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