資料列層級安全性

使用群組成員資格或執行內容,控制對資料庫資料表中資料列的存取。

資料列層級安全性 (RLS) 可簡化安全性的設計和編碼。 可讓您對應用程式中的資料列存取套用限制。 例如,限制使用者只能存取其部門的相關資料列,或限制客戶只能存取其公司的相關資料。

存取限制邏輯是位於資料庫層,而不是離開這些資料,到另一個應用程式層。 資料庫系統會在每次於任何層嘗試存取該資料時套用存取限制。 此邏輯可藉由縮小安全性系統的接觸區,讓安全性系統更加可靠和健全。

RLS 可讓您只將對資料表特定部分的存取權提供給其他應用程式和使用者。 例如,您可能要:

  • 僅授與符合某些準則的資料列存取權
  • 匿名某些資料行中的資料
  • 以上皆是

注意

當資料表啟用了 RLS 原則,就會將存取權完全取代為資料表上定義的 RLS 查詢。 存取限制適用於所有使用者,包括資料庫管理員和 RLS 建立者。 針對您要授與存取權的所有使用者類型,RLS 查詢必須明確地包含其定義。

如需詳細資訊,請參閱 管理數據列層級安全策略的管理命令

提示

這些函式通常對 row_level_security 查詢很有幫助:

限制

  • 對於可設定資料列層級安全性原則的資料表數目,沒有任何限制。
  • 無法在 外部數據表上設定數據列層級安全策略。
  • 在下列情況下,無法在數據表上啟用 RLS 原則:

範例

限制對 Sales 資料表的存取

在名為 Sales 的資料表中,每個資料列都包含銷售的相關詳細資料。 其中一個資料行包含銷售人員的姓名。 不要讓銷售人員存取 Sales 中的所有記錄,而是在此資料表上啟用資料列層級安全性原則,只傳回銷售人員為目前使用者的記錄:

Sales | where SalesPersonAadUser == current_principal()

您也可以遮罩電子郵件地址:

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

如果您想要讓每個銷售人員查看特定國家/地區的所有銷售量,您可以定義類似以下的查詢:

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

如果您有包含管理員的群組,您可能會想要讓他們存取所有資料列。 以下是數據列層級安全策略的查詢。

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

將不同的數據公開給不同 Microsoft Entra 群組的成員

如果您有多個 Microsoft Entra 群組,而且您希望每個群組的成員看到不同的數據子集,請使用這個結構進行 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>)

將相同的 RLS 函式套用到多個資料表

首先,定義接收資料表名稱做為字串參數的函式,並使用 table() 運算子參考資料表。

例如:

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

然後以下列方式在多個資料表上設定 RLS:

.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')"

在未經授權存取時產生錯誤

如果您想要讓非授權的數據表使用者收到錯誤,而不是傳回空的數據表,請使用 函 assert() 式。 下列範例示範如何在 RLS 函式中產生此錯誤:

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

您可以結合此方法與其他範例。 例如,您可以對不同 Microsoft Entra 群組中的用戶顯示不同的結果,併為其他人產生錯誤。

控制追蹤者資料庫的許可權

您在追蹤者資料庫上設定的 RLS 原則,也會在執追蹤者資料庫中生效。 您無法在生產和追蹤者資料庫上設定不同的 RLS 原則。 不過,您可以在 RLS 查詢中使用 current_cluster_endpoint() 函式來達成相同的效果,因為在追蹤者資料表中具有不同的 RLS 查詢。

例如:

.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
}

注意

上述 RLS 函式對領導者叢集上的查詢沒有任何效能影響。 對追蹤者叢集查詢的效能影響只會受到的複雜度 DataForFollowerClusters影響。

更多使用案例

  • 話務中心支援人員可以透過來電者社會安全號碼中的幾個數字識別來電者。 此號碼不應完全公開給支援人員。 可以在資料表上套用 RLS 原則,以在任何查詢的結果集中,遮罩社會安全號碼除最後四個數字以外的所有數字。
  • 設定隱藏個人識別資訊 (PII) 的 RLS 策略,使開發人員能夠在不違反法規規範的情況下,查詢生產環境以進行疑難排解。
  • 醫院可以設定 RLS 原則,讓護理師僅能檢視患者的資料列。
  • 銀行可以根據員工的業務部門或角色設定 RLS 原則,來限制財務資料列的存取權。
  • 多租用戶應用程式可以將許多租用戶的資料儲存在單一資料表集中 (這種方式很有效率)。 他們會使用 RLS 原則來強制對每個其他租用戶資料列的每個租用戶資料列進行邏輯分隔,讓每個租用戶只能看到其資料列。

對查詢的效能影響

在資料表上啟用 RLS 原則時,對存取該資料表的查詢會有一些效能影響。 資料表的存取權將會由該資料表上定義的 RLS 查詢所取代。 RLS 查詢的效能影響通常包含兩個部分:

  • Microsoft Entra ID 中的成員資格檢查:檢查有效率。 您可以檢查數十或甚至數百個群組的成員資格,而不會影響查詢效能。
  • 對數據套用的篩選、聯結和其他作業:影響取決於查詢的複雜度

例如:

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

如果使用者不是的一 some_group@domain.com部分,則會 IsRestrictedUser 評估為 false。 評估的查詢類似於下列查詢:

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

同樣地,如果 IsRestrictedUser 評估為 true,則只會評估 PartialData 的查詢。

改善使用 RLS 時的查詢效能

擷取的效能影響

對於擷取沒有任何效能影響。