HashiCorp Vault: централизованное хранение секретов и политики доступа

Переменные CI и поиск секретов в git закрывают конкретные частные случаи. Там, где приложений и секретов много — несколько команд, несколько сред, десятки сервисных учётных записей — нужен отдельный централизованный сервис, который хранит секреты, выдаёт их по политике и ведёт историю версий. HashiCorp Vault — такой сервис с открытым исходным кодом.
Статья опирается на логику направления «Безопасность данных» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена на Vault в тестовом режиме (dev) в контейнере, после неё всё удалено.
Что должно получиться
| Уровень | Что это значит на практике |
|---|---|
| 2. Гигиенический | Секреты приложений хранятся в централизованном сервисе с политиками доступа, а не в коде, переменных окружения без контроля или общем чате команды |
Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.
Запись и чтение секрета
vault kv put secret/myapp/db password=СЛОЖНЫЙ_ПАРОЛЬ user=app_owner
vault kv get secret/myapp/db
Приложение не хранит пароль у себя — оно запрашивает его у Vault при старте, используя собственный токен. Важная оговорка: режим dev, использованный для проверки (vault server -dev), автоматически распечатывает хранилище и хранит данные только в памяти — для реальной эксплуатации нужен обычный режим с настроенным физическим хранилищем и ручным или автоматическим процессом распечатывания (unseal), который здесь не рассматривается.
Политика доступа только на чтение
Выдавать приложению корневой токен (как в примере выше) недопустимо — у него тогда будет доступ ко всему хранилищу. Политика ограничивает токен конкретным путём и действием:
path "secret/data/myapp/*" {
capabilities = ["read"]
}
vault policy write myapp-ro myapp-ro.hcl
vault token create -policy=myapp-ro -ttl=1h
Ключ -ttl ограничивает срок жизни токена — после истечения приложению нужно получить новый, что снижает ущерб от утечки токена по сравнению с бессрочным доступом.
Результат проверки
Действие токеном с политикой myapp-ro |
Результат |
|---|---|
Прочитать секрет по разрешённому пути (secret/myapp/db) |
Успех, данные получены |
| Записать новое значение по тому же пути | Отказ: permission denied |
Прочитать секрет по другому пути (secret/other-app/db) |
Отказ: permission denied |
| Использовать токен после истечения срока жизни (TTL 10 секунд в тесте) | Отказ: invalid token |
Политика и ограничение по времени жизни токена работают именно так, как заявлено: токен не может выйти за пределы разрешённого пути и действия, и перестаёт работать по истечении срока без дополнительных действий.
Версионирование секретов
Хранилище типа KV версии 2 (используется по умолчанию в современных версиях) хранит историю изменений секрета:
vault kv get -version=1 secret/myapp/db # предыдущее значение пароля
vault kv get secret/myapp/db # текущее (последняя версия)
В тесте после повторной записи нового пароля запрос с явным номером версии корректно вернул старое значение, а запрос без номера — новое. Это полезно при разборе инцидента: можно увидеть, каким был секрет на конкретный момент, без отдельной системы журналирования паролей.
Порядок внедрения
- Разверните Vault в обычном (не
dev) режиме с постоянным хранилищем и настройте процесс распечатывания при перезапуске. - Заведите отдельный путь и политику для каждого приложения, а не общий путь «на всё» — узкая политика ограничивает ущерб при утечке конкретного токена.
- Используйте короткоживущие токены там, где это возможно (CI, временные задачи), и регулярно продлеваемые — для постоянно работающих сервисов.
- Включите аудит-лог Vault — отдельный журнал всех обращений к секретам, не смешанный с обычными журналами приложений.
- Переносите секреты поэтапно, начиная с самых критичных (пароли к продуктивным базам), не пытайтесь мигрировать всё сразу.
Диагностика
| Симптом | Причина и что делать |
|---|---|
| Все приложения используют корневой токен | Миграция сделана наспало без политик. Заведите отдельную политику на каждое приложение, даже если это требует времени |
| После перезапуска сервера Vault недоступен | В обычном режиме хранилище нужно распечатать (unseal) после каждого запуска процесса, если не настроен автоматический механизм. Это ожидаемое поведение, не сбой |
| Приложение теряет доступ к секретам в середине дня | Истёк срок жизни токена. Настройте продление (renew) или увеличьте TTL для долгоживущих сервисов |
| Нужно узнать, кто и когда читал секрет | Без включённого аудит-лога эта информация не сохраняется. Включите аудит-устройство до того, как он понадобится при разборе инцидента |
Где это в модели зрелости
Материал относится к направлению «Безопасность данных» (материалы направления, карта зрелости). Уровень 2 требует контролируемого доступа к чувствительным данным: централизованное хранение секретов с политиками и аудитом закрывает конкретный риск — пароли и ключи, разбросанные по коду, конфигурациям и чатам без единого контроля.
Как проверить
- Секреты приложений хранятся в Vault, а не в коде, переменных окружения без контроля или текстовых файлах.
- У каждого приложения отдельная политика с минимально необходимым доступом, не общий корневой токен.
- Токены ограничены по времени жизни там, где это применимо к характеру сервиса.
- Аудит-лог включён и доступен для разбора при инциденте.
Источники
- Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
- Документация HashiCorp Vault: developer.hashicorp.com.


















