Zasady zabezpieczeń na poziomie wiersza
Dotyczy: ✅Microsoft Fabric✅Azure Data Explorer
Użyj członkostwa w grupie lub kontekstu wykonywania, aby kontrolować dostęp do wierszy w tabeli bazy danych.
Zabezpieczenia na poziomie wiersza upraszczają projektowanie i kodowanie zabezpieczeń. Umożliwiają stosowanie ograniczeń dostępu do wierszy danych w aplikacji. Na przykład ogranicz dostęp użytkowników do wierszy odpowiednich dla ich działu lub ogranicz dostęp klienta tylko do danych istotnych dla swojej firmy.
Logika ograniczeń dostępu znajduje się w warstwie bazy danych, a nie z dala od danych w innej warstwie aplikacji. System bazy danych stosuje ograniczenia dostępu za każdym razem, gdy jest podejmowana próba dostępu do danych z dowolnej warstwy. Ta logika sprawia, że system zabezpieczeń jest bardziej niezawodny i niezawodny, zmniejszając obszar powierzchni systemu zabezpieczeń.
Zabezpieczenia na poziomie wiersza umożliwiają dostęp do innych aplikacji i użytkowników, tylko do określonej części tabeli. Na przykład możesz chcieć:
- Udzielanie dostępu tylko do wierszy spełniających niektóre kryteria
- Anonimizacja danych w niektórych kolumnach
- Wszystkie powyższe
Uwaga
Po włączeniu zasad zabezpieczeń na poziomie wiersza w tabeli dostęp jest całkowicie zastępowany przez zapytanie zabezpieczeń na poziomie wiersza zdefiniowane w tabeli. Ograniczenie dostępu dotyczy wszystkich użytkowników, w tym administratorów bazy danych i twórcy zabezpieczeń na poziomie wiersza. Zapytanie zabezpieczeń na poziomie wiersza musi jawnie zawierać definicje dla wszystkich typów użytkowników, którym chcesz udzielić dostępu.
Aby uzyskać więcej informacji, zobacz polecenia zarządzania dotyczące zarządzania zasadami zabezpieczeń na poziomie wiersza.
Napiwek
Te funkcje są często przydatne w przypadku zapytań row_level_security:
Ograniczenia
- Nie ma limitu liczby tabel, dla których można skonfigurować zasady zabezpieczeń na poziomie wiersza.
- Nie można skonfigurować zasad zabezpieczeń na poziomie wiersza w tabelach zewnętrznych.
- Nie można włączyć zasad zabezpieczeń na poziomie wiersza w tabeli w następujących okolicznościach:
- Gdy odwołuje się do niego zapytanie zasad aktualizacji, podczas gdy zasady aktualizacji nie są skonfigurowane przy użyciu tożsamości zarządzanej.
- W przypadku odwoływania się do niego przez eksport ciągły korzystający z metody uwierzytelniania innej niż personifikacja.
- Po skonfigurowaniu zasad dostępu widoku z ograniczeniami dla tabeli.
Przykłady
Ograniczanie dostępu do tabeli Sales
W tabeli o nazwie Sales
każdy wiersz zawiera szczegółowe informacje o sprzedaży. Jedna z kolumn zawiera nazwę sprzedawcy. Zamiast udzielać sprzedawcom dostępu do wszystkich rekordów w Sales
programie , włącz zasady zabezpieczeń na poziomie wiersza w tej tabeli, aby zwracać rekordy tylko wtedy, gdy sprzedawca jest bieżącym użytkownikiem:
Sales | where SalesPersonAadUser == current_principal()
Możesz również zamaskować adres e-mail:
Sales | where SalesPersonAadUser == current_principal() | extend EmailAddress = "****"
Jeśli chcesz, aby każda osoba sprzedaży widziała całą sprzedaż określonego kraju/regionu, możesz zdefiniować zapytanie podobne do:
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))
Jeśli masz grupę zawierającą menedżerów, możesz udzielić im dostępu do wszystkich wierszy. Oto zapytanie dotyczące zasad zabezpieczeń na poziomie wiersza.
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
Udostępnianie różnych danych członkom różnych grup firmy Microsoft Entra
Jeśli masz wiele grup firmy Microsoft Entra i chcesz, aby członkowie każdej grupy widzieli inny podzestaw danych, użyj tej struktury dla zapytania zabezpieczeń na poziomie wiersza.
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>)
Stosowanie tej samej funkcji zabezpieczeń na poziomie wiersza w wielu tabelach
Najpierw zdefiniuj funkcję, która odbiera nazwę tabeli jako parametr ciągu, i odwołuje się do tabeli przy użyciu table()
operatora .
Na przykład:
.create-or-alter function RLSForCustomersTables(TableName: string) {
table(TableName)
| ...
}
Następnie skonfiguruj zabezpieczenia na poziomie wiersza w wielu tabelach w następujący sposób:
.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')"
Generowanie błędu po nieautoryzowanym dostępie
Jeśli chcesz, aby użytkownicy nieuwierzytelnionej tabeli otrzymywali błąd zamiast zwracać pustą tabelę, użyj assert()
funkcji . W poniższym przykładzie pokazano, jak wygenerować ten błąd w funkcji zabezpieczeń na poziomie wiersza:
.create-or-alter function RLSForCustomersTables() {
MyTable
| where assert(current_principal_is_member_of('aadgroup=mygroup@mycompany.com') == true, "You don't have access")
}
To podejście można połączyć z innymi przykładami. Możesz na przykład wyświetlić różne wyniki dla użytkowników w różnych grupach firmy Microsoft Entra i wygenerować błąd dla wszystkich innych osób.
Kontrolowanie uprawnień do baz danych obserwowanych
Zasady zabezpieczeń na poziomie wiersza skonfigurowane w produkcyjnej bazie danych również zostaną zastosowane w kolejnych bazach danych. Nie można skonfigurować różnych zasad zabezpieczeń na poziomie wiersza w produkcyjnych i obserwowanych bazach danych. Można jednak użyć current_cluster_endpoint()
funkcji w zapytaniu zabezpieczeń na poziomie wiersza, aby osiągnąć ten sam efekt, co w przypadku różnych zapytań zabezpieczeń na poziomie wiersza w tabelach obserwowanych.
Na przykład:
.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
}
Uwaga
Powyższa funkcja zabezpieczeń na poziomie wiersza nie ma żadnego wpływu na wydajność zapytań w klastrze liderów. Wpływ na wydajność zapytań w klastrach obserwowanych będzie mieć wpływ tylko na złożoność programu DataForFollowerClusters
.
Kontrolowanie uprawnień do baz danych skrótów
Zasady zabezpieczeń na poziomie wiersza skonfigurowane w produkcyjnej bazie danych również zostaną zastosowane w bazach danych skrótów. Nie można skonfigurować różnych zasad zabezpieczeń na poziomie wiersza w produkcyjnych i skrótowych bazach danych. Można jednak użyć current_cluster_endpoint()
funkcji w zapytaniu zabezpieczeń na poziomie wiersza, aby osiągnąć ten sam efekt, co różne zapytania zabezpieczeń na poziomie wiersza w tabelach skrótów.
Na przykład:
.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
}
Uwaga
Powyższe funkcje zabezpieczeń na poziomie wiersza nie mają żadnego wpływu na wydajność zapytań w źródłowej bazie danych. Wpływ na wydajność zapytań dotyczących baz danych skrótów będzie mieć wpływ tylko na złożoność programu DataForFollowerClusters
.
Więcej przypadków użycia
- Osoba pomocy technicznej centrum telefonicznego może zidentyfikować rozmówców za pomocą kilku cyfr swojego numeru ubezpieczenia społecznego. Ta liczba nie powinna być w pełni widoczna dla osoby wspierającej. Zasady zabezpieczeń na poziomie wiersza można zastosować w tabeli, aby zamaskować wszystkie cztery ostatnie cyfry numeru ubezpieczenia społecznego w zestawie wyników dowolnego zapytania.
- Ustaw zasady zabezpieczeń na poziomie wiersza, które maskują dane osobowe (PII) i umożliwiają deweloperom wykonywanie zapytań dotyczących środowisk produkcyjnych na potrzeby rozwiązywania problemów bez naruszania przepisów dotyczących zgodności.
- Szpital może ustawić zasady zabezpieczeń na poziomie wiersza, które umożliwiają pielęgniarkom wyświetlanie tylko wierszy danych dla pacjentów.
- Bank może ustawić zasady zabezpieczeń na poziomie wiersza, aby ograniczyć dostęp do wierszy danych finansowych na podstawie działu lub roli pracownika.
- Aplikacja wielodostępna może przechowywać dane z wielu dzierżaw w jednym zestawie tabel (co jest wydajne). Używają one zasad zabezpieczeń na poziomie wiersza, aby wymusić logiczne rozdzielenie wierszy danych każdej dzierżawy z wierszy każdej innej dzierżawy, aby każda dzierżawa mogła wyświetlać tylko wiersze danych.
Wpływ na wydajność zapytań
Po włączeniu zasad zabezpieczeń na poziomie wiersza w tabeli będzie mieć pewien wpływ na wydajność zapytań, które uzyskują dostęp do tej tabeli. Dostęp do tabeli zostanie zastąpiony przez zapytanie zabezpieczeń na poziomie wiersza zdefiniowane w tej tabeli. Wpływ na wydajność zapytania zabezpieczeń na poziomie wiersza zwykle składa się z dwóch części:
- Sprawdzanie członkostwa w usłudze Microsoft Entra ID: kontrole są wydajne. Możesz sprawdzić członkostwo w dziesiątkach, a nawet setki grup bez poważnego wpływu na wydajność zapytań.
- Filtry, sprzężenia i inne operacje stosowane względem danych: wpływ zależy od złożoności zapytania
Na przykład:
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
Jeśli użytkownik nie jest częścią some_group@domain.comelementu , IsRestrictedUser
zostanie obliczony na false
wartość . Oceniane zapytanie jest podobne do następującego:
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
Podobnie, jeśli IsRestrictedUser
zostanie obliczona true
wartość , zostanie obliczone tylko zapytanie dla PartialData
.
Zwiększanie wydajności zapytań w przypadku użycia zabezpieczeń na poziomie wiersza
- Jeśli filtr jest stosowany w kolumnie o wysokiej kardynalności, na przykład DeviceID, rozważ użycie zasad partycjonowania lub zasad kolejności wierszy
- Jeśli filtr jest stosowany w kolumnie o niskiej kardynalności średniej, rozważ użycie zasad Kolejność wierszy
Wpływ na wydajność pozyskiwania
Nie ma wpływu na wydajność pozyskiwania.