資料列層級安全性原則
適用於: ✅Microsoft網狀架構✅Azure 數據總管
使用群組成員資格或執行內容來控制資料庫數據表中數據列的存取。
資料列層級安全性 (RLS) 簡化安全性的設計和編碼。 可讓您對應用程式中的資料列存取套用限制功能。 例如,限制使用者存取與其部門相關的數據列,或限制客戶只存取與其公司相關的數據。
存取限制邏輯位於資料庫層,而不是遠離另一個應用層中的數據。 資料庫系統會在每次嘗試從任何層級存取數據時套用存取限制。 此邏輯可藉由減少安全性系統的介面區,讓您的安全性系統更可靠且健全。
RLS 可讓您只存取特定部分的數據表,才能存取其他應用程式和使用者。 例如,您可能要:
- 僅將存取權授與符合某些準則的數據列
- 將部分數據行中的數據匿名化
- 上述所有檔案
注意
在數據表上啟用 RLS 原則時,存取權會完全由數據表上定義的 RLS 查詢所取代。 存取限制適用於所有使用者,包括資料庫管理員和 RLS 建立者。 RLS 查詢必須明確包含您想要授與存取權之所有使用者類型的定義。
如需詳細資訊,請參閱 管理數據列層級安全策略的管理命令。
提示
這些函式通常適用於row_level_security查詢:
限制
- 無法限制可以設定數據列層級安全策略的數據表數目。
- 無法在外部數據表上設定數據列層級安全策略。
- 在下列情況下,無法在數據表上啟用 RLS 原則:
- 當更新原則查詢參考時,更新原則未使用受控識別進行設定。
- 當持續匯出參考時,會使用模擬以外的驗證方法。
- 設定數據表的受限制檢視存取原則時。
- 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 原則也會在快捷方式資料庫中生效。 您無法在生產和快捷方式資料庫上設定不同的 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 原則,以遮罩任何查詢結果集中社會安全號碼的最後四位數。
- 設定 RLS 原則,以遮罩個人標識資訊 (PII),並讓開發人員在不違反合規性法規的情況下,查詢生產環境以進行疑難解答。
- 醫院可以設定 RLS 原則,讓護士只檢視其病患的數據列。
- 銀行可以設定 RLS 原則,根據員工的營業單位或角色來限制財務數據列的存取。
- 多租使用者應用程式可以將來自許多租用戶的數據儲存在單一數據表集中(這是有效率的)。 他們會使用 RLS 原則來強制執行每個租用戶數據列與其他租用戶數據列的邏輯區隔,讓每個租使用者只能看到其數據列。
對查詢的效能影響
在數據表上啟用 RLS 原則時,對存取該數據表的查詢會有一些效能影響。 數據表的存取權將會由該數據表上定義的 RLS 查詢所取代。 RLS 查詢的效能影響通常包含兩個部分:
- Microsoft Entra 識別碼中的成員資格檢查:檢查是有效率的。 您可以檢查數十個或甚至數百個群組的成員資格,而不會對查詢效能造成重大影響。
- 對數據套用的篩選、聯結和其他作業:影響取決於查詢的複雜度
例如:
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 時改善查詢效能
對擷取的效能影響
對擷取沒有效能影響。