Безопасный пароль в скриптах PowerShell
Так или иначе каждый человек, работающий с написанием скриптов рано или поздно сталкивается с тем что нужно использовать пароли в скриптах. Если это безответственный человек, то он просто вбивает пароль в скрипт в открытом виде и забывает про это.

Но есть вторая категория людей, которые уже не хотят хранить пароль в открытом виде, кстати в эту группу также могут и перейти люди с первой группы, особенно если они уже слили пароль однажды.

Export-Clixml
Наш первый вариант — это команда Export-Clixml, которая просто сохраняет пароль в xml файл. Т.е. суть работы следующая:
- Вы экспортируете пароль в файл под текущим пользователем, под которым будете запускать скрипт
- Удостоверяетесь что доступ к этому файлу есть только у этого пользователя
- Уже используя команду
Import-CliXmlимпортируете пароль в свой скрипт - Рекомендация от меня если возможно запретить этому пользователю вход в систему и сделать файл скрытым
Скажу сразу что этот вариант мне не нравится. Да вы получите доступ к файлу с паролем только под этим пользователем. Но не забываем несколько вещей:
- Малейший шанс того что кто-то зайдёт под этим пользователем в систему всё же существует
- Администратор системы может получить доступ к любым файлам, если знает, как

#ask for password $pwd = Get-Credential myuser #store password in file $pwd | Export-CLiXml password.clixml # Make files hidden (get-item password.clixml).Attributes += 'Hidden' #get password from file $password= Import-CliXml password.clixml
ConvertTo-SecureString
Вариант второй уже нравится мне больше. Тут мы используем команду ConvertTo-SecureString которая преобразует обычную строку в безопасную. Также для большей безопасности то, что мы получили от команды ConvertTo-SecureString будем дополнительно шифровать, с использованием файл ключа. Суть работы следующая:
- Мы создаём файл ключ, который дальше будет использоваться для создания зашифрованной строки
- Создаём текстовый файл, в котором сохраняем пароль в чистом виде (потом удаляем)
- Преобразовываем обычную строку в безопасную (
ConvertTo-SecureString) - Преобразовываем безопасную строку в зашифрованную используя ключ (
ConvertFrom-SecureString) - Сохраняем полученное в файл
- Используем в скриптах расшифровывая с использованием файл ключа
Тут уже как минимум наш пароль в файле становится зашифрованным, а не лежит в открытом виде. Также без ключа не получится расшифровать пароль.

#path for key file $keyFile = "keyfile.key" #path for file which contain password (must be deleted after first run) $insecurePassFile = "insecurePass.txt" ##path for file which will be contain encrypted password $securePassFile = "securePass.txt" #Create key file $key = New-Object Byte[] 32 $key | Out-File $keyFile (get-item $keyFile).Attributes += 'Hidden' #Convert password to secure string and then to encrypted string $key = Get-Content $keyFile $password = Get-Content $insecurePassFile | Select-Object -First 1 | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString -key $key $password | Out-File $securePassFile (get-item $securePassFile).Attributes += 'Hidden'
Команды выше можно запустить всего один раз, и после выполнения обязательно удалить файл с открытым паролем. Только не обновите файл с зашифрованным паролем.
После можно уже использовать эту схему у себя в скрипте:
#Get password in secure string
$SecurePassword = Get-Content $securePassFile | ConvertTo-SecureString -Key $key
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword
#Get password
$pwd = [System.Net.NetworkCredential]::new("", ( Get-Content $securePassFile | ConvertTo-SecureString -Key $key ) ).Password
$pwd
$pwd2 = $Credentials.GetNetworkCredential().Password
$pwd2
ConvertTo-SecureString
Вариант выше конечно же хорош, но мне этого еще недостаточно. Ну что тебе не нравится тут? - спросите вы. А не нравится мне то, что тут присутствует файл ключ, который всё также может стырить какой-нибудь жулик (жулик не воруй).
И что можно сделать? Да по сути ничего не надо особо менять, выполняем всё тоже самое только без ключа (ConvertFrom-SecureString). Магия тут вся заключается в Windows Data Protection API, благодаря которой вместо ключа будет не файл, а ваша учетная запись WIndows. Да, да вот такая замечательная новость, т.е. для того чтобы добраться до пароля жулику нужно будет залогинится под вашей учетной записью и именно на этом же хосте.

#path for file which contain password (must be deleted after first run) $insecurePassFile = "insecurePass.txt" ##path for file which will be contain encrypted password $securePassFile = "securePass.txt" #Convert password to secure string and then to encrypted string $password = Get-Content $insecurePassFile | Select-Object -First 1 | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString $password | Out-File $securePassFile (get-item $securePassFile).Attributes += 'Hidden'
После чего попробуйте выполнить команды ниже от разных пользователей Windows.
#Get password in secure string
$SecurePassword = Get-Content $securePassFile | ConvertTo-SecureString
$Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName, $SecurePassword
#Get password
$pwd = [System.Net.NetworkCredential]::new("", ( Get-Content $securePassFile | ConvertTo-SecureString ) ).Password
$pwd
$pwd2 = $Credentials.GetNetworkCredential().Password
$pwd2