gMSA jako konto usługi SQL Servera: wdrożenie krok po kroku
Konto usługi SQL Servera z hasłem, które nigdy nie wygasa i które zna kilka osób, zostaje bez zmian latami, bo zmiana hasła oznacza przestój na każdym serwerze. Jak wdrożyć grupowe zarządzane konto usługi (gMSA): klucz KDS, konto, instalacja na serwerach i zmiana konta w SQL Server Configuration Manager.
Przewodnik SQL Server w małej firmie Część 5 z 7
- Jak klient znajduje SQL Server: instancje, SQL Browser i porty
- Kerberos do SQL Servera: SPN, stały port i nazwa DNS
- Loginy, użytkownicy i role w SQL Serverze: kto ma dostęp do czego
- Log transakcji, który rośnie: model odzyskiwania SIMPLE i FULL
- gMSA jako konto usługi SQL Servera: wdrożenie krok po kroku
- Kopia bazy bez SQL Agenta: harmonogram zadań i własna wysyłka logu
- SQL Server Express: kiedy wystarczy, a kiedy już nie
Konto usługi SQL Servera założono przy pierwszej instalacji, kilka lat temu, z zaznaczoną opcją „Hasło nigdy nie wygasa”. Hasło zna administrator, który instalował serwer, dwie inne osoby z działu IT i co najmniej jeden były pracownik, a do tego jest zapisane w dokumentacji wdrożenia. Nikt go nie zmienia, bo zmiana oznacza nowe hasło w Active Directory, ręczne wpisanie go w każdej usłudze SQL na każdym serwerze i restart każdej instancji. Usługa pominięta przy zmianie nie wystartuje po najbliższym restarcie serwera i zgłosi błąd 1069 („The service did not start due to a logon failure”).
Grupowe zarządzane konto usługi (gMSA, group Managed Service Account) usuwa ten problem u źródła. Hasło generuje i zmienia kontroler domeny, serwery pobierają je same, a żaden człowiek go nie zna i nigdzie nie wpisuje. Ten wpis prowadzi przez wdrożenie: od klucza głównego KDS, przez utworzenie konta i instalację na serwerach, po zmianę konta instancji w SQL Server Configuration Manager.
Jak działa gMSA
Konto gMSA to obiekt Active Directory zbliżony budową do konta komputera. Hasło oblicza kontroler domeny na podstawie klucza głównego usługi KDS (Key Distribution Service) i atrybutów konta, a domyślnie zmienia je co 30 dni. Interwał można ustawić wyłącznie przy tworzeniu konta, parametrem -ManagedPasswordIntervalInDays. Później atrybut msDS-ManagedPasswordInterval jest tylko do odczytu, a inny interwał wymaga utworzenia nowego konta.
Hasło mogą pobrać tylko podmioty wpisane w atrybucie msDS-GroupMSAMembership, który ustawia parametr -PrincipalsAllowedToRetrieveManagedPassword. Najprościej wskazać w nim grupę komputerów, tu GG-SQL-Hosts z serwerami srv-sql-01 i srv-sql-02. Serwer z tej grupy pobiera z kontrolera domeny bieżące i poprzednie hasło, dlatego zmiana hasła nie wymaga restartu usług.
SQL Server obsługuje gMSA jako konto usługi od wersji 2014, na Windows Server 2012 R2 lub nowszym.
Konto wirtualne, konto domenowe czy gMSA
Instalator SQL Servera domyślnie uruchamia silnik na koncie wirtualnym, na przykład NT SERVICE\MSSQL$CRM. To dobre ustawienie dla pojedynczego serwera, który nie sięga do zasobów sieciowych. W sieci konto wirtualne występuje jako konto komputera, więc uprawnienie do udziału z kopiami dostaje cały serwer ze wszystkimi usługami, a SPN dla własnych nazw instancji trzeba rejestrować na koncie komputera i przenosić razem z instancją.
| Cecha | Konto wirtualne | Zwykłe konto domenowe | gMSA |
|---|---|---|---|
| Kto zna hasło | nikt, konto nie ma hasła | administrator, który je ustawił, i każdy, komu je przekazano | nikt, hasło oblicza kontroler domeny |
| Zmiana hasła | nie dotyczy | ręcznie w AD i w każdej usłudze, z restartem | automatycznie, domyślnie co 30 dni, bez restartu |
| Dostęp do zasobów sieciowych | jako konto komputera, np. CORP\srv-sql-01$ | jako to konto | jako CORP\svc-sql$ |
| SPN | na koncie komputera | na koncie usługi | na koncie gMSA |
| Praca na kilku serwerach | nie, tożsamość lokalna serwera | tak | tak, na serwerach z grupy GG-SQL-Hosts |
| Logowanie interaktywne | niemożliwe | możliwe dla każdego, kto zna hasło | niemożliwe |
Klucz główny KDS
Kontrolery domeny potrzebują klucza głównego KDS, zanim zaczną obliczać hasła gMSA. Klucz tworzy się raz na las, na kontrolerze domeny, z uprawnieniami grupy Domain Admins lub Enterprise Admins. Najpierw warto sprawdzić, czy klucz już istnieje, bo mógł powstać przy wdrażaniu innej usługi.
# Sprawdzenie, czy klucz już istnieje
Get-KdsRootKey
# Tylko gdy poprzednie polecenie nic nie zwróciło
Add-KdsRootKey -EffectiveImmediately
Mimo nazwy przełącznika -EffectiveImmediately Microsoft zaleca odczekać 10 godzin, zanim pierwsze konto zacznie być używane. Klucz musi się zreplikować na wszystkie kontrolery domeny, a serwer, który zwróci się o hasło do kontrolera jeszcze bez klucza, nie dostanie go. Utworzenie klucza potwierdza zdarzenie 4004 w dzienniku operacyjnym usługi KdsSvc. W laboratorium z jednym kontrolerem można ustawić datę wejścia w życie 10 godzin wstecz (-EffectiveTime ((Get-Date).AddHours(-10))); w środowisku produkcyjnym nie należy tego robić.
Grupa serwerów i konto gMSA
Konto tworzy się poleceniem New-ADServiceAccount, które domyślnie umieszcza je w kontenerze Managed Service Accounts. Parametr -DNSHostName jest wymagany dla konta grupowego i zwykle zawiera nazwę konta w domenie. Parametr -KerberosEncryptionType ogranicza szyfrowanie biletów do AES, zgodnie z zaleceniem Microsoftu dla kont zarządzanych.
# Grupa komputerów, które mogą pobrać hasło konta
New-ADGroup -Name GG-SQL-Hosts -GroupScope Global -GroupCategory Security
Add-ADGroupMember -Identity GG-SQL-Hosts -Members 'srv-sql-01$', 'srv-sql-02$'
# Konto gMSA; interwał zmiany hasła można ustawić tylko teraz
New-ADServiceAccount -Name svc-sql -DNSHostName svc-sql.corp.example.com `
-PrincipalsAllowedToRetrieveManagedPassword GG-SQL-Hosts `
-ManagedPasswordIntervalInDays 30 `
-KerberosEncryptionType AES128, AES256
Kolejny serwer SQL dodaje się do grupy GG-SQL-Hosts, a nie do samego konta. Polecenie Set-ADServiceAccount z parametrem -PrincipalsAllowedToRetrieveManagedPassword ustawia listę uprawnionych od nowa, więc łatwo nim przypadkiem odebrać dostęp działającym serwerom.
Instalacja i test na serwerze
Na każdym serwerze SQL potrzebny jest moduł ActiveDirectory dla PowerShella. Polecenie Install-ADServiceAccount sprawdza, czy serwer może korzystać z konta, i przygotowuje je lokalnie, a w przypadku gMSA buforuje konto na serwerze. Wymaga sesji PowerShella uruchomionej jako administrator.
# Moduł ActiveDirectory dla PowerShella
Install-WindowsFeature RSAT-AD-PowerShell
Install-ADServiceAccount -Identity svc-sql
Test-ADServiceAccount -Identity svc-sql
Test-ADServiceAccount zwraca True, gdy serwer może pobrać hasło i uwierzytelnić się kontem. Wynik False ma zwykle jedną z trzech przyczyn: serwer nie należy do grupy GG-SQL-Hosts albo jeszcze o tym nie wie, klucz KDS nie dotarł do kontrolera domeny, z którym rozmawia serwer, albo serwer nie obsługuje typów szyfrowania wymaganych przez konto.
Zmiana konta w SQL Server Configuration Manager
Konto instancji zmienia się w SQL Server Configuration Manager. W SQL Server 2025 otwiera go polecenie SQLServerManager17.msc, w starszych wersjach plik z odpowiednio niższym numerem. W węźle SQL Server Services trzeba otworzyć właściwości usługi SQL Server (CRM), przejść na zakładkę Log On i wpisać konto ze znakiem dolara na końcu, zostawiając puste pola hasła:
SQL Server Services > SQL Server (CRM) > Properties > Log On
This account
Account Name: CORP\svc-sql$
Password: (puste)
Confirm password: (puste)
Po zatwierdzeniu Configuration Manager proponuje restart usługi. Nowe konto działa dopiero po nim, a na czas restartu bazy instancji są niedostępne. To jedyny przestój w całym wdrożeniu, dlatego zmianę planuje się w oknie serwisowym, a kolejne zmiany hasła odbywają się już bez restartów. Tak samo zmienia się konto usługi SQL Server Agent, przy czym Microsoft zaleca osobne konta dla różnych usług SQL Servera, więc Agent może dostać własne konto albo zostać na koncie wirtualnym.
Przystawki Usługi (services.msc) nie należy do tego używać: Microsoft zaleca zmieniać konto i hasło usług SQL Servera wyłącznie jego narzędziami. Configuration Manager oprócz nazwy konta aktualizuje lokalny magazyn zabezpieczeń Windows, który chroni klucz główny usługi (service master key) silnika bazy danych. Przystawka Usługi zmienia tylko nazwę konta, a skutki wychodzą później, na przykład jako błąd „A required privilege is not held by the client” w krokach zadań Agenta. Uprawnienia do plików i rejestru instancji instalator nadaje identyfikatorowi usługi NT SERVICE\MSSQL$CRM (per-service SID), a nie kontu, więc po zmianie konta nie trzeba ich poprawiać.
Przed przełączeniem trzeba przenieść na nowe konto wszystko, co było nadane staremu: uprawnienia do udziałów sieciowych, na przykład udziału z kopiami (kopie bez SQL Agenta opisuje szósta część przewodnika), loginy starego konta na innych instancjach i ustawienia delegacji. SPN trzeba usunąć ze starego konta i zarejestrować na CORP\svc-sql$; polecenia i kolejność opisuje druga część przewodnika. Stare konto wyłącza się dopiero po sprawdzeniu, że żadna usługa z niego nie korzysta, a usuwa po okresie obserwacji.
Jedno konto dla wszystkich instancji czy kilka
Wspólne konto svc-sql dla instancji CRM, ERP i HR na obu serwerach jest najprostsze. SPN wszystkich instancji leżą na jednym koncie, delegację konfiguruje się raz, a przeniesienie instancji ze srv-sql-01 na srv-sql-02 sprowadza się do zmiany rekordu DNS, bez zmian w SPN i uprawnieniach.
Ceną jest zasięg skutków przejęcia. Każdy proces działający jako SYSTEM na dowolnym serwerze z grupy GG-SQL-Hosts może pobrać hasło konta, bo dokładnie w ten sposób pobiera je sam system. Atakujący, który przejmie jedną instancję, na przykład przez xp_cmdshell, działa w sieci jako CORP\svc-sql$, czyli z dostępem do udziałów wszystkich instancji, z ich delegacją i z loginami nadanymi temu kontu na innych serwerach.
Praktyczna zasada: jedno konto na grupę instancji o podobnej wrażliwości danych i tych samych administratorach. Instancja z danymi kadrowymi, tu HR, powinna dostać osobne konto gMSA. Osobne konto tylko częściowo ogranicza skutki przejęcia innej instancji na tym samym serwerze. Proces instancji nie działa jako SYSTEM, więc nie pobierze wprost hasła cudzego konta, ale konta usług SQL Servera mają uprawnienie do personifikacji (SeImpersonatePrivilege), które często pozwala podnieść uprawnienia do poziomu systemu. Pełną izolację daje dopiero osobny serwer i osobna grupa uprawnionych komputerów.
Sprawdź u siebie
Klucze główne KDS w lesie, polecenie do uruchomienia na kontrolerze domeny. Dobry wynik to co najmniej jeden klucz z EffectiveTime przesuniętym o co najmniej 10 godzin w przeszłość. Pusty wynik oznacza, że w lesie nie ma jeszcze kont gMSA, a data w przyszłości, że klucz jeszcze nie obowiązuje.
Get-KdsRootKey | Select-Object KeyId, CreationTime, EffectiveTime
Kto może pobrać hasło konta, z jakim interwałem jest zmieniane, jakie szyfrowanie obsługuje konto i kiedy hasło zmieniło się ostatnio. Dobry wynik to wyłącznie grupa GG-SQL-Hosts w PrincipalsAllowedToRetrieveManagedPassword, wartość 30 (albo świadomie wybrany interwał), 24 w msDS-SupportedEncryptionTypes (AES128 i AES256) oraz PasswordLastSet nie starsze niż mniej więcej jeden interwał. Konta użytkowników albo grupa Domain Computers na liście uprawnionych to zły wynik: hasło może wtedy pobrać ktoś spoza serwerów SQL.
Get-ADServiceAccount -Identity svc-sql -Properties PrincipalsAllowedToRetrieveManagedPassword, 'msDS-ManagedPasswordInterval', 'msDS-SupportedEncryptionTypes', PasswordLastSet |
Select-Object Name, PrincipalsAllowedToRetrieveManagedPassword, 'msDS-ManagedPasswordInterval', 'msDS-SupportedEncryptionTypes', PasswordLastSet
Dostęp serwera do konta, na każdym serwerze SQL osobno. Dobry wynik to True i grupa GG-SQL-Hosts na liście grup komputera. False przy obecności serwera w grupie oznacza zwykle stary bilet Kerberos, opisany w ramce o członkostwie, a brak grupy na liście oznacza, że serwera nikt do niej nie dodał.
Test-ADServiceAccount -Identity svc-sql
# Grupy, do których należy konto tego komputera
Get-ADComputer -Identity $env:COMPUTERNAME | Get-ADPrincipalGroupMembership | Select-Object Name
Konta, na których działają usługi SQL Servera na serwerze. Dobry wynik to CORP\svc-sql$ w StartName usług MSSQL$… i Running w State. Konto osoby, stare konto usługi albo LocalSystem wskazuje usługę, której jeszcze nie przełączono.
Get-CimInstance -ClassName Win32_Service -Filter "Name LIKE 'MSSQL%' OR Name LIKE 'SQLAgent%'" |
Select-Object Name, StartName, State