Внезапный, но очевидный дисклеймер: хранение авторизационных данных в любом виде (даже зашифрованном) заведомо отвратительная идея. Это даже хуже оставленной без присмотра административной сессии. Впрочем, если временно отбросить здравую паранойю и использовать метод «слепой» авторизации только в целях оправданной автоматизации…
Так вот! Спустя дебри дисклеймера, который пришлось нагородить чуть выше, поведаю триллер.
Функция Get-AdminCredential появилась на свет в муках. Изначально она умещалась в две куцые строчки в скрипте, с помощью которого (как я предполагал) можно пролечить оборванные связи между целевым хостом и контроллером домена. Тот скрипт помог. Частично. Да и то не сразу и далеко не всем.
Основная идея работы с credentials упомянутого скрипта заключалась в единоразовом вводе учётных данных профиля с правами администратора домена. Далее скрипт должен был сохранить авторизационные данные в xml-файл и больше никому не докучать расспросами, черпая всё, что нужно из него. По-крайней мере, этот функционал работал максимально безотказно и, признаться, очень радовал.
Чуть позже я решил развить идею и, пожертвовав количеством строк, перековать те самые две строки в универсальную функцию, которая бы могла работать с учётными данными в последующих проектах. Получилось вот это:
function Get-AdminCredential
{
# Имя файла для хранения учетных данных
param (
[string]$FileName = "credentials.xml"
)
# Проверяем, если функция вызывается в контексте скрипта
$scriptPath = if ($MyInvocation.MyCommand.Path)
{
Split-Path -Parent $MyInvocation.MyCommand.Path
}
else
{
# Если нет, используем текущую директорию
Get-Location
}
# Формируем полный путь к файлу с учетными данными
$credFile = Join-Path -Path $scriptPath -ChildPath $FileName
# Проверяем, существует ли файл с учетными данными
if (Test-Path -Path $credFile)
{
# Если файл существует, импортируем учетные данные из него
$credential = Import-CliXml -Path $credFile
}
else
{
# Если файл не найден, запрашиваем у пользователя учетные данные
$credential = Get-Credential -Message "Введите учетные данные администратора"
# Сохраняем введенные пользователем учетные данные в файл для будущего использования
$credential | Export-CliXml -Path $credFile
}
# Возвращаем учетные данные
return $credential
}
Структура файла credentials.xml выглядит так:
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Management.Automation.PSCredential</T>
<T>System.Object</T>
</TN>
<ToString>System.Management.Automation.PSCredential</ToString>
<Props>
<S N="UserName">user</S>
<SS N="Password">А ЗДЕСЬ ЗАШИФРОВАННЫЙ ПАРОЛЬ!</SS>
</Props>
</Obj>
</Objs>
Функция ищет файл credentials.xml или же иной файл заданный с помощью параметра -FileName, если файла не оказывается по указанным координатам — запрашивает пару Username/Password. Если же файл найден — забирает учётные данные оттуда и возвращает в виде $credential.
Функция отлично работает в скомпилированных с помощью утилиты PS2EXE скриптах.
Не могу сказать, что Get-AdminCredential мною полностью протестирована, но в условиях запроса учётных данных для командлетов с параметром -Credentials ведёт себя так, как и ожидалось.