Управление секретами
| Что такое секрет | пароль БД, API-ключ, токен, закрытый ключ, сертификат |
|---|---|
| Главное правило | не хранить секреты в коде и git |
| Хранилища | HashiCorp Vault / OpenBao, AWS Secrets Manager, GCP Secret Manager, Azure Key Vault |
| Шифрование в git | SOPS, age, git-crypt, Sealed Secrets |
| Поиск утечек | gitleaks, trufflehog, GitHub secret scanning |
| В Kubernetes | Secret, External Secrets Operator, CSI Secrets Store |
Управление секретами (англ. secrets management) — совокупность практик и инструментов для работы с чувствительными учётными данными: паролями баз данных, API-ключами, токенами доступа, закрытыми ключами TLS и SSH. Задача — чтобы секрет был доступен ровно тем программам и людям, которым он нужен, не утекал в исходный код, логи и образы, мог быть быстро заменён и чтобы каждое обращение к нему оставляло след.[1]
Почему это проблема
Самая частая утечка — секрет, закоммиченный в Git. Удаление файла следующим коммитом не помогает: значение остаётся в истории, в форках и клонах, а публичные репозитории сканируются ботами в течение минут после пуша. Другие типичные пути утечки — образы контейнеров со скопированным .env, логи и трассировки ошибок, переменные в выводе CI, общие чаты и вики, ноутбуки Jupyter.
Жизненный цикл секрета
- Создание — генерация достаточно длинного случайного значения (не придуманного человеком).
- Хранение — в зашифрованном виде, в одном доверенном месте.
- Доставка — приложению во время запуска, а не во время сборки.
- Использование — с минимальными правами: у каждого сервиса свой ключ.
- Ротация — регулярная замена и немедленная замена при подозрении на утечку.
- Отзыв и аудит — журнал: кто, когда и какой секрет прочитал.
Способы хранения
Переменные окружения и файлы
Методология Twelve-Factor App предлагает отделять конфигурацию от кода через переменные окружения.[7] Это лучше, чем константы в коде, но переменные видны дочерним процессам, попадают в дампы и /proc/<pid>/environ, а файл .env легко случайно закоммитить. Распространённый компромисс — .env только локально и в .gitignore, а в рабочей среде — файл с правами 0600 или монтируемый том в памяти (tmpfs).
Шифрование в репозитории
Секреты можно хранить в git зашифрованными. SOPS шифрует значения в YAML/JSON/ENV-файлах, оставляя ключи читаемыми, что удобно для ревью и diff; ключи берутся из age, PGP или облачного KMS.[3]
sops --encrypt --age age1q...xyz secrets.yaml > secrets.enc.yaml
sops exec-env secrets.enc.yaml './run-app'
Аналоги — git-crypt, а в Kubernetes — Sealed Secrets, где шифрованный ресурс расшифровывает только контроллер в кластере.
Централизованные хранилища
HashiCorp Vault (и его открытый форк OpenBao) — сервер, который хранит секреты зашифрованными, выдаёт их по политикам после аутентификации клиента (токен, Kubernetes ServiceAccount, облачная роль, OIDC) и ведёт журнал аудита.[2] Его сильная сторона — динамические секреты: вместо постоянного пароля к PostgreSQL Vault создаёт для каждого клиента временного пользователя БД с ограниченным сроком жизни и сам удаляет его по истечении. Облачные аналоги — AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, Yandex Lockbox.
Kubernetes
Объект Secret по умолчанию хранится в etcd лишь в base64 — это кодирование, а не шифрование. Рекомендации:[4] включить шифрование etcd, ограничить RBAC-доступ к секретам, монтировать их как файлы, а не переменные, и синхронизировать из внешнего хранилища через External Secrets Operator или CSI Secrets Store Driver.
Секреты в CI/CD
Системы CI/CD имеют встроенные хранилища (GitHub Actions secrets, GitLab CI variables) и маскируют значения в логах — но маскировка ломается при любом преобразовании строки. Лучше вообще не хранить долгоживущие облачные ключи: GitHub Actions и GitLab CI умеют получать OIDC-токен и обменивать его на короткоживущие облачные учётные данные. Секреты не должны быть доступны сборкам из форков.
Обнаружение утечек
- pre-commit с gitleaks или trufflehog не даёт закоммитить строку, похожую на ключ.[6]
- GitHub secret scanning и push protection проверяют пуши и уведомляют провайдеров, которые автоматически отзывают найденные ключи.[5]
- Периодическое сканирование истории и образов контейнеров.
Если секрет утёк
- Сначала отозвать и заменить — это единственное, что действительно помогает.
- Проверить журналы использования за период утечки.
- Только потом чистить историю (
git filter-repo), понимая, что копии уже могли разойтись. - Разобрать причину: почему секрет оказался там, где его не должно быть.
См. также
- Хранение паролей (bcrypt, Argon2)
- Криптография с открытым ключом
- GitHub Actions
- Infrastructure as Code