Перейти к основному содержимому

Секреты и безопасная автоматизация

Разработчику Архитектору Инженеру
Загрузка PowerShell…

Перед продакшеном
Пароли, API-ключи и токены никогда не коммитят в Git и не вставляют в .ps1. См. также Опасные скрипты.


Зачем отдельная статья

Скрипт с $password = 'P@ssw0rd' работает на демо и ломает безопасность в продакшене. Автоматизация по 124 и 126 почти всегда требует учётных данных — SQL, SMTP, Azure, сетевые шары. Здесь — принципы и практика PowerShell.


Принципы безопасной автоматизации

ПринципСуть
Секреты вне скриптаПароли, ключи, строки подключения — в хранилище или CI, не в .ps1
Минимальные привилегииУЗ службы только с правами, нужными для одной роли скрипта
Учёт контекстаИнтерактивный запуск и планировщик — разные модели доступа
Ролевые УЗОтдельные учётки для SQL, почты, AD — «одна УЗ на систему и роль»
Логирование и алертыКто запустил, успех/сбой — без записи секретов в лог
Защита репозиторияПодпись скриптов, ревью, .gitignore для локальных конфигов с секретами

Что считать чувствительным

Очевидно: пароли, API-ключи, SSH-ключи, закрытые ключи сертификатов.

Менее очевидно, но тоже ценно для атакующего:

  • строка подключения к SQL (сужает цель);
  • имена служебных УЗ (половина пары «логин + пароль»);
  • URL внутренних админок и webhook-токены в query string.

Правило: если данные помогают злоумышленнику — их нет в исходнике скрипта.


SecureString и PSCredential

SecureString — строка в зашифрованном виде в памяти процесса (Windows DPAPI). PSCredential — объект UserName + Password (SecureString).

Интерактивный ввод:

$cred = Get-Credential -Message 'Учётные данные для SQL'
$cred.UserName
# $cred.Password — SecureString, не выводить в лог

Создание из переменной окружения или файла только на этапе подготовки машины, не в репозитории:

# Антипаттерн в Git — допустимо только в одноразовом setup-скрипте на сервере
$secure = Read-Host 'Пароль' -AsSecureString
$cred = New-Object PSCredential ('DOMAIN\svc-backup', $secure)

ConvertTo-SecureString с -AsPlainText -Force оставляет след в истории и памяти — для автоматизации используйте SecretManagement или CI secrets.


SecretManagement и SecretStore

Модуль Microsoft.PowerShell.SecretManagement — единый API; провайдеры подключают бэкенд.

ПровайдерСценарий
SecretStore (Microsoft.PowerShell.SecretStore)Один сервер, задачи планировщика
KeePassКоманда, офлайн-хранилище, общая база
Azure Key VaultОблако, ротация, аудит

Установка и настройка SecretStore:

Install-Module Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore -Scope AllUsers
Install-SecretVault -Name LocalStore -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault

Set-Secret -Name 'SqlMonitor' -Secret (Get-Credential) -Vault LocalStore
Set-Secret -Name 'SmtpApiKey' -Secret 'sg.xxxx' -Vault LocalStore

Использование в скрипте:

Import-Module Microsoft.PowerShell.SecretManagement

$sqlCred = Get-Secret -Name 'SqlMonitor' -AsCredential
$apiKey = Get-Secret -Name 'SmtpApiKey'

Invoke-Sqlcmd -Query 'SELECT 1' -Credential $sqlCred
# $apiKey — передать в заголовок HTTP, не Write-Host

Scope модулей и планировщик
Секреты и модули для задачи от SYSTEM ставят с -Scope AllUsers. Иначе планировщик не увидит vault — см. 126.


Контекст выполнения

РежимКак получить секретПример
ИнтерактивGet-Credential, Get-Secret после входа оператораРазовая миграция
Планировщик + УЗ службыSecretStore на машине, gMSA, Windows Integrated AuthМониторинг SQL
CI/CDSecrets в GitHub Actions / Azure DevOps / JenkinsDeploy pipeline
Azure AutomationCredential asset, Managed Identity — 11Runbook в облаке

Windows Integrated Auth к SQL или файловому ресурсу часто снимает необходимость пароля в скрипте: задача планировщика от доменной УЗ с нужными ACL.


Ролевые учётные записи

Один «универсальный admin» для всех скриптов упрощает жизнь на неделю и усложняет на годы.

Роль скриптаПрава
Мониторинг SQL (только sys.databases)VIEW ANY DATABASE, без чтения данных
Отправка почты через SMTP relayТолько Send As на одном relay, ограничение по IP
Архивация логовRead/Write на каталог логов и архива, без админов ОС

gMSA (group Managed Service Account) в AD — пароль не хранят в скрипте; Windows обновляет его автоматически. Подходит для служб и длительных задач в домене.


Логирование без утечек

Write-Verbose "Подключение к SQL как $($cred.UserName)"
# Плохо: Write-Host $cred.Password или $connectionString с паролем
Write-Log "SQL check finished: exit 0"

При -Verbose в планировщике включайте в настройках задачи или передавайте -Verbose в аргументах pwsh.


Риски, о которых стоит помнить

РискМитигация
Скрипт в публичном gistСекреты только в vault; ревью перед публикацией
Invoke-Expression с URLВыполнение чужого кода = чужие секреты в памяти
Экспорт Scheduled Task XML с паролемХранить XML в защищённом месте или создавать задачу кодом
Clixml с Export-Clixml для $credПривязка к пользователю/машине; не переносить между серверами без понимания DPAPI

Чек-лист

#Вопрос
1В репозитории нет паролей, ключей, .pfx без пароля?
2УЗ службы имеет минимальные права?
3Секреты читаются через SecretManagement / CI / gMSA?
4Логи не содержат connection string и токены?
5При компрометации одной УЗ ущерб ограничен одной системой?

Дальше

ТемаМатериал
Конфиги без секретов в JSON128
Триггеры и контекст УЗ126
Azure Automation, runbook11
Общая безопасность кода8.03/101

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").