PowerShell: Szyfrowanie hasła (poświadczeń) w skrypcie

Wiele skryptów używa poświadczeń/haseł do realizacji określonych zadań. Automatyczna wysyłka wiadomości mailowej czy realizacja zapytania SQL będzie wymagała podania nazwy użytkownika i hasła. Często zdarza się, że administrator zapomina o bezpieczeństwie tworząc skrypt i wpisuje hasło otwartym tekstem. Nie trzeba nikomu mówić o tym że nie jest to dobra ani bezpieczna praktyka. Na szczęście mamy na to sprawdzone rozwiązanie.

PowerShell pozwala na wiele sposobów zarządzać poświadczeniami. Można przypisywać login i hasło do zmiennej:

$login = 'sprawdzone.it\administrator'
$haslo = 'B@rdz0Trudn3H@s10'

a nastąpienie używać tych zmiennych. Jak informowaliśmy powyżej jest to nie bezpieczne i nie zalecane – zwłaszcza w skryptach produkcyjnych. Można poświadczenia zapisywać podczas danej sesji z użyciem polecenia Get-Credential

$poswiadczenia = get-credential

Wtedy pojawi się monit o podanie loginu i hasła. Następnie system zaszyfruje hasło i będzie przechowywał przez czas trwania sesji pod podaną wyżej zmienną.

Nasz problem jest jednak troche inny o ile można pytać usera wykoującego jednorazowo lub na rządanie poprzez get-credential o poświadczenia o tyle w automatycznym skrypcie czy zadaniu to już nie możliwe.

I to własnie System.Security.SecureString jest rozwiązaniem naszego problemu z bezpieczeństwem hasła.

Samo rozwiązanie opiera się o Windows Data Protection API a dokładnie DPAPI (Data Protection Application Programming Interface) i jest używane w produktach Microsoft od dawna. Polega ono na szyfrowaniu określonego łańcucha znaków (w naszym przypadku hasła) z użyciem zmiennej ścisłe związanej z kluczem prywatnym danego profilu użytkownika. Taki zaszyfrowany łańcuch znaków możemy przechowywać np w pliku tekstowym. Dzięki temu hasło będzie „pod ręką” gotowe do użycia np jako zmienna ale nie możliwe do odczytania przez osobę postronną – nawet po otwarciu czy skopiowaniu pliku txt. Do użycia Windows Data Protection API posłużą nam dwa polecenia:

ConvertTo-SecureString
ConvertFrom-SecureString

Zaczynamy przygotowania pliku z zaszyfrowanym hasłem:

$haslo = Read-Host "Wprowadź hasło" –AsSecureString

Następnie zapisujemy zaszyfrowane hasło:

$haslo | ConvertFrom-SecureString | Set-Content C:\it\script\haslo.txt

Dla pewności sprawdzamy jeszcze jak wygląda zawartość takiego pliku:

get-content c:\it\script\haslo.txt

Mamy już zaszyfrowane hasło jak użyć go w skrypcie? Wybraliśmy drogę z plikiem zatem przeczytajmy jego zawartość i zamieńmy z powrotem z użyciem Windows Data Protection API do hasła:

$haslo = get-content C:\it\script\haslo.txt | ConvertTo-SecureString

Jeżeli chcemy użyć loginu i hasła w jednej zmiennej zmieniamy całość w obiekt Management.Automation.PSCredential

$poswiadczenia= new-object Management.Automation.PSCredential -ArgumentList $login, $haslo

Teraz taką zmienną możemy użyć jako hasło np przy wysyłce maila skryptem (odsyłamy do naszego wpisu) – całość wygląda dużo prościej niż myślicie:

$login = 'sprawdzone.it@gmail.com'
 $haslo = get-content C:\it\script\haslo.txt | ConvertTo-SecureString
 $poswiadczenia=new-object Management.Automation.PSCredential -ArgumentList $login, $haslo
 $param = @{
     SmtpServer = 'smtp.gmail.com'
     Port = 587
     UseSsl = $true
     Credential  = $poswiadczenia
     Encoding = 'utf8'
     From = 'sprawdzone.it@gmail.com'
     To = 'info@sprawdzone.it'
     Subject = 'mail wyslany skryptem'
     Body = 'Mail wyslany ze skryptu z zaszyfrowanym haslem'
 }
 Send-MailMessage @param

Dzięki temu wzrasta poziom bezpieczeństwa naszych skryptów – szyfrować możemy dowolną zmienną nie tylko hasło. Zaszyfrowane dane nie muszą być trzymane w pliku! To dopiero początek – wkrótce kolejne wpisy.