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

thief can steal your password

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

thief can't steal your password

Export-Clixml

Наш первый вариант — это команда Export-Clixml, которая просто сохраняет пароль в xml файл. Т.е. суть работы следующая:

  1. Вы экспортируете пароль в файл под текущим пользователем, под которым будете запускать скрипт
  2. Удостоверяетесь что доступ к этому файлу есть только у этого пользователя
  3. Уже используя команду Import-CliXml импортируете пароль в свой скрипт
  4. Рекомендация от меня если возможно запретить этому пользователю вход в систему и сделать файл скрытым

Скажу сразу что этот вариант мне не нравится. Да вы получите доступ к файлу с паролем только под этим пользователем. Но не забываем несколько вещей:

  1. Малейший шанс того что кто-то зайдёт под этим пользователем в систему всё же существует
  2. Администратор системы может получить доступ к любым файлам, если знает, как

thief can steal your password

#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 будем дополнительно шифровать, с использованием файл ключа. Суть работы следующая:

  1. Мы создаём файл ключ, который дальше будет использоваться для создания зашифрованной строки
  2. Создаём текстовый файл, в котором сохраняем пароль в чистом виде (потом удаляем)
  3. Преобразовываем обычную строку в безопасную (ConvertTo-SecureString)
  4. Преобразовываем безопасную строку в зашифрованную используя ключ (ConvertFrom-SecureString)
  5. Сохраняем полученное в файл
  6. Используем в скриптах расшифровывая с использованием файл ключа

Тут уже как минимум наш пароль в файле становится зашифрованным, а не лежит в открытом виде. Также без ключа не получится расшифровать пароль.

thief can steal your password

#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. Да, да вот такая замечательная новость, т.е. для того чтобы добраться до пароля жулику нужно будет залогинится под вашей учетной записью и именно на этом же хосте.

thief can't steal your password

#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

Заключение

Для меня самым идеальным вариантом является третий по счёту. Возможность того, что кто-то сворует ваш пароль, а потом ещё и залогинится на том же хосте и найдёт файл с зашифрованным паролем невысокий.