Zasada najmniejszych uprawnień – Row-Level Security – SQL Server Security

W tym wpisie będę ponownie poruszać się po obszarach bezpieczeństwa i ograniczania dostępu do danych. Mowa konkretnie będzie o Row-Level Security, który umożliwia nadawanie uprawnień do konkretnych wierszy w zależności np:

  • Stanowisku w firmie,
  • Departamentu, w którym użytkownik pracuje,
  • Regionu lub obszaru, w którym realizuję swoje obowiązki

Jest to technologia, która może okazać się świetnym uzupełnieniem dla Dynamic Data Masking gdzie uprawnienia mieliśmy zupełnie zero-jedynkowe.

Row-Level Security, jak to działa?

Kontroluję dostęp na poziomie wierszy na podstawie użytkownika lub  członkostwie w grupie.  Rozwiązanie Row-Level Security wykorzystuję predykaty, które są dodawane do wszystkich zapytań do tabeli, dla której zostaną utworzone zasady bezpieczeństwa. Ograniczanie dostępu następuje na warstwie bazy danych, poza warstwą aplikacji. Tak jak wcześniej wspomniałem Row-Level Security składa się z dwóch elementów:

  • Predykat filtrujący (predykatu), który jest funkcją tabelaryczną, która sprawdza, czy użytkownik wykonujący określone zapytanie w tabeli ma uprawnienia do wierszy w tabeli. Zwraca wartość 1 dla każdego wiersza, do którego użytkownik ma dostęp.
  • Zasad bezpieczeństwa,  które są odpowiedzialne za stosowanie ww. funkcji filtrujących do tabel/tabeli. Gdy użytkownik uruchomi polecenia SQL, które odwołują się do tabeli w polityce bezpieczeństwa, uruchamia również funkcję filtrującą (predykatu). Istnieją dwa typy predykatów zabezpieczeń:
    • Prydykat filtrujący (ADD FILTER PREDICATE) po cichu filtruj operacje SELECT, UPDATE i DELETE, aby wykluczyć wiersze, które nie spełniają prydykatu.
    • Predykaty blokujące (ADD BLOCK PREDICATE) jawnie blokują operacje INSERT, UPDATE i DELETE, które nie spełniają predykatu.

Row-Level Security - schemat

Zalety vs wady Row-Level Security

Tak jak w Dynamic Data Masking również tutaj otrzymujemy transparentność dla aplikacji, co pozwala w teorii na implementacje Row-Level Security bez ingerencji w aplikację.

Jeśli chodzi o wady. Osobiście w pierwszym kontakcie dla mnie mało intuicyjne, ale subiektywne spostrzeżenie. Jednak zrozumienie rozwiązania jest kluczowe dla naszych późniejszych zapytań do tabel gdzie Row-Level Security zostanie włączone. Im bardziej złożone predykaty filtrujące przygotujemy tym większy wpływ będą miały na wydajności zapytań.

Oprócz tego, jeśli użytkownik członek roli db_owner lub właściciel tabeli zapyta o tabelę, dla której włączona jest polityka bezpieczeństwa, wiersze są wtedy filtrowane lub blokowane zgodnie z definicją zasad zabezpieczeń. Czy to zaleta czy wada? To zależy. Trzeba o takich użytkowników odpowiednio zadbać w zależności od założeń.

Demo Row-Level Security

W przykładzie posłużę się bazą Northwind. Lubię ją za swoją prostotę, idealna do tego typu przykładów. W celu uruchomienia poniższych skryptów należy ja odtworzyć na swoim środowisku oraz podnieść poziom kompatybilności przynajmniej do 130 (SQL Server 2016)

W przykładzie będę chciał ograniczać dostęp do zamówień oraz tabeli z pracownikami. Każdy pracownik będzie miał możliwość zobaczyć tylko zamówienia obsługiwane przez nich. Chyba, że będzie członkiem grupy TopManagment. Oprócz tego dodam dodatkowy „wytrych” dla użytkowników będących członkami ‚db_owner’.

Zaczynamy od użytkowników, uprawnień oraz utworzenia roli.

Następnie tworzymy predykat filtrujący. Lakonicznie tłumacząc, parametrem funkcji będzie wartość kolumny EmployeeID. Wartość ta będzie porównywana wynikiem podzapytania SELECT EmployeeID FROM dbo.Employees WHERE LastName+FirstName = USER_NAME(), gdzie  USER_NAME() to nazwa użytkownika. Jeśli funkcja zwróci wartość 1 oznacza, że użytkownik pytają ma dostęp do tego konkretnego wiersza.

Poniżej ta sama funkcja ale z dodatkowymi obejściami dotyczącymi członkostwa roli db_owner lub TopManagment.

Mając przygotowany predykat filtrujący, tworzymy jedną zasady bezpieczeństwa zarówno dla dbo.Employees oraz dbo.Orders

To wszystko. Pozostaję sprawdzenie czy uzyskałem efekt zgodnie z założeniami.

Row-Level Security - predykat filtrujący

Zasada najmniejszych przywilejów - Row-Level Security

Row-Level Security - implementacja

Wygląda, że cel został osiągnięty. W ten sposób udało się ograniczyć dostęp tylko do danych niezbędnych/wymaganych dla danego pracownika.

Podsumowanie

Jak dla mnie, Row-Level Security to rozwiązanie, które może okazać się niezwykle interesujące między innymi dla działów bezpieczeństwa.

Z pasją poświęcam czas na zdobywanie wiedzy w zakresie szeroko rozumianej Data Platform. Zachwycony językiem skryptowym Windows PowerShell. Swoją wiedzę, doświadczenia i spostrzeżenia opisuję na blogu.

Leave a Reply

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *