Когда пароль к базе данных живет минуты, а не месяцы

Ваша команда меняет пароли к базе данных каждые три месяца. Вы чувствуете себя в большей безопасности, чем команды, которые вообще не меняют пароли. Но вот неудобный вопрос: что произойдет, если пароль утечет через два дня после смены? Этот секрет останется действительным еще на 88 дней. Любой, кто его найдет, сможет получить доступ к вашей production-базе данных почти три месяца, пока следующая ротация не аннулирует его.

Этот разрыв — не теория. Секреты утекают через файлы логов, скомпрометированные CI-раннеры, ноутбуки разработчиков или некорректно настроенные резервные копии. Статический секрет с долгим сроком жизни дает злоумышленникам широкое окно возможностей. Чем дольше живет секрет, тем больший ущерб может нанести одна утечка.

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

Что делает секрет динамическим

Динамический секрет — это не хранимое значение. Это учетные данные, созданные в момент, когда они кому-то понадобились, со сроком жизни, измеряемым минутами или секундами. Когда задача завершается, учетные данные исчезают. Никто не сможет использовать их позже.

Представьте такой сценарий: вашему CI-пайплайну нужно запустить миграцию для базы данных PostgreSQL. Со статическим секретом пайплайн читает сохраненный пароль из хранилища, подключается к базе данных, выполняет миграцию и отключается. Этот пароль остается действительным для будущего использования. Если кто-то извлечет его из логов пайплайна, он сможет подключаться к базе данных в любое время до следующей ротации.

Следующая диаграмма последовательности показывает, как работает этот процесс:

sequenceDiagram participant CI as CI Pipeline participant V as Vault participant DB as Database CI->>V: Request DB access for migration V->>DB: Create temp user + password DB-->>V: Credentials V-->>CI: Return temp credentials CI->>DB: Run migration DB-->>CI: Migration done CI->>V: Signal task complete V->>DB: Revoke temp user DB-->>V: Confirmed

С динамическим секретом пайплайн отправляет запрос в хранилище: "Мне нужен доступ к базе данных для этой миграции". Хранилище создает новое имя пользователя и пароль, предоставляет права на чтение и запись в схему миграции и возвращает учетные данные пайплайну. Пайплайн использует их, завершает миграцию, и хранилище автоматически отзывает учетные данные. Имя пользователя и пароль, существовавшие в течение этого пятиминутного окна, теперь мертвы. Даже если логи пайплайна утекут, эти учетные данные бесполезны.

Вот как выглядит такой запрос к хранилищу на практике:

# Request a dynamic database credential from Vault
VAULT_RESPONSE=$(vault read -format=json database/creds/migration-role)

# Extract the temporary username and password
DB_USER=$(echo "$VAULT_RESPONSE" | jq -r '.data.username')
DB_PASS=$(echo "$VAULT_RESPONSE" | jq -r '.data.password')

# Use the credential for the migration
psql "postgresql://${DB_USER}:${DB_PASS}@db.example.com:5432/production" \
  -f ./migrations/001_initial.sql

# The credential expires automatically after its TTL (e.g., 5 minutes)
# No manual revocation needed

Ключевое отличие: время жизни

Статические секреты имеют долгий срок жизни. Вы храните их, периодически меняете и надеетесь, что они не утекут между ротациями. Риск пропорционален времени жизни. Пароль, меняемый каждые 90 дней, дает злоумышленнику потенциальное окно в 90 дней.

Динамические секреты имеют короткий срок жизни. Они создаются для конкретной цели и уничтожаются после ее достижения. Окно для эксплуатации сокращается с месяцев до минут. Если учетные данные утекают, к тому моменту, когда их кто-то находит, они уже истекли.

Этот сдвиг меняет то, как вы думаете об управлении секретами. Вместо вопроса "кто может прочитать этот секрет?" вы задаете вопрос "кто может запросить новый секрет?" Хранилище берет на себя все остальное.

Как динамические секреты меняют контроль доступа

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

Динамические секреты позволяют определять политики доступа на уровне запроса. Когда пайплайну нужен доступ к базе данных, хранилище создает учетные данные с ровно теми разрешениями, которые требуются этому пайплайну. Пайплайн только для чтения получает учетные данные только для чтения. Пайплайн миграции получает доступ на запись к определенным таблицам. Аналитический пайплайн получает доступ только на выборку к определенным схемам.

Такая детализация делает аудит простым и понятным. Каждые учетные данные привязаны к конкретному запросу, конкретному пайплайну и конкретному временному окну. Вы можете точно отследить, что произошло, когда и с какими разрешениями.

Когда динамические секреты не подходят

Динамические секреты — мощный инструмент, но они не являются универсальной заменой статическим секретам. Некоторые ситуации по-прежнему требуют долгоживущих учетных данных.

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

Внешние системы, не поддерживающие автоматическое создание учетных данных, также создают проблему. Если вам нужно аутентифицироваться в стороннем API, который выдает токены через ручной процесс регистрации, вы не сможете генерировать для него динамические учетные данные. Вы застряли со статическими токенами и должны тщательно управлять их ротацией.

Некоторые устаревшие системы не имеют API, необходимых для динамического предоставления учетных данных. Если ваша база данных не поддерживает программное создание пользователей или ваш облачный провайдер требует ручного создания IAM-ролей, динамические секреты не являются вариантом.

Инструменты для работы с динамическими секретами

HashiCorp Vault — самый распространенный инструмент для управления динамическими секретами. Он поддерживает генерацию учетных данных для PostgreSQL, MySQL, MongoDB, AWS, GCP и многих других систем. Когда клиент запрашивает учетные данные, Vault создает их, назначает аренду с временем жизни (TTL) и автоматически отзывает их по истечении аренды.

Другие инструменты, такие как CyberArk Conjur и AWS Secrets Manager, также предлагают возможности динамических секретов, хотя реализация различается. Ключевая функция, на которую стоит обратить внимание, — это автоматическое создание и отзыв учетных данных без ручного вмешательства.

Практический чек-лист перед внедрением динамических секретов

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

  • Поддерживает ли целевая система программное создание учетных данных? Проверьте, есть ли у вашей базы данных или облачного провайдера API для создания временных пользователей или ролей.
  • Может ли ваше приложение обрабатывать истечение срока действия учетных данных? Если ваше приложение поддерживает долгоживущие соединения, вам нужна стратегия обновления учетных данных без разрыва соединений.
  • Запрашивают ли ваши пайплайны учетные данные по требованию? Динамические секреты работают лучше всего, когда каждый запуск пайплайна запрашивает свои собственные учетные данные, а не использует кэшированные.
  • Надежна ли ваша инфраструктура хранилища? Если хранилище выйдет из строя, никто не сможет запросить новые учетные данные. Планируйте обеспечение высокой доступности.
  • Проверили ли вы, каким пайплайнам действительно нужны динамические секреты? Некоторые пайплайны запускаются настолько редко, что статический секрет с коротким периодом ротации проще в управлении.

Конкретный вывод

Статические секреты с долгим сроком жизни создают брешь в безопасности, которая растет с каждым днем между ротациями. Динамические секреты закрывают эту брешь, делая учетные данные действительными только на время выполнения одной задачи. Плата за это — сложность: вам нужно хранилище, поддерживающее динамическое предоставление, приложения, работающие с короткоживущими учетными данными, и системы, способные создавать пользователей по запросу. Но для любых учетных данных, используемых в автоматизированном пайплайне или краткосрочном процессе, динамические секреты — это разница между утечкой, которая имеет значение, и утечкой, которая его не имеет.