Модуль доступен только в Deckhouse Enterprise Edition.

Модуль secrets-store-integration реализует доставку секретов для приложения в Kubernetes-кластерах путем подключения секретов, ключей и сертификатов, хранящихся во внешних хранилищах секретов.

Секреты монтируются в модули в виде тома с использованием реализации драйвера CSI. Хранилища секретов должны быть совместимы с API-интерфейсом Hashicorp Vault.

Доставка секретов в приложения

Доставить секреты в приложение из vault-совместимого хранилища можно несколькими способами:

  1. Пользовательское приложение само обращается в хранилище. Рекомендация: Это наиболее безопасный вариант, но требует модификации приложений.

  2. В хранилище обращается приложение-прослойка, а ваше приложение получает доступ к секретам из файлов, созданных в контейнере. Рекомендация: Если возможности модифицировать приложения нет — используйте этот вариант. Он менее безопасный, потому что секретные данные хранятся в файлах в контейнере, но проще в реализации.

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

Рекомендация: Если нет возможности читать из файлов, можно использовать этот вариант, но он не безопасен. При таком подходе секретные данные хранятся в Kubernetes (а так же в etcd и, следовательно, потенциально могут быть прочитаны на любом узле кластера).

Приложение Механизм CSI Инжектор vault-agent Секреты Kubernetes
Потребление ресурсов Не меняется Два пода на каждую ноду (daemonset) По одному агенту на каждый под (sidecar) Одно приложение на кластер (deployment)
Как приложение получает данные? Напрямую из хранилища секретов
  • Из дискового тома (как файл)
  • Из переменной окружения
Из дискового тома (как файл)
  • Из дискового тома (как файл)
  • Из переменной окружения
Где хранится в Kubernetes? Не хранится Не хранится Не хранится Хранится в Secrets
Статус Реализовано Реализовано *Не будет реализовано Планируется

*Поддержка отсутствует и не планируется, поскольку этот вариант не имеет преимуществ перед использованием механизма CSI.

Вариант №1: Получение секретов самим приложением

Статус: Наиболее безопасный вариант. Рекомендован к использованию, если есть возможность модификации приложений.

Приложение обращается к API Stronghold и запрашивает необходимый секрет по HTTPS протоколу с использованием токена авторизации (токен из SA).

Плюсы:

  • Секрет, полученный приложением, нигде не хранится, кроме как в самом приложении, нет опасности что он будет скомпрометирован в процессе передачи

Минусы:

  • Требует доработки приложения для возможности работы со Stronghold
  • Требует повторения реализации доступа к секретам в каждом приложении, и в случае обновления библиотеки - пересборки всех приложений
  • Приложение должно поддерживать TLS и проверку сертификатов
  • Нет кэширования, при перезапуске приложение нужно повторно запросить секрет напрямую из хранилища

Вариант №2: Доставка секретов через файлы

Механизм CSI

Статус: Безопасный вариант. Рекомендован к использованию, если отсутствует возможность модификация приложений.

При создании подов, запрашивающих тома CSI, драйвер хранилища секретов CSI отправляет запрос к Vault CSI. Затем Vault CSI использует указанный SecretProviderClass и ServiceAccount пода для получения секретов из хранилища и монтирования их в том пода.

Инъекция переменных окружений:

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

Пример на bash:

bash -c "for file in $(ls /mnt/secrets); do export  $file=$(cat /mnt/secrets/$file); done ; exec my_original_file_to_startup"

Плюсы:

  • Всего два контейнера с прогнозируемыми ресурсами на каждой ноде для обслуживания системы доставки секретов в приложения.
  • Создание ресурсов SecretsStore/SecretProviderClass уменьшает количество повторяемого кода по сравнению с другими вариантами реализации vault agent.
  • Есть возможность при необходимости создавать копию секрета из хранилища в виде секрета kubernetes.
  • Секрет извлекается из хранилища драйвером CSI на этапе создания контейнера. Это означает, что запуск подов заблокируется до тех пор, пока секреты не будут прочитаны из хранилища и записаны в том.

Справочно: Инжектор vault-agent

Статус: Не имеет плюсов в сравнении с механизмом CSI. Поддержка отсутствует и не планируется, поскольку этот вариант не имеет преимуществ перед использованием механизма CSI.

При создании пода происходит мутация, которая добавляет контейнер с vault-agent. Агент обращается к хранилищу секретов, извлекает их, и помещает в общий том на диске, к которому может обратиться приложение.

Минусы:

  • Для каждого пода нужен сайдкар, который так или иначе потребляет ресурсы. Представим кластер, в котором 50 приложений, каждое имеет от 3 до 15 реплик. Так как для сайдкара с агентом нужно выделить пусть и не большие, но ресурсы cpu и memory, в сумме на кластер это может получиться. 50mcpu + 100Mi на все приложения в сумме десятки ядер и десятки гигабайт ОЗУ.
  • Так как мы мониторим метрики с каждого контейнера, с таким подходом мы получим х2 метрик только по контейнерам.

Вариант №3: Доставка секретов через механизмы Kubernetes

Статус: Не безопасный вариант, не рекомендован к использованию. Поддержка отсутствует, но планируется в будущем.

Этот метод интеграции, который реализует оператор секретов Kubernetes с набором CRD, отвечающих за синхронизацию секретов из Vault в секреты Kubernetes.

Минусы:

  • Секрет находится и в хранилище секретов, и в секрете Kubernetes, то есть доступен через API Kubernetes, а так же в etcd, а значит потенциально может быть считан на любом узле кластера или извлечён из бэкапа etcd. Нет возможности не хранить данные в секретах kubernetes.

Плюсы:

  • Классический способ передачи секрета в приложение через environment variables - достаточно подключить секрет kubernetes.