Как упорядочить работу с секретами в Kubernetes с помощью хранилища секретов

от автора

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

Меня зовут Даниил Рахновский, я ведущий архитектор в Orion soft. В этой статье мы поговорим о том, почему опасно доверять секреты контейнерам, рассмотрим, как упорядочить работу с секретами в Kubernetes с помощью системы управления секретами и какие встроенные инструменты в этом помогают.

Проблемы с безопасностью из-за неосторожного обращения с секретами знакомы многим. Например, можно вспомнить инцидент Uber: в 2016 году злоумышленники получили доступ к приватному репозиторию, нашли access key и использовали его для доступа к данным миллионов пользователей и водителей. У Tesla в 2018 году исследователи обнаружили небезопасно сконфигурированную Kubernetes-консоль. Через нее злоумышленники получили доступ к облачным учетным данным и использовали ресурсы для криптомайнинга, что привело к масштабному криптоджекингу кластера.

Чтобы избежать подобных ситуаций, мы в Orion soft используем StarVault — инструмент для управления секретами на уровне всей контейнерной платформы Nova. Подробнее о том, как устроены эти решения, можно почитать здесь и здесь.

StarVault разворачивается не внутри Kubernetes, а как набор системных сервисов на виртуальных машинах управляющего контура Nova Container Platform. За счет этого хранилище секретов не работает как пользовательская нагрузка Kubernetes и не зависит от состояния Pod, пространств имен и пользовательской плоскости кластера. Для отказоустойчивости StarVault разворачивается в HA-схеме, а его жизненный цикл управляется средствами платформы. Встроенный PKI выдает сертификаты, а секреты компонентов Nova Container Platform хранятся непосредственно в StarVault.

Чтобы аутентификация проходила единообразно, StarVault подключается к корпоративному IdP и выступает OIDC-провайдером/брокером для сервисов платформы. Это позволяет централизованно нормализовать identity-информацию, claims, scopes и группы. При этом сами сервисы всё равно настраиваются как OIDC-клиенты StarVault и используют полученные данные для принятия решений об авторизации.

В выбранной схеме секреты не создаются как Kubernetes Secret и не попадают в etcd: приложение получает их напрямую из StarVault через CSI-том или инжектор. Это снижает поверхность атаки, но не отменяет защиту самого StarVault, токенов ServiceAccount, узлов Kubernetes и приложения после чтения секрета.

Инжекторы

Внутри контейнерной платформы мы используем два вида инжекторов:

  • Vault CSI

  • Banzai Webhook

Vault CSI монтирует секреты как tmpfs-том. Этот метод выбирают, когда приложение умеет читать секреты из файлов, а передавать их через переменные окружения не требуется.

Плюсы:

  • Источником секрета остается StarVault: секрет не создается как Kubernetes Secret и не сохраняется в etcd. В приложение он попадает через смонтированный tmpfs-том.

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

  • Для Vault CSI в типовой схеме используются методы аутентификации Kubernetes/JWT через токен ServiceAccount, связанный с Pod.

Минусы:

  • В базовой схеме CSI отдает секреты как файлы. Переменные окружения возможны только через дополнительную синхронизацию в Kubernetes Secret, что возвращает секрет в etcd и требует перезапуска Pod для обновления переменных окружения.

  • Меньше гибкости при передаче секретов в приложение по сравнению с Banzai/Bank-Vaults webhook.

  • CSI-подход не стоит использовать для крупных объектов или большого числа часто обновляемых секретов.

Banzai webhook — второй тип инжектора, который используется в случаях, если вам не подходит Vault CSI. Bank-Vaults mutating webhook изменяет PodSpec и добавляет механизм запуска через vault-env: приложение стартует через обертку vault-env, который во время запуска получает значения из StarVault и подставляет их в окружение процесса. Это не sidecar-паттерн в классическом смысле: секреты не рендерятся постоянным Vault Agent sidecar’ом, а подставляются на старте процесса.

Плюсы:

  • Универсальность. Можно интегрировать любое приложение, потому что инжектор не меняет структуры кода;

  • Поддерживаются методы аутентификации Kubernetes и JWT.

  • Простая интеграция с помощью аннотаций. 

Нюансы:

  • При массовых развертываниях увеличивается задержка на этапе admission

  • Изменение PodSpec происходит на этапе admission при создании или изменении Pod: webhook изменяет PodSpec и настраивает запуск контейнера через vault-env. Если в этот момент webhook недоступен, результат зависит от failurePolicy и timeout. Получение самих значений из StarVault происходит уже при старте контейнера через vault-env, поэтому недоступность StarVault на этом этапе может привести к ошибке запуска приложения. Изменение секрета в хранилище само по себе не обновляет переменные окружения внутри уже запущенного процесса; для этого нужен перезапуск, reloader или другой механизм обновления.

Центральный PKI

Третий компонент системы работы с секретами — это PKI. Мы специально не делали для этого отдельное решение. Просто взяли StarVault и развернули в нем контур PKI. 

Базовая рекомендуемая схема — offline Root CA и online Intermediate CA в StarVault.
Размещение общекорпоративного Root CA внутри StarVault допустимо только как осознанное исключение и требует отдельного описания защиты ключей, unseal-процедур, аудита, резервного копирования, DR и регламента доступа.

Такая схема интеграции PKI дает сразу несколько преимуществ: 

  • cert-manager отвечает за декларативное управление жизненным циклом сертификатов в Kubernetes: создает запросы на выпуск, следит за сроками действия сертификатов и обновляет их в кластере. StarVault при этом остается центром выдачи сертификатов: в нем хранятся роли, политики выпуска, параметры TTL, настройки CRL/OCSP и аудит операций PKI.

  • Меньше отдельных компонентов для эксплуатации: PKI работает через тот же API и тот же операционный контур.

Минусы:

  • При большом числе выданных/отозванных сертификатов растут метаданные PKI и CRL. Для таких сценариев нужно заранее проектировать TTL, CRL/OCSP, бэкенд хранения, резервное копирование и политику ротации;

  • Ресурсная нагрузка: при росте количества запросов на выдачу или отзыв сертификатов Vault будет потреблять больше CPU, поэтому эти ресурсы нужно закладывать заранее.

  • Узкая функциональность UI. В StarVault в основном все делается через API. Это же касается и сертификатов: UI позволяет посмотреть информацию о сертификате и отозвать его, если это необходимо. Все остальное делается через API.

  • Секреты и PKI оказываются в одном операционном контуре и частично в одной точке отказа. Поэтому HA, резервное копирование и восстановление, аудит, unseal-процедуры и DR нужно проектировать заранее.

Как жить в динамической инфраструктуре?

На уровне одного кластера схема выглядит достаточно просто: есть StarVault, есть рабочие нагрузки, есть механизмы доставки секретов через CSI или инжектор, есть PKI и OIDC-интеграции. Но в реальной инфраструктуре редко все заканчивается одним кластером.

Когда команд, сервисов и окружений становится больше, инфраструктура начинает жить динамически. Пользователи запрашивают новые среды, платформенная команда готовит типовые шаблоны, а кластеры Nova Container Platform или автономные Kubernetes-кластеры могут создаваться и сопровождаться через единый управляющий контур. Это уже не задача «как выдать секрет в один Pod», а задача управления секретами, доступами и политиками на уровне множества кластеров и окружений.

Для таких сценариев мы используем HyperDrive — GitOps-платформу для управления жизненным циклом инфраструктуры. HyperDrive не заменяет Nova Container Platform, Kubernetes, StarVault, GitLab или платформу виртуализации. Его задача — связать эти компоненты в единый управляемый процесс: от выбора шаблона и создания кластера до доставки конфигураций, секретов и платформенных компонентов.

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

В HyperDrive StarVault работает по модели 1+N. Один основной StarVault находится внутри управляющего контура HyperDrive и используется как центральное хранилище секретов платформы. Для каждого кластера Nova поднимается отдельный локальный StarVault: это может быть как кластер, общий для нескольких команд, так и выделенный кластер, развернутый под конкретную инфраструктурную архитектуру.

Основной StarVault остается источником правды для секретов, которыми управляет HyperDrive. Локальные StarVault-инстансы в кластерах Nova используются для доступа приложений к секретам во время работы и получают только те секреты, политики и настройки доступа, которые нужны конкретному кластеру. Такой подход позволяет не тянуть все обращения приложений в центральный контур HyperDrive и одновременно сохранять централизованное управление секретами.

Важно, что локальный StarVault в кластере Nova — это не полная копия центрального хранилища. В него доставляются только выбранные пути KV v2 и только в рамках заданной политики синхронизации. Это снижает зону влияния возможной ошибки или компрометации: кластер получает доступ к тем секретам, которые нужны его приложениям, а не ко всему хранилищу платформы.

За управление жизненным циклом секретов отвечает управляющий контур HyperDrive. Он хранит метаданные секрета: идентификатор, путь в хранилище, точку монтирования, тип, область применения, владельца, статус и параметры синхронизации. Значение секрета при этом не хранится в базе управляющей системы и не рендерится в GitOps-манифесты. Само значение секрета хранится в StarVault KV v2.

StarVault-wrapper в этой схеме выступает плоскостью выполнения для работы с Vault-инстансами. Он регистрирует кластеры и локальные StarVault-инстансы, настраивает целевые пути синхронизации, копирует выбранные KV v2-секреты из основного StarVault в локальные StarVault-инстансы, а также создает политики доступа и роли аутентификации Kubernetes для приложений.

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

Когда приложение в Kubernetes должно получить доступ к секрету, StarVault-wrapper создает минимально необходимые политики доступа Vault и роли аутентификации Kubernetes. Эти роли привязываются к конкретным пространствам имен и ServiceAccount, поэтому приложение получает доступ только к тем путям, которые ему действительно нужны. В GitOps при этом остаются ссылки, идентификаторы и параметры доступа, но не сами значения секретов.

Такой подход удобен для динамической инфраструктуры: новый кластер можно создать через HyperDrive по заданному шаблону, связать с локальным StarVault, применить нужные политики синхронизации и довести доступы до требуемого состояния автоматически. Командам не нужно вручную переносить секреты, заводить политики доступа в каждом Vault-инстансе и проверять, что значения не утекли в GitOps.

При этом синхронизацию нельзя путать с резервным копированием. StarVault-wrapper синхронизирует только явно выбранные пути KV v2 и не заменяет резервное копирование, восстановление и процедуры аварийного восстановления самого хранилища. Основной StarVault остается источником правды для управляемых секретов, а локальные изменения на синхронизируемых путях ограничиваются политиками доступа. Это позволяет избежать конфликтов записи и предсказуемо восстанавливать локальные StarVault-инстансы до последней успешно зафиксированной версии.

В результате HyperDrive управляет не набором разрозненных Vault-инсталляций, а целой моделью доставки секретов: основной StarVault хранит значения секретов и остается источником правды, локальные StarVault-инстансы обслуживают приложения в кластерах Nova, а StarVault-wrapper связывает эти уровни между собой и приводит доступы к нужному состоянию.

Заключение

Система управления секретами позволяет решить многие задачи в сфере управления секретами и организации безопасного доступа как на небольших, так и на масштабных территориально-распределенных инсталляциях. Если у вас уже есть опыт работы со StarVault или остались вопросы по работе компонентов, ждем в комментариях. 

ссылка на оригинал статьи https://habr.com/ru/articles/1051424/