Ответ
В моей практике работа с секретами строилась на принципе "секреты — это данные в движении, а не в покое", с использованием HashiCorp Vault в качестве центрального хранилища.
1. Хранение и управление:
- Все секреты (пароли БД, TLS-сертификаты, API-ключи) хранились в Vault с включенным аудитом всех операций чтения.
- Использовались динамические секреты для БД PostgreSQL: Vault по запросу создавал пользователя с паролем, действительным 1 час, что сводило риск утечки к минимуму.
2. Интеграция в CI/CD и runtime:
- В CI/CD (GitLab): Для доступа к Vault использовался JWT-токен, который GitLab CI генерировал для каждого джоба. Скрипт получал временный токен Vault и выгружал секреты в переменные окружения пайплайна.
- В Kubernetes: Использовался Vault Agent Injector (sidecar). Аннотации в манифесте Pod указывали, какие секреты нужны, и Injector автоматически монтировал их в контейнер как файлы в tmpfs или обновлял переменные окружения.
apiVersion: v1 kind: Pod metadata: annotations: vault.hashicorp.com/agent-inject: "true" vault.hashicorp.com/role: "app-role" vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/app-role" spec: containers: - name: app image: myapp:latest
3. Ротация и аварийные процедуры:
- Критические секреты (например, root-сертификаты) имели настроенную автоматическую ротацию в Vault.
- У нас были четкие runbook'и на случай компрометации, которые включали немедленную ревокацию всех токенов определенного типа и генерацию новых секретов через Vault.