Zabezpieczenia na poziomie wiersza

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 swojego 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 następuje próba uzyskania 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ą zapewnienie dostępu 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 zarządzanie poleceniami zarządzania zasadami zabezpieczeń na poziomie wiersza.

Porada

Te funkcje są często przydatne w przypadku zapytań row_level_security:

Ograniczenia

  • Nie ma limitu liczby tabel, w 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:

Przykłady

Ograniczanie dostępu do tabeli Sales

W tabeli o nazwie Saleskaż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 Salesprogramie , włącz zasady zabezpieczeń na poziomie wiersza w tej tabeli, aby zwracać tylko rekordy, w których sprzedawca jest bieżącym użytkownikiem:

Sales | where SalesPersonAadUser == current_principal()

Możesz również maskować 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

Uwidacznianie różnych danych członkom różnych grup Microsoft Entra

Jeśli masz wiele grup 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 nieuwierzytelnionych tabel otrzymywali błąd zamiast zwracać pustą tabelę, użyj assert() funkcji . W poniższym przykładzie pokazano, jak utworzyć 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")
}

Możesz połączyć to podejście z innymi przykładami. Na przykład możesz wyświetlić różne wyniki dla użytkowników w różnych grupach Microsoft Entra i wygenerować błąd dla wszystkich innych osób.

Kontrolowanie uprawnień do obserwowanych baz danych

Zasady zabezpieczeń na poziomie wiersza skonfigurowane w produkcyjnej bazie danych również będą obowiązywać 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 różne zapytania 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

Funkcja zabezpieczeń na poziomie wiersza powyżej 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.

Więcej przypadków użycia

  • Osoba pomocy technicznej centrum telefonicznego może zidentyfikować rozmówców przez kilka cyfr ich numeru ubezpieczenia społecznego. Ta liczba nie powinna być w pełni widoczna dla osoby wsparcia. Zasady zabezpieczeń na poziomie wiersza można zastosować w tabeli, aby zamaskować wszystkie, ale ostatnie cztery 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ń w środowiskach 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 swoich pacjentów.
  • Bank może ustawić zasady zabezpieczeń na poziomie wiersza w celu ograniczenia dostępu do wierszy danych finansowych na podstawie działu biznesowego lub roli pracownika.
  • Aplikacja z wieloma dzierżawami może przechowywać dane z wielu dzierżaw w jednym zestawie tabel (co jest wydajne). Zasady zabezpieczeń na poziomie wiersza są używane do wymuszania logicznego rozdzielenia wierszy danych każdej dzierżawy z wierszy każdej innej dzierżawy, dzięki czemu każda dzierżawa może 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:

  • Kontrole członkostwa w Tożsamość Microsoft Entra: Kontrole są wydajne. Członkostwo w dziesiątkach lub nawet setkach grup można sprawdzić bez istotnego wpływu na wydajność zapytań.
  • Filtry, sprzężenia i inne operacje stosowane na 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ą elementu some_group@domain.com, IsRestrictedUser zostanie obliczony na falsewartość . 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 truewartość , zostanie obliczone tylko zapytanie dla PartialData polecenia .

Zwiększanie wydajności zapytań w przypadku użycia zabezpieczeń na poziomie wiersza

Wpływ na wydajność pozyskiwania

Nie ma wpływu na wydajność pozyskiwania.