Nie dawaj sysadmina. Zaprojektuj uprawnienia w SQL Server
Nie dawaj sysadmina. Zaprojektuj uprawnienia w SQL Server
W SQL Server jest jedna rola, która potrafi rozwiązać niemal każdy problem z uprawnieniami.
sysadmin.
Użytkownik nie może utworzyć bazy?
Dodajmy sysadmin.
Job nie chce się uruchomić?
Dodajmy sysadmin.
Deployment się nie udaje?
Dodajmy sysadmin.
Technicznie problem często znika.
Tylko że razem z nim znika również duża część kontroli nad bezpieczeństwem.
sysadmin nie powinien być odpowiedzią na każdy komunikat permission denied.
Powinien być świadomą decyzją administracyjną.
sysadminnie jest rozwiązaniem problemu z uprawnieniami. Bardzo często jest po prostu rezygnacją z ich projektowania.
W tym artykule pokażę, jak podejść do tego inaczej: zacząć od rzeczywistych operacji, które konto musi wykonywać, a dopiero potem dobrać odpowiednie role i uprawnienia.
Problem: konto techniczne potrzebuje „dużo uprawnień”
Załóżmy, że mamy konto deploymentowe.
Ma ono:
- tworzyć bazy danych,
- wykonywać podstawową diagnostykę instancji,
- tworzyć i uruchamiać joby SQL Server Agent,
- wykonywać określone zadania administracyjne,
- w przyszłości wykonywać deploymenty, na przykład do SSISDB,
- ale nie powinno być administratorem całej instancji.
Najprostsze rozwiązanie wygląda tak:
| |
I wszystko zaczyna działać.
Problem polega na tym, że konto dostało znacznie więcej możliwości, niż rzeczywiście potrzebuje.
Może zarządzać całą instancją.
Może zmieniać konfigurację.
Może zarządzać loginami.
Może przejmować dostęp do baz danych.
Może wykonywać operacje administracyjne, których jego zadanie w ogóle nie dotyczy.
To nie jest już rozwiązanie problemu z uprawnieniami.
To jest ominięcie modelu bezpieczeństwa.
Nie zaczynaj od roli
Najważniejsza zmiana sposobu myślenia jest bardzo prosta.
Nie zaczynaj od pytania:
Jaką rolę mam nadać użytkownikowi?
Zacznij od pytania:
Jakie dokładnie operacje ten użytkownik ma wykonywać?
Dopiero później mapuj je na:
- uprawnienia serwerowe,
- role serwerowe,
- role bazodanowe,
- role w
msdb, - SQL Server Agent Proxy,
- uprawnienia w SSISDB,
- własne role serwerowe.
To jest istota zasady least privilege.
Konto powinno mieć dokładnie tyle praw, ile potrzebuje do wykonania swojej pracy.
Ani mniej.
Ani więcej.
Demo bez domeny
Do pokazania mechanizmu nie potrzebujemy Active Directory.
Wystarczy zwykły login SQL Server.
| |
Sprawdźmy, czy konto jest członkiem sysadmin.
| |
Oczekiwany wynik:
| |
I właśnie taki stan chcemy zachować.
Konto ma tworzyć bazy danych
Jeżeli konto ma tworzyć bazy, nie oznacza to automatycznie, że potrzebuje sysadmin.
Możemy wykorzystać rolę:
| |
Teraz konto może tworzyć bazy danych, ale nadal nie kontroluje całej instancji.
Własna rola serwerowa
Załóżmy, że konto potrzebuje również podstawowego dostępu diagnostycznego.
Możemy stworzyć własną rolę serwerową:
| |
Następnie nadać jej konkretne uprawnienia:
| |
I dodać konto do tej roli:
| |
Możemy teraz sprawdzić członkostwo:
| |
Powinniśmy zobaczyć:
| |
Nie zobaczymy:
| |
I właśnie o to chodzi.
Test pozytywny: użytkownik może zrobić to, czego potrzebuje
Przełączmy kontekst bezpieczeństwa.
| |
Sprawdźmy, jako kto aktualnie działamy:
| |
Teraz wykonajmy operację, którą konto rzeczywiście ma wykonywać:
| |
Jeżeli wszystko zostało skonfigurowane poprawnie, baza zostanie utworzona.
Wracamy do poprzedniego kontekstu:
| |
To jest pierwszy test modelu bezpieczeństwa.
Operacja dozwolona powinna się udać.
Test negatywny: użytkownik nie może przekroczyć granicy
To jednak dopiero połowa testu.
Dobry model uprawnień powinien również potwierdzać, że użytkownik nie może zrobić czegoś, czego robić nie powinien.
Ponownie przełączamy kontekst:
| |
Spróbujmy dodać konto do sysadmin:
| |
Wracamy:
| |
I ponownie sprawdzamy:
| |
Wynik nadal powinien wynosić:
| |
To jest dokładnie ten model, którego szukamy.
Konto może wykonać potrzebną operację.
Nie może przekroczyć granicy, którą dla niego zaprojektowaliśmy.
Sprawdź efektywne uprawnienia
Przy projektowaniu bezpieczeństwa warto nie tylko analizować przypisane role, ale również sprawdzać efektywne uprawnienia.
SQL Server udostępnia do tego między innymi:
| |
To przydatny sposób na sprawdzenie, co konto rzeczywiście może zrobić po uwzględnieniu członkostwa w rolach oraz bezpośrednio nadanych uprawnień.
SQL Server Agent również nie wymaga sysadmina
Kolejny często spotykany argument brzmi:
Konto musi zarządzać jobami, więc potrzebuje sysadmin.
Nie musi.
SQL Server Agent posiada własny model bezpieczeństwa.
W bazie msdb dostępne są trzy podstawowe role:
| |
Każda daje inny poziom dostępu.
Na potrzeby demo tworzymy użytkownika:
| |
Następnie dodajemy go do:
| |
Możemy sprawdzić członkostwo:
| |
To nadal nie robi z naszego użytkownika administratora całej instancji.
Tworzenie joba bez sysadmina
Przełączmy kontekst na konto demo:
| |
Tworzymy prosty job:
| |
Dodajemy krok:
| |
Przypisujemy job do lokalnego serwera:
| |
Wracamy do poprzedniego kontekstu:
| |
Teraz możemy sprawdzić właściciela joba:
| |
Mamy więc kolejny przykład operacji administracyjnej, którą można wykonać bez nadawania pełnej kontroli nad instancją.
A co z PowerShell i CmdExec?
Tutaj pojawia się ważna granica.
Krok TSQL działa wewnątrz mechanizmów SQL Server.
Ale SQL Server Agent może uruchamiać również:
- PowerShell,
- CmdExec,
- SSIS,
- inne subsystemy.
Takie operacje mogą wychodzić poza sam silnik SQL Server.
I właśnie tutaj pojawiają się:
- Credential,
- SQL Server Agent Proxy.
Schemat wygląda mniej więcej tak:
| |
Zamiast:
| |
Proxy pozwala kontrolować, kto może uruchomić konkretny subsystem i pod jaką tożsamością systemową.
To znacznie lepszy model niż rozszerzanie praw użytkownika tylko po to, żeby job zaczął działać.
SSISDB również ma własny model bezpieczeństwa
Podobna sytuacja występuje przy SSIS.
Jeżeli korzystamy z Integration Services Catalog, nie powinniśmy automatycznie zakładać:
Deployment SSIS = sysadmin.
SSISDB posiada własny model uprawnień.
Możemy oddzielić:
- administratora katalogu,
- osobę wdrażającą projekty,
- operatora wykonującego pakiety,
- użytkowników mających dostęp tylko do wybranych folderów lub projektów.
Znowu wracamy do tej samej zasady.
Nie pytamy:
Jaką największą rolę mogę nadać?
Pytamy:
Jakiej konkretnie operacji potrzebuje to konto?
Uważaj na securityadmin
W takich scenariuszach często pojawia się również rola:
| |
Trzeba jednak podchodzić do niej ostrożnie.
Jeżeli konto potrzebuje zarządzać bezpieczeństwem, nie oznacza to automatycznie, że powinno zarządzać całym bezpieczeństwem instancji.
Czasami lepszym rozwiązaniem będzie:
- własna server role,
- konkretne
GRANT, - role bazodanowe,
- procedury podpisane certyfikatem,
- separacja obowiązków.
Im silniejsza rola stała, tym dokładniej warto przeanalizować jej rzeczywiste możliwości.
Testuj bezpieczeństwo w obie strony
To jedna z najważniejszych zasad całego procesu.
Bardzo często testujemy tylko:
Czy użytkownik potrafi wykonać operację?
To za mało.
Powinniśmy testować dwa przypadki.
Test pozytywny
Operacja dozwolona powinna działać.
Na przykład:
| |
Test negatywny
Operacja zabroniona powinna zakończyć się błędem.
Na przykład:
| |
Dopiero gdy oba przypadki zachowują się zgodnie z oczekiwaniem, możemy powiedzieć, że granica bezpieczeństwa działa poprawnie.
Jak projektować uprawnienia krok po kroku?
Można zastosować prosty schemat.
1. Zidentyfikuj operacje
Przykład:
| |
2. Określ zakres
Czy operacja dotyczy:
- całej instancji,
- jednej bazy,
msdb,- SSISDB,
- systemu operacyjnego?
3. Dobierz mechanizm
Może to być:
- konkretne
GRANT, - fixed server role,
- custom server role,
- database role,
- SQL Server Agent role,
- Proxy,
- Credential,
- certyfikat.
4. Nadaj minimalny zestaw praw
Nie więcej niż potrzeba.
5. Wykonaj test pozytywny
Sprawdź, czy konto potrafi wykonać swoją pracę.
6. Wykonaj test negatywny
Sprawdź, czy nie może zrobić czegoś dodatkowego.
7. Udokumentuj model
Za pół roku powinno być wiadomo:
- dlaczego konto ma dane uprawnienie,
- do czego jest ono wykorzystywane,
- jakie operacje są dozwolone,
- jakie operacje powinny pozostać zabronione.
Pełne demo
Poniższy skrypt zbiera podstawową konfigurację środowiska demonstracyjnego.
| |
Test pozytywny:
| |
Test negatywny:
| |
Na koniec sprawdzamy stan:
| |
Oczekiwany rezultat:
| |
I właśnie ten wynik najlepiej podsumowuje całe podejście.
Konto ma uprawnienie, którego potrzebuje.
Nie ma pełnej kontroli nad instancją.
Podsumowanie
sysadmin jest wygodny.
Jeżeli konto nie może czegoś zrobić, jedno polecenie potrafi usunąć problem:
| |
Tylko że zadaniem administratora nie powinno być wyłącznie doprowadzenie do sytuacji:
działa.
Powinniśmy również wiedzieć:
dlaczego działa i co jeszcze użytkownik może zrobić.
Dlatego zamiast traktować sysadmin jak lekarstwo na każdy permission denied, warto rozłożyć wymagania na konkretne operacje.
Tworzenie baz?
Nadaj odpowiednie uprawnienia do tworzenia baz.
Diagnostyka?
Nadaj konkretne uprawnienia diagnostyczne.
SQL Server Agent?
Skorzystaj z modelu bezpieczeństwa msdb.
PowerShell lub CmdExec?
Wykorzystaj Proxy i Credential.
SSISDB?
Skorzystaj z modelu bezpieczeństwa katalogu.
Dopiero kiedy konto rzeczywiście potrzebuje pełnej kontroli nad instancją, sysadmin staje się uzasadnionym wyborem.
Bo dobrze zaprojektowane bezpieczeństwo nie polega na tym, żeby użytkownik mógł zrobić wszystko.
Polega na tym, żeby mógł zrobić dokładnie to, czego potrzebuje — i nic więcej.
Najpierw zdefiniuj operację. Potem zaprojektuj dostęp. Nigdy odwrotnie.