Управление паролями локальных администраторов. Бесплатная замена Microsoft LAPS

10 июля 2024

Одной из распространенных задач ИБ является управление паролями локального администратора. У компании Microsoft для управления паролями и регулярной их ротации существует продукт LAPS (Local Administrator Password Solution). Однако, он обеспечивает ротацию паролей локальных учетных записей только для доменных серверов. Для серверов не в домене, Linux-серверов LAPS не применим. С помощью существующих open source продуктов Hashicorp Vault, OpenBao, StarVault можно построить систему, которая позволяет автоматически ротировать пароли:

  • для любых локальных учетных записей.
  • вне зависимости от того входят ли сервера в домен или нет.
  • вне зависимости от операционной системы.

Архитектура

Система состоит из 2х компонентов:

  • Сервер, в роли которого выступает Hashicorp Vault, OpenBao, StarVault.
  • Клиент:
    • для Linux - приложение написаное на Go. Язык Go выбран, т.к. удобнее обрабатывать ошибки, по сравнению с bash, и не требуется устанавливать зависимости в отличие от Python.
    • для Windows - скрипт powershell.

Vault и его альтернативы отвечают за :

  • создание надежных паролей в соотвествии с заданными политиками.
  • хранение паролей с разграничением доступа.
  • хранение истории паролей с заданной глубиной хранения.

Клиентская часть:

  • запрашивает новый пароль у Vault.
  • сохраняет пароль в Vault.
  • обновляет пароль на хосте для заданной учетной записи.

Для запуска клиентской части по расписанию используются:

  • в Linux - таймер systemd.
  • в Windows - Task Scheduler.

Права доступа к секретам (паролям) разграничены таким образом, что сервера могут только создавать и обновлять секреты в Vault. А системные администраторы - только читать эти секреты.

Исходный код клиентской части размещен на https://gitverse.ru/strongpass/manage-local-admin-password

Настройка Vault

Предполагается, что у вас уже есть развернутый сервер Vault и вы можете к нему подключиться с административной учетной записью. В статье не будет описываться выбор схемы развертывания и установка Vault, т.к. таких статей уже достаточно много в Интернeт. Так же в статье не рассматривается настройка прав доступа к чтению секретов для системных администраторов, т.к. она индивидуальна в каждой компании.

Аутентифицируемся в Vault с помощью токена (вместо <токен> подставьте свой токен доступа):

> vault login token=<токен>


Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.

Key                  Value
---                  -----
token                hvs.cNsG340tvlimz8ENAM4HtrMY
token_accessor       Zw3IjEt8LqNiLqoA4hcTxvBh
token_duration       ∞
token_renewable      false
token_policies       ["root"]
identity_policies    []
policies             ["root"]

Полученный токен сохраним в переменную среды VAULT_TOKEN

export VAULT_TOKEN="hvs.cNsG340tvlimz8ENAM4HtrMY"

Создадим файл password-policy.hcl с настройками парольной политики:

length=20
rule "charset" {
  charset = "abcdefghijklmnopqrstuvwxyz"
  min-chars = 1
}
rule "charset" {
  charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  min-chars = 1
}
rule "charset" {
  charset = "0123456789"
  min-chars = 1
}
rule "charset" {
  charset = "!@#$%^&*-"
  min-chars = 1
}

Создадим парольную политику с именем local-account-pwd-policy:

vault write sys/policies/password/local-account-pwd-policy policy=@password-policy.hcl

Проверим, что можем получить сгенерированный пароль в соответствии с этой политикой:

curl --request GET \
  --url http://vault.acme.corp/v1/sys/policies/password/local-account-pwd-policy/generate \
  --header "X-Vault-Token: $VAULT_TOKEN"

В случае успеха, вы должны получить ответ вида:

{"request_id":"c6ea55d6-189a-df1f-4279-ab2947f0722f","lease_id":"","renewable":false,"lease_duration":0,"data":{"password":"UAVq1SVXVR8XWwRB7pxG"},"wrap_info":null,"warnings":null,"auth":null}

В поле data.password будет находиться сгенерированный пароль.

Создадим KV-хранилище с именем local-account-creds для хранения паролей:

vault secrets enable -version=2 -path=local-accounts-creds kv

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

# Allows hosts to write new passwords
path "local-accounts-creds/*" {
capabilities = ["create", "update"]
}


path "sys/policies/password/local-account-pwd-policy/generate" {
  capabilities=["read"]

}

Включаем метод атунтификации AppRole, который предназначен для аутентификации сервисов, приложений:

vault auth enable approle

Создаем роль для серверов

vault write auth/approle/role/pwd-rotate token_policies="password-rotate" token_ttl=1h token_max_ttl=2h

В данном варианте предполагается, что роль одна для всех серверов или группы серверов. Для усиления безопасности вы можете создавать отдельные роли для каждого сервера и устанавливать дополнительные ограничения для ролей. Проверяем правильность параметров:

❯ vault read auth/approle/role/pwd-rotate
Key                        Value
---                        -----
bind_secret_id             true
local_secret_ids           false
secret_id_bound_cidrs      <nil>
secret_id_num_uses         0
secret_id_ttl              0s
token_bound_cidrs          []
token_explicit_max_ttl     0s
token_max_ttl              2h
token_no_default_policy    false
token_num_uses             0
token_period               0s
token_policies             [password-rotate]
token_ttl                  1h
token_type                 default

Обратите внимание на token_policies. Если вы сделали все правильно, то значение этого параметра будет содержать имя политики для генерации паролей.

Получаем role-id и secret-id. RoleID - это идентификатор AppRole, по которому оцениваются другие учетные данные. При аутентификации в систему RoleID всегда является обязательным аргументом (через role-id). В данном случае role-id эквивалентен имени пользователя, а secret-id - соответствующему паролю.

❯ vault read auth/approle/role/pwd-rotate/role-id
Key        Value
---        -----
role_id    c59c3a2f-1991-5a8f-d08f-d8f8415ff6aa
❯ vault write -force auth/approle/role/pwd-rotate/secret-id
Key                   Value
---                   -----
secret_id             53e7b725-b93e-ffdd-5865-0ef3b48ccca7
secret_id_accessor    8dc2d921-5ce1-ba52-0110-97eecd1f5a1b
secret_id_num_uses    0
secret_id_ttl         0s

Значение параметра secret_id_ttl равное 0s означает, что secret_id действует бессрочно.

Пробуем авторизоваться с указанными данными и получить токен доступа:

❯ vault write auth/approle/login role_id="c59c3a2f-1991-5a8f-d08f-d8f8415ff6aa" secret_id="53e7b725-b93e-ffdd-5865-0ef3b48ccca7"


Key                     Value
---                     -----
token                   hvs.CAESIIMFzrS9j-6p5hQo5cofWpHZS__qoc0Kxqr95pc6nCyMGh4KHGh2cy5ZS0lNRE9ySGlrYVhVTnBtZTdZc3JQTmo
token_accessor          RpP3Cwc3CeHOWbk1MonNaqDU
token_duration          1h
token_renewable         true
token_policies          ["default" "password-rotate"]
identity_policies       []
policies                ["default" "password-rotate"]
token_meta_role_name    pwd-rotate

Для дальнейших проверок сохраняем токен доступа в переменную окружения VAULT_TOKEN

export VAULT_TOKEN="hvs.CAESIIMFzrS9j-6p5hQo5cofWpHZS__qoc0Kxqr95pc6nCyMGh4KHGh2cy5ZS0lNRE9ySGlrYVhVTnBtZTdZc3JQTmo"

Проверяем, что политики доступа настроены правильно и мы можем получить сгенерированный пароль:

❯ curl -k --request GET \
  --url http://vault.acme.corp/v1/sys/policies/password/local-account-pwd-policy/generate \
  --header "X-Vault-Token: $VAULT_TOKEN"

В случае успеха, в поле data.password будет содержаться новый пароль:

{"request_id":"dd9250a2-655e-b8ea-f750-ca5291505e6d","lease_id":"","renewable":false,"lease_duration":0,"data":{"password":"zH2c54POGm4YKEwHzmxC"},"wrap_info":null,"warnings":null,"auth":null}

Проверяем запись пароля в Vault:

curl \
  --header "X-Vault-Token: $VAULT_TOKEN" \
  --json '{"data":{"root": "password-test"}}' \
  http://vault.acme.corp/v1/local-accounts-creds/data/host_test

Успешный ответ будет выглядеть так:

{"request_id":"dca9f6c9-172d-0f42-c985-3715522f0d55","lease_id":"","renewable":false,"lease_duration":0,"data":{"created_time":"2024-07-07T14:53:25.263274272Z","custom_metadata":null,"deletion_time":"","destroyed":false,"version":2},"wrap_info":null,"warnings":null,"auth":null}

Со стороны Vault все готово для автоматизации смены паролей.

Настройка клиентской части для Linux

Переходим на сервер, на котором планируем автоматически менять пароль. Скачайте архив с клиентской частью для Linux (файл password-auto-rotate.lnx.tar.gz ) со страницы https://gitverse.ru/strongpass/manage-local-admin-password/releases и распакуйте его.

Скопируйте файл password-auto-rotate в /usr/local/bin

Скопируйте файл assets/password-auto-rotate.env в /etc/defaut и устанавите переменным значения, полученные при настройке Vault:

VAULT_ADDR="https://vault.acme.corp"
ROLE_ID=c59c3a2f-1991-5a8f-d08f-d8f8415ff6aa
SECRET_ID=53e7b725-b93e-ffdd-5865-0ef3b48ccca7
PASSWORD_POLICY_NAME="local-account-pwd-policy"
SECRETS_STORE_NAME="local-accounts-creds"
SECRETS_BASE_PATH="linux"

Скопируйте файлы из архива assets/password-auto-rotate.timer и assets/password-auto-rotate.service в /etc/systemd/system . Эти файлы в дальнейшем будут использоваться как основа для сервисов, которые меняют пароли у конкретных пользователей. Вы можете настроить ротацию паролей для любой локальной учетной записи.

Создаем сервисы для смены пароля у пользователя root:

cp /etc/systemd/system/password-auto-rotate.service /etc/systemd/system/password-auto-rotate@root.service
cp /etc/systemd/system/password-auto-rotate.timer /etc/systemd/system/password-auto-rotate@root.timer

Активируем таймер:

systemctl enable --now /etc/systemd/system/password-auto-rotate@root.timer

Повторите два последних действия для каждой учетной записи, пароль которой необходимо автоматически менять.

Посмотреть список таймеров и их статус можно командой systemctl list-timers --all

Запустим сервис для проверки правильности всех настроек.

systemctl start password-auto-rotate@root.service

Результат выполнения сервиса можно посмотреть в журнале.

journalctl -xeu password-auto-rotate@root.service

При необходимости вывод сообщений о ходе выполнения сервиса можно перенаправить в файл. Подробнее см. README

Система готова для автоматической ротации паролей на Linux-серверах.

Настройка клиентской части для Windows

Скачайте архив password-auto-rotate.win.zip со страницы https://gitverse.ru/strongpass/manage-local-admin-password/releases. и распакуйте его.

Скопируйте файл в password-auto-rotate.ps1 в каталог C:\Program Files\password-auto-rotate\

Запустите скрипт из командной строки powershell и убедитесь, что с указанными вами параметрами командной строки обновление пароля происходит успешно. Пример запуска скрипта:

.\password-auto-rotate.ps1 -VaultAddr "https://vault.acme.corp" -RoleID "c59c3a2f-1991-5a8f-d08f-d8f8415ff6aa" -SecretID "53e7b725-b93e-ffdd-5865-0ef3b48ccca7" -PasswordPolicyName "local-account-pwd-policy" -SecretsStoreName "local-accounts-creds" -SecretsBasePath "windows" -Username Administrator

Создайте задачу в Task Scheduler. Сначала указываем базовые параметры:

$principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount
$settings = New-ScheduledTaskSettingsSet

Зададим расписание запуска:

$trigger = New-ScheduledTaskTrigger -RandomDelay (New-TimeSpan -Minute 1) -Daily -At 1am

Создадим команду, которая будет выполняться задачей. Обратите внимание, что значение параметра Argument находится в одинарных кавычках.

$action = New-ScheduledTaskAction -Execute "powershell.exe"  -Argument '-File "C:\Program Files\password-auto-rotate\password-auto-rotate.ps1" -VaultAddr "https://vault.acme.corp" -RoleID "c59c3a2f-1991-5a8f-d08f-d8f8415ff6aa" -SecretID "53e7b725-b93e-ffdd-5865-0ef3b48ccca7" -PasswordPolicyName "local-account-pwd-policy" -SecretsStoreName "local-accounts-creds" -SecretsBasePath "windows" -Username Administrator'

Теперь создаем непосредственно саму задачу и регистрируем ее в Task Scheduler:

$task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings
Register-ScheduledTask -TaskName "Password auto rotate" -InputObject $task

Результаты выполнение скрипта пишутся:

  • кратко - в журнал Application Windows Event Log. Сообщения можно найти произведя поиск по источнику сообщений PasswordAutoRotate.
  • подробно - в файл C:\windows\debug\password-auto-rotate.log

Система готова для автоматической ротации паролей на Windows-серверах.