Keamanan Tingkat Baris

Gunakan keanggotaan grup atau konteks eksekusi untuk mengontrol akses ke baris dalam tabel database.

Keamanan Tingkat Baris (RLS) menyederhanakan desain dan pengkodean keamanan. Hal ini memungkinkan Anda menerapkan pembatasan akses baris data di aplikasi Anda. Misalnya, batasi akses pengguna ke baris yang relevan dengan departemen mereka, atau batasi akses pelanggan hanya ke data yang relevan dengan perusahaan mereka.

Logika pembatasan akses terletak di tingkat database daripada jauh dari data di tingkat aplikasi lain. Sistem database menerapkan pembatasan akses setiap kali akses data dicoba dari tingkat mana pun. Logika ini membuat sistem keamanan Anda lebih andal dan tangguh dengan mengurangi luas permukaan sistem keamanan Anda.

RLS memungkinkan Anda menyediakan akses ke aplikasi dan pengguna lain, hanya ke bagian tertentu dari tabel. Misalnya, Anda mungkin perlu:

  • Memberikan akses hanya ke baris yang memenuhi beberapa kriteria
  • Menganonimkan data di beberapa kolom
  • Semua benar

Catatan

Ketika kebijakan RLS diaktifkan pada tabel, akses sepenuhnya digantikan oleh kueri RLS yang ditentukan pada tabel. Pembatasan akses berlaku untuk semua pengguna, termasuk admin database dan pembuat RLS. Kueri RLS harus secara eksplisit menyertakan definisi untuk semua jenis pengguna yang ingin Anda berikan aksesnya.

Untuk informasi selengkapnya, lihat perintah manajemen untuk mengelola kebijakan Keamanan Tingkat Baris.

Tip

Fungsi-fungsi ini sering berguna untuk kueri row_level_security:

Batasan

  • Tidak ada batasan jumlah tabel di mana kebijakan Keamanan Tingkat Baris dapat dikonfigurasi.
  • Kebijakan Keamanan Tingkat Baris tidak dapat dikonfigurasi pada Tabel Eksternal.
  • Kebijakan RLS tidak dapat diaktifkan pada tabel dalam keadaan berikut:

Contoh

Membatasi akses ke tabel Penjualan

Dalam tabel bernama Sales, setiap baris berisi detail tentang penjualan. Salah satu kolom berisi nama penjual. Alih-alih memberi tenaga penjualan Anda akses ke semua baris di Sales, aktifkan kebijakan Keamanan Tingkat Baris pada tabel ini hanya mengembalikan baris di mana penjual adalah pengguna saat ini:

Sales | where SalesPersonAadUser == current_principal()

Anda juga dapat menambahkan alamat email:

Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"

Jika Anda ingin setiap orang penjualan melihat semua penjualan negara/wilayah tertentu, Anda bisa menentukan kueri yang mirip dengan:

let UserToCountryMapping = datatable(User:string, Country:string)
[
  "john@domain.com", "USA",
  "anna@domain.com", "France"
];
Sales
| where Country in ((UserToCountryMapping | where User == current_principal_details()["UserPrincipalName"] | project Country))

Jika Anda memiliki grup yang berisi manajer, Anda mungkin ingin memberi mereka akses ke semua baris. Berikut adalah kueri untuk kebijakan Keamanan Tingkat Baris.

let IsManager = current_principal_is_member_of('aadgroup=sales_managers@domain.com');
let AllData = Sales | where IsManager;
let PartialData = Sales | where not(IsManager) and (SalesPersonAadUser == current_principal()) | extend EmailAddress = "****";
union AllData, PartialData

Mengekspos data yang berbeda ke anggota grup Microsoft Entra yang berbeda

Jika Anda memiliki beberapa grup Microsoft Entra, dan Anda ingin anggota setiap grup melihat subset data yang berbeda, gunakan struktur ini untuk kueri RLS.

Customers
| where (current_principal_is_member_of('aadgroup=group1@domain.com') and <filtering specific for group1>) or
        (current_principal_is_member_of('aadgroup=group2@domain.com') and <filtering specific for group2>) or
        (current_principal_is_member_of('aadgroup=group3@domain.com') and <filtering specific for group3>)

Menerapkan fungsi RLS yang sama pada beberapa tabel

Pertama, tentukan fungsi yang menerima nama tabel sebagai parameter untai, dan mereferensikan tabel menggunakan tabel table().

Contohnya:

.create-or-alter function RLSForCustomersTables(TableName: string) {
    table(TableName)
    | ...
}

Kemudian konfigurasikan RLS pada beberapa tabel dengan cara ini:

.alter table Customers1 policy row_level_security enable "RLSForCustomersTables('Customers1')"
.alter table Customers2 policy row_level_security enable "RLSForCustomersTables('Customers2')"
.alter table Customers3 policy row_level_security enable "RLSForCustomersTables('Customers3')"

Membuat kesalahan pada akses yang tidak sah

Jika Anda ingin pengguna tabel yang tidak sah menerima kesalahan alih-alih mengembalikan tabel kosong, gunakan fungsi .assert() Contoh berikut menunjukkan kepada Anda cara membuat kesalahan ini dalam fungsi RLS:

.create-or-alter function RLSForCustomersTables() {
    MyTable
    | where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}

Anda dapat menggabungkan pendekatan ini dengan contoh lain. Misalnya, Anda dapat menampilkan hasil yang berbeda kepada pengguna di grup Microsoft Entra yang berbeda, dan menghasilkan kesalahan untuk orang lain.

Mengontrol izin pada database pengikut

Kebijakan RLS yang Anda konfigurasikan pada database produksi juga akan berlaku di database pengikut. Anda tidak dapat mengonfigurasi kebijakan RLS yang berbeda pada database produksi dan pengikut. Namun, Anda dapat menggunakan fungsi current_cluster_endpoint() dalam kueri RLS Anda untuk mencapai efek yang sama, karena memiliki kueri RLS yang berbeda dalam tabel pengikut.

Contohnya:

.create-or-alter function RLSForCustomersTables() {
    let IsProductionCluster = current_cluster_endpoint() == "mycluster.eastus.kusto.windows.net";
    let DataForProductionCluster = TempTable | where IsProductionCluster;
    let DataForFollowerClusters = TempTable | where not(IsProductionCluster) | extend EmailAddress = "****";
    union DataForProductionCluster, DataForFollowerClusters
}

Catatan

Fungsi RLS di atas tidak berdampak pada performa apa pun pada kueri pada kluster pemimpin. Dampak performa pada kueri pada kluster pengikut hanya akan terpengaruh oleh kompleksitas DataForFollowerClusters.

Lebih banyak kasus penggunaan

  • Orang yang mendukung call center dapat mengidentifikasi penelepon dengan beberapa digit dari nomor keamanan sosial mereka. Nomor ini seharusnya tidak sepenuhnya diekspos ke orang yang mendukung. Kebijakan RLS dapat diterapkan pada tabel untuk menutupi semua kecuali empat digit terakhir dari nomor keamanan sosial dalam hasil dari setiap kueri.
  • Tetapkan kebijakan RLS yang menutupi informasi pengenal pribadi (PII), dan memungkinkan pengembang untuk menanyakan lingkungan produksi untuk tujuan pemecahan masalah tanpa melanggar peraturan kepatuhan.
  • Sebuah rumah sakit dapat menetapkan kebijakan RLS yang memungkinkan perawat untuk melihat baris data untuk pasien mereka saja.
  • Bank dapat menetapkan kebijakan RLS untuk membatasi akses ke baris data keuangan berdasarkan divisi atau peran bisnis karyawan.
  • Aplikasi multi-penyewa dapat menyimpan data dari banyak penyewa dalam satu set tabel (yang efisien). Mereka akan menggunakan kebijakan RLS untuk menegakkan pemisahan logis dari baris data masing-masing penyewa dari setiap baris penyewa lainnya, sehingga setiap penyewa hanya dapat melihat baris datanya.

Dampak performa pada kueri

Ketika kebijakan RLS diaktifkan pada tabel, akan ada beberapa dampak performa pada kueri yang mengakses tabel tersebut. Akses ke tabel akan diganti dengan kueri RLS yang ditentukan pada tabel tersebut. Dampak performa kueri RLS biasanya terdiri dari dua bagian:

  • Pemeriksaan keanggotaan di Microsoft Entra ID: Pemeriksaan efisien. Anda dapat memeriksa keanggotaan dalam puluhan, atau bahkan ratusan grup tanpa dampak besar pada performa kueri.
  • Filter, gabungan, dan operasi lain yang diterapkan pada data: Dampaknya bergantung pada kompleksitas kueri

Contohnya:

let IsRestrictedUser = current_principal_is_member_of('aadgroup=some_group@domain.com');
let AllData = MyTable | where not(IsRestrictedUser);
let PartialData = MyTable | where IsRestrictedUser and (...);
union AllData, PartialData

Jika pengguna bukan bagian some_group@domain.comdari , maka IsRestrictedUser dievaluasi ke false. Kueri yang dievaluasi mirip dengan kueri ini:

let AllData = MyTable;           // the condition evaluates to `true`, so the filter is dropped
let PartialData = <empty table>; // the condition evaluates to `false`, so the whole expression is replaced with an empty table
union AllData, PartialData       // this will just return AllData, as PartialData is empty

Demikian pula, jika IsRestrictedUser dievaluasi ke true, maka hanya kueri yang PartialData akan dievaluasi.

Meningkatkan performa kueri saat RLS digunakan

Dampak performa pada pencernaan

Tidak ada dampak performa pada pencernaan.