Внедрение HashiCorp Vault в OpenShift
При развертывании Vault в кластере OpenShift с помощью Kustomize убедитесь, что Vault настроен на работу в высокодоступном режиме (несколько реплик) и использует надежное хранилище данных (например, Integrated Storage (Raft) или внешний backend). Следует включить аудит в Vault для отслеживания всех операций (например, настроить audit device на файл или syslog) – это позволит позже анализировать, кто и когда получал доступ к секретам. Также важно учесть особенности безопасности OpenShift: контейнер Vault и связанного вебхука (injector) должны удовлетворять политикам безопастности (например, runAsNonRoot, запрет привилегий и т.д.), иначе OpenShift может блокировать их запуск .
Инициализация Vault должна проводиться в контролируемых условиях: при первом запуске vault operator init сгенерирует ключи разблокировки (unseal keys) и root-токен. Рекомендуется задать достаточное количество ключей и порог разблокировки (например, 5 ключей, 3 из которых нужны для unseal) и распределить ключи между надёжными держателями. HashiCorp рекомендует PGP-шифрование ключей и root-токена при инициализации– Vault позволяет это сделать флагами команды init – чтобы каждый ключ был зашифрован открытым ключом получателя . Храните шифрованные ключи в безопасных местах (например, офлайн-хранилище, защищённые секреты в внешних системах) и периодически проводите «учения» по ручному unseal (раз в квартал) , чтобы увериться, что процесс доступен нескольким операторам и отработан. После начальной настройки root-токен следует изъять из обращения: в идеале, отозвать его (revoke) или по крайней мере сохранить офлайн и использовать только в чрезвычайных ситуациях. Для повседневных задач создайте отдельные политики и токены с ограниченными правами вместо использования всесильного root. Это уменьшит риск компрометации суперпользовательского доступа.
Авто-unseal: Для увеличения отказоустойчивости и устранения ручных операций рекомендуется настроить автоматическое распечатывание Vault. Vault поддерживает авто-unseal с использованием внешних KMS/HSM: например, облачных KMS (AWS KMS, Google Cloud KMS, Azure Key Vault и т.д.) либо аппаратного модуля безопасности (HSM) . В этом случае мастер-ключ (root key) шифруется и хранится в надёжном внешнем хранилище, а при старте Vault запрашивает у него расшифровку ключа для автоматического разблокирования . Авто-unseal значительно снижает операционную сложность (не нужно вручную вводить ключи при каждом запуске/перезапуске Vault) . Однако важно защитить сами credentials для доступа к KMS/HSM – например, минимизировать права доступа к ключу KMS только для Vault и включить аудит обращений к нему . Также помните, что при авто-unseal вместо обычных unseal-ключей будут сгенерированы ключи восстановления (recovery keys), которые требуются для некоторых операций (например, генерации нового root-токена) . Если внешний механизм авто-unseal выйдет из строя или ключ будет утерян, восстановить доступ к Vault будет сложно, поэтому обеспечьте резервирование или возможность manual unseal на случай отказа авто-unseal механизма .
Интеграция приложений OpenShift с Vault
Одной из ключевых задач является безопасная доставка секретов из Vault в приложения, работающие в OpenShift. Рассмотрим три основных подхода: Vault Agent Sidecar Injector, Secrets Store CSI Driver (Vault CSI Provider) и External Secrets Operator (ESO). Ниже приведено сравнение этих подходов:
Подход 1. Vault Agent Sidecar Injector
Механизм работы
Mutating-webhook Vault (k8s-injector) перехватывает создание Pod и добавляет в него:
- initContainer, который выполняет аутентификацию во Vault по JWT сервис-аккаунта;
- sidecar-контейнер Vault Agent, который получает секреты из Vault и сохраняет их в общем emptyDir (tmpfs) либо выставляет как переменные окружения. Сами значения секретов никогда не сохраняются в etcd кластера.
Поддержка динамических секретов
Да. Sidecar может автоматически продлевать срок жизни токена и обновлять файлы с секретами до истечения TTL.
Преимущества
- Секреты остаются только внутри Pod; каждый запрос фиксируется в audit-логе Vault.
- Поддерживаются все движки Vault (KV, DB, PKI, Transit и т.д.).
- Приложению не нужно знать о Vault — достаточно прочитать файл или переменную.
Ограничения
- Требуется установка injector-webhook в кластер.
- В манифестах приходится прописывать аннотации Vault (путь секрета, шаблон, права доступа).
- Приложение должно уметь перечитывать файл или реагировать на сигнал, если секрет обновился.
Подход 2. Secrets Store CSI Driver + Vault CSI Provider
Механизм работы
CSI-драйвер монтирует в Pod том (volume). Содержимое — файлы, полученные из Vault по описанию ресурса SecretProviderClass. При желании том можно синхронизировать в обычный Secret Kubernetes.
Поддержка динамических секретов
Да. Драйвер периодически перечитывает значения из Vault; файлы внутри Pod обновляются без перезапуска контейнера.
Преимущества
- Стандартный механизм Kubernetes (CSI), легко подключать разные бэкенды.
- Секреты, как и в варианте с sidecar, не попадают в etcd (пока не включена опция sync = Secret).
- Унифицированный способ доставки файлов—сертификатов, конфигураций и т.п.
Ограничения
- Не поддерживает прямую инъекцию в переменные окружения.
- Требует DaemonSet CSI-драйвера на каждом узле; это добавляет точку отказа.
- Поддерживаются главным образом методы аутентификации Kubernetes Auth и JWT/OIDC.
Подход 3. External Secrets Operator (ESO)
Механизм работы
В GitOps-репозитории хранится объект ExternalSecret, ссылающийся на SecretStore/ClusterSecretStore. Оператор извлекает данные из Vault и создаёт/обновляет стандартный Secret в нужном namespace. Приложения используют этот Secret привычным способом.
Поддержка динамических секретов
Частично. ESO отслеживает изменения данных в Vault и обновляет Kubernetes Secret. Для краткоживущих (секунд-минут) секретов лучше применить sidecar или CSI, потому что перезапуск или релоад приложения может потребоваться.
Преимущества
- Разработчикам ничего менять не нужно — остаётся объект Secret.
- В Git-репозитории нет конфиденциальных данных: хранится только ссылка на путь во Vault.
- Поддерживаются разные источники (Vault, AWS Secrets Manager и др.) и методы аутентификации.
Ограничения
- Значения секретов сохраняются в etcd кластера (требуется шифрование etcd и контроль RBAC).
- Для динамических движков Vault (DB, PKI) автоматическая ротация не столь прозрачна.
- Нужна точная настройка RBAC и SecretStore, чтобы пользователи не смогли запросить «чужой» путь.
Практические рекомендации выбора
- Критичные или краткоживущие секреты (пароли БД TTL ≤ 1 час, краткосрочные сертификаты) — используйте Vault Agent Sidecar либо CSI Driver. Так значения не попадут в etcd, а ротация выполняется автоматически.
- Большинство приложений, ожидающих обычный Kubernetes Secret, особенно сторонние Helm-чарты, — разумно обслуживать через External Secrets Operator: GitOps-декларативность соблюдена, разработчики работают в привычной модели.
- В сложных кластерах допускается комбинированная схема: ESO по умолчанию, а для особо чувствительных workload-ов — sidecar/CSI. Такой баланс минимизирует усилия команд и одновременно обеспечивает высокий уровень безопасности.
Выбор подходящего способа интеграции. Каждый из перечисленных методов может успешно применяться в OpenShift, и нередко используются сразу несколько подходов в зависимости от типа приложений и секретов. Если ваша цель – минимизировать присутствие секретов в Kubernetes и обеспечить строгий аудит доступа через Vault, то Vault Agent Sidecar Injector или CSI Driver предпочтительнее, так как секреты хранятся только в памяти пода, а каждое обращение проходит через Vault (с логированием) . Vault Agent более гибок в поддержке разных секретов (динамические DB доступы, PKI) и умеет автоматически продлять их в фоне , поэтому в случаях динамических секретов (например, часто меняющиеся пароли, короткоживущие сертификаты) sidecar-агент – лучший выбор. С другой стороны, CSI удобен, когда приложения могут работать с файлами и вам нужен унифицированный подход через Kubernetes-механизмы volumes; он тоже не сохраняет секреты в etcd и поддерживает ротацию, но чуть сложнее в установке и сейчас ограничен аутентификацией через Kubernetes Auth.
Если же приоритет – максимальная простота для команд разработки и совместимость с существующими чарты/приложениями, то External Secrets Operator показывает себя очень хорошо: разработчики вообще не меняют способ получения конфигурации (они по-прежнему читают из Kubernetes Secret), а операторы могут управлять секретами в Vault и их версионирование через GitOps (в виде манифестов ExternalSecret). Этот подход особенно полезен, когда много сторонних Helm-чартов или продуктов, ожидающих секреты именно в Kubernetes Secret – вместо ручного переписывания этих чартов под Vault Agent, можно использовать ESO для автоматической выдачи секретов им . Кроме того, ESO вместе с Vault отлично вписывается в GitOps-процесс: никаких секретов в Git, автоматическое обновление конфигураций при изменении в Vault . Минус – потеря детализации аудита: после синхронизации в Secret само чтение секрета подом не проходит через Vault, так что Vault не узнает, когда и кто в Kubernetes прочёл секрет (это можно частично компенсировать аудитом Kubernetes API). В целом, рекомендуется сочетать подходы: критичные секреты, требующие максимальной строгости (например, динамические учётные данные к БД, ключи шифрования) – через прямую доставку из Vault (sidecar/CSI); менее чувствительные или используемые сторонними компонентами – через синхронизацию (ESO).
Хранение секретов в GitOps-подходе
При GitOps (управлении инфраструктурой через Git, в нашем случае с помощью Argo CD) важно избежать хранения открытых секретов в репозитории. Даже приватный репозиторий не гарантирует полной безопасности, поэтому применяют специальные механизмы:
- Sealed Secrets. Это подход, при котором секреты хранятся в Git в зашифрованном виде. Инструмент Sealed Secrets (от Bitnami) предоставляет контроллер, который содержит приватный ключ и может расшифровывать специальные объекты типа SealedSecret в реальный Secret. Команда разработчиков шифрует секреты публичным ключом кластера и коммитит зашифровки. В результате секреты хранятся в Git, но они недоступны в открытом виде – их может расшифровать только контроллер внутри кластера . Плюс данного метода в том, что он просто внедряется и совместим с любыми типами данных – в итоге в Git можно версионировать и ревьюить изменения секретов без раскрытия значений. Однако, Sealed Secrets по сути создают параллельное хранилище секретов, не связанное с Vault. При наличии Vault использование Sealed Secrets для рабочих секретов выглядит избыточным – лучше хранить секрет один раз в Vault, чем зашифрованную копию в Git. Кроме того, зашифрованные секреты статичны: чтобы обновить секрет (например, поменять пароль), нужно сгенерировать новый SealedSecret и закоммитить его – автоматическая ротация затруднена. Рекомендация: применять Sealed Secrets только для тех конфиденциальных данных, которые не подходят для хранения в Vault или должны быть изначально загружены до запуска Vault. Например, Sealed Secrets может пригодиться для безопасного хранения unseal-ключей Vault или первичного root-токена в GitOps (хотя лучше всё же не хранить их в кластере вовсе). Если же Vault уже развёрнут и используется, отдавайте предпочтение direct-вариантам (ESO, Vault Agent), а не запечатывайте его секреты обратно в Git.
- Внешние ссылки вместо значений. Лучший способ интеграции секретов с GitOps – не хранить значения секретов в Git репозитории вовсе, а хранить там лишь ссылки или шаблоны, указывающие, откуда секрет взять. Например, вместо того чтобы коммитить пароль к базе в YAML деплоя, вы можете поместить в деплой аннотацию Vault Agent
Injector: vault.hashicorp.com/agent-inject-secret-db_password: secret/data/prod/db#password
. Такая манифестация не раскрывает секрет (в Git хранится только путь), но при развёртывании пода Vault-agent сам подтянет значение . Аналогично, с External Secrets в Git хранится объект, где прописано, что “secret X нужно взять из Vault по пути kv/data/app/config”. Эти ссылки не чувствительны, их можно безопасно версионировать. Подход GitOps без секретов в Git повышает безопасность: «секреты есть, но их нет» – инфраструктура деплоится как обычно, а секретные значения подтягиваются в последнюю очередь из доверенного хранилища. Обратите внимание, что даже токен или пароль доступа к самому Vault не должны храниться в Git в открытом виде. Частая ошибка – вынести из манифестов приложения секреты, но при этом сохранить в репозитории credentials для доступа к Vault (например, GitOps-плагин с прописанным роль-ID и секрет-ID AppRole). Этот секрет тоже нужно вынести из Git. Решение – использовать для Argo CD/Kubernetes Kubernetes Auth метод Vault, чтобы аутентификация шла по сервисному аккаунту, а не по статическому токену . Например, External Secrets Operator можно настроить так, что он сам залогинится в Vault, предъявив JWT сервис-аккаунта (и Vault пустит его с определённой политикой) – никакого токена в Git не нужно. Для Argo CD Vault Plugin есть возможность аналогично использовать токен SA ArgoCD (если настроить RBAC Vault для SA argocd-repo-server). Таким образом, в репозитории остаются только несекретные ссылки, а все чувствительные данные хранятся либо в Vault, либо зашифрованы контроллером кластера. - Шаблонизация манифестов (Argo CD Vault Plugin, Helm Secrets и др.). Ещё один подход – оставить в Git “пустые места” для секретов, которые будут заполнены в процессе деплоя. Например, Argo CD Vault Pluginпозволяет в манифестах Kubernetes указывать шаблоны вида
${vault:secret/data/path#key}
– при синхронизации приложения ArgoCD подключает плагин, тот подтягивает нужные значения из Vault и подставляет их в итоговый YAML перед применением в кластер . Итоговый манифест (уже содержащий секрет) поступает в Kubernetes. Этот метод похож на внешние ссылки, но обработка происходит на стороне CI/CD. Плюсы: секретов нет в Git, команды могут использовать привычные Deployment/ConfigMap с переменными, и плагин сам их наполнит из Vault. Минусы: полученные секреты всё равно попадают в итоговый Kubernetes-манифест (например, плагин заполнит объект Secret с паролем) – то есть в etcd они окажутся в открытом виде . Кроме того, автообновления секретов нет – ArgoCD подтянет актуальные данные только при следующем sync/деплое. Если секрет в Vault изменился, а приложение не перезапускали, оно останется со старым значением. Таким образом, шаблонизация через плагин подходит для статических или редко меняющихся конфигураций. Аналогичный подход – использование утилит вроде Helm + SOPS, Kustomize с встроенным шифрованием (например, Mozilla SOPS шифрует секреты в Git, а при deploy CI расшифровывает и генерирует Secret). Эти варианты также требуют заботиться о ключах для расшифровки и не дают динамической ротации.
Рекомендации по GitOps: старайтесь проектировать манифесты приложений так, чтобы в них вместо явных секретных значений были ссылки на внешнее хранилище или шаблоны. В сочетании с Argo CD оптимальными выглядят две схемы:
- использовать External Secrets – в Git хранится CR, в Kubernetes появляется Secret, приложение его потребляет;
- использовать Vault Injector – в Git у Deployment манифеста только аннотации, в Kubernetes секрет вообще не сохраняется, приложение читает из файла.
Оба подхода исключают конфиденциальные данные из репозитория и автоматизируют доставку секретов. Если нужен мгновенный автоматический rollout при смене секрета – External Secrets Operator в комбинации с монтированием Secret как volume даст более предсказуемый результат (он обновит Secret и Kubernetes обновит файл в контейнере) . Vault Agent тоже способен обновлять файл, но реакции приложения придётся реализовать (например, ловить сигнал от агента или проверять таймстамп файла). В случае сертификатов TLS: хранить их удобно в Vault PKI, но к приложениям можно доставлять либо через Injector (файлы crt/key в pod), либо через ESO (синхронизировать в Secret типа tls). GitOps-подход позволяет зашить в манифесты только, например, ссылку на Vault PKI роль, а сам сертификат выпустится динамически. Итого: секреты никогда не должны “жить” в Git в открытом виде, вместо этого применяйте комбинацию Vault и специальных операторов/плагинов, чтобы секреты подтягивались на этапе деплоя или во время выполнения.
Разграничение доступа и аудит в Vault
При эксплуатации Vault в среде с множеством приложений, сервисов и пространств имён (namespaces) в OpenShift критически важно обеспечить корректное разграничение доступа к секретам и полноценный аудит всех операций.
Используйте политики Vault (ACL) для каждой службы/приложения. В Vault каждой учетной записи (токену, роли) можно привязать одну или несколько политик, определяющих, какие пути (secret paths) доступны на чтение/запись. Рекомендуется организовать хранилище Vault по принципу namespaces или префиксов для разных команд/приложений. Например, секреты приложения A хранить под префиксом kv/appA/*, а приложения B – под kv/appB/*. Создайте политики appA-policy, appB-policy и т.д., дающие доступ только к соответствующим префиксам. Тогда даже если токен одной службы утечёт, он не позволит прочитать чужие секреты.
Привязка Kubernetes service account к Vault-роли. Основной способ интеграции – Kubernetes Auth Method в Vault. Настройте аутентификацию Vault на ваш OpenShift (Vault требует URL API сервера и CA сертификат, а также токен Kubernetes для проверки JWT) . Затем для каждой группы приложений создайте Vault role, ограниченную Namespace и именем сервис-аккаунта. Например, можно привязать роль Vault к сервисному аккаунту default в namespace app и дать ей политику только на секреты этого приложения . Пример команды Vault: vault write auth/kubernetes/role/role-app bound_service_account_names=default bound_service_account_namespaces=app policies=app-policy ttl=1h
. После этого все поды в OpenShift, запущенные от SA default в ns app, смогут автоматически получать Vault-токен с политикой app-policy. В случае с Vault Agent Injector или CSI это происходит прозрачно: Vault Agent внутри пода сам обменяет JWT на токен Vault. При использовании External Secrets Operator – можно сконфигурировать SecretStore с методом kubernetes и указанием serviceAccount (либо он по умолчанию возьмёт SA оператора) . В итоге каждая сущность в кластере получает минимально необходимый доступ: приложение или оператор не сможет вычитать секреты, не разрешённые его политикой. Это реализует принцип наименьших привилегий.
Vault Namespaces (Enterprise) – если у вас Vault Enterprise, можно использовать изоляцию на уровне namespace внутри Vault, предоставляя разным командам “суб-ваулты” с собственными пространствами имен, политиками и auth-методами. Это добавляет сильную изоляцию (например, команды даже не видят пути секретов друг друга), но и усложняет управление. В open-source Vault таких namespace нет, поэтому имитируем изоляцию через названия путей и отдельные политики.
RBAC в Kubernetes и Argo CD. Помимо настроек в самом Vault, убедитесь, что в Kubernetes ограничены возможности злоупотребления. Например, если используете Vault Agent Injector, метаданные Pod могут раскрыть путь до секрета – не позволяйте обычным пользователям редактировать Deployment и вставлять произвольные vault-аннотации, иначе они могут попытаться внедрить чужие секреты. Решение – ограничить права на изменение манифестов только определённым pipelines/Argo CD приложениям и тщательно проводить код-ревью GitOps изменений. Аналогично, если применяется External Secrets Operator, настроить RBAC так, чтобы разработчики в namespace могли создавать ExternalSecret только со ссылкой на разрешённый SecretStore (иначе теоретически они могут попробовать указать чужой secretPath). К счастью, SecretStore обычно находится в том же namespace и можно контролировать кто может его менять. В Argo CD целесообразно настроить Projects и привязать каждое приложение к своему проекту, ограничив ему путь в репозитории и namespace развёртывания – это предотвращает ситуацию, когда один манифест из Git случайно развёртывается в чужой namespace.
Включите аудит в Vault. Vault позволяет включить audit devices (например, файл или socket), куда будет записывать каждое обращение: команду, путь, политику и т.д. Это следует сделать при инициализации (в конфиге Vault или через API). Впоследствии логи аудита Vault можно отправлять в SIEM или централизованную систему логирования для анализа. В сочетании с Kubernetes audit (если включён) вы получите полный след: какой под/SA запрашивал токен, под каким Vault-именем и что читал. Например, при использовании Injector и Kubernetes Auth в audit-логах Vault будет видно, что некто с именем сущности “kubernetes-sa:app:default” читает secret/app/credentials– таким образом, можно отследить использование секретов каждым приложением . Hабилитированный аудит также помогает выявлять подозрительную активность (например, множество неудачных попыток доступа). Не забывайте защищать сами аудиторские логи и ограничивать к ним доступ.
Использование Argo CD совместно с Vault
Argo CD как система CD в OpenShift (OpenShift GitOps) играет роль посредника, применяя манифесты из Git. Есть несколько вариантов интеграции Argo CD с Vault, каждый со своими плюсами:
- Плагин Argo CD Vault Plugin. Этот способ предполагает, что вы устанавливаете специальный бинарь-плагин в контейнер argocd-repo-server. Плагин на этапе рендеринга манифестов вытягивает секреты из Vault и подставляет их. Конфигурация плагина может быть задана глобально или на уровне приложения. Например, в argocd-cm можно прописать шаблон команд для обработчика argocd-vault-plugin. Сейчас поддерживается удобный sidecar-режим установки плагина (Argo CD >= v2.0) . Преимущества: секреты не хранятся в репозитории (только placeholders) , Argo CD автоматически подтягивает нужные данные во время sync. Это прозрачный процесс, не требующий изменений в самих приложениях. Недостатки: как отмечалось, подставленные секреты становятся обычными Kubernetes-объектами. Если плагин генерирует, к примеру, Secret манифест, то в etcd он будет в открытом виде . Кроме того, Argo CD по умолчанию использует один Vault-токен/роль на все приложения (от имени своего сервис-аккаунта или настроенного AppRole). Это означает, что при некорректной конфигурации один проект ArgoCD может запросить секреты, предназначенные для другого, – тут нужно аккуратно организовать либо несколько экземпляров ArgoCD, либо использовать vault namespacing/per-AppRole. В целом, Vault Plugin хорошо подходит в сценариях, где приложения ожидают секреты до деплоя (например, нужна шаблонизация ConfigMap/Deployment манифестов значениями из Vault). Но если требуется динамическая ротация без повторного деплоя, этот вариант уступает другим, так как ArgoCD не будет автоматически переподставлять изменившиеся значения (нужен новый sync).
- Встроенная интеграция через Vault Agent Injector. В этом случае Argo CD вообще не знает о Vault: он просто развертывает приложения с аннотациями для injector (как описано выше). Все необходимые компоненты (Vault, injector-webhook) уже работают в кластере. Argo CD применяет Deployment, MutatingWebhook перехватывает его и добавляет sidecar с агентом, который при запуске пода подтянет секреты. Преимущество – простота: не требуется никаких специальных настроек в ArgoCD, достаточно один раз развернуть vault-k8s injector в кластер и добавить нужные аннотации. С точки зрения GitOps, вы явно видите в YAML, какой секрет требуется приложению (путь в Vault указан в аннотации), а само значение в Git не попало. Разграничение в этом случае контролируется на уровне Vault Auth (разные сервис-аккаунты для разных приложений). Audit тоже максимальный – ArgoCD лишь создает Pod, а дальнейшее получение секрета фиксируется Vault (с указанием service account) . Недостатки: необходимо убедиться, что все команды разработки правильно используют аннотации и не пытаются облегчить себе жизнь, закоммитив секрет напрямую (код-ревью!). Также иногда Helm-чарты могут конфликтовать с неизвестными им аннотациями или Volume, добавленным webhook’ом – эти моменты надо учитывать в pipeline (тестировать манифесты). Ещё нюанс: поддержка горячей ротации секретов несколько сложнее – sidecar обновит файл, но приложение не узнает об этом без механизма отслеживания. В случае, когда это критично, можно добавить в Pod сайдкар, который будет слать сигнал приложению или перезапускать его при обновлении файла (есть open-source утилиты для этого).
- External Secrets Operator + Argo CD. Этот способ можно назвать наилучшим с точки зрения GitOps-принципов. Все, что нужно – описать в Git манифест SecretStore (как подключиться к Vault) и набор ExternalSecret для нужных значений. Argo CD применяет эти манифесты, после чего оператор самостоятельно свяжется с Vault и создаст Secrets. Полностью отсутствуют чувствительные данные в репозитории, при этом весь процесс декларативен (если удалить ExternalSecret из Git, ArgoCD уберет его из кластера, а оператор удалит Secret – состояние точно соответствует репо). External Secrets Operator также способен автоматически синхронизировать изменения, что важно для долгоживущих приложений: если секрет обновился, оператор обновит Secret, а затем можно либо перезапустить под, либо – если приложение умеет – обновить значение на лету . Разделение доступа при таком подходе достигается, как упоминалось, через раздельные SecretStore/ClusterSecretStore и Vault roles. Можно, например, задеплоить несколько ClusterSecretStore: один – с правами только на path команды A, другой – для команды B, и задать ExternalSecret в ns команды A ссылаться на первый store. Чужой namespace не сможет использовать не свой store из-за отсутствия RBAC прав. Минусы ESO+ArgoCD: появляется дополнительный слой (сам оператор), за состоянием которого нужно следить (но он довольно простой). И также – секреты возвращаются в etcd. Если требования безопасности организации запрещают хранение секретов в Kubernetes даже временно, то этот метод может не подойти. Однако на практике Kubernetes-secret используется в оперативной памяти узлов и может быть зашифрован в etcd, что при должной настройке кластера приемлемо.
Что лучше выбрать? С учётом использования Argo CD и потребностей в разделении и аудите, многие эксперты рекомендуют сочетание External Secrets Operator для большинства сценариев, а Vault Agent Injection – для отдельных случаев, требующих особой свежести секретов или отсутствия их в Kubernetes. В 2024 году практики GitOps показывают, что External Secrets Operator совместно с Vault – оптимальное решение для управления секретами: он полностью GitOps-совместим, не сохраняет секреты в репозитории и позволяет автоматизировать ротацию . При этом, благодаря Kubernetes Auth, можно настроить аудит и ограничения практически так же тонко, как с sidecar (просто аудит будет фиксировать вызовы от имени оператора или от имени service account на namespace) . Если же у приложения особые требования (например, секрет нужно обновлять ежеминутно, или он не должен вообще появляться в виде Kubernetes Secret), то Vault Agent Injector (vault-k8s) незаменим.
Вывод: используйте External Secrets Operator для большинства приложений – как более простой и масштабируемый путь в GitOps , а для высокочувствительных случаев – прямую доставку через Vault Agent или CSI. Во всех случаях придерживайтесь принципа наименьших привилегий и контролируйте как Vault, так и Kubernetes-уровень доступа, чтобы секреты каждого приложения были изолированы и аудитируемы. Это обеспечит безопасную и масштабируемую работу с секретами в OpenShift.
Источники: Использованы материалы HashiCorp и Red Hat по интеграции Vault с Kubernetes и GitOps, включая сравнение методов доступа к Vault , рекомендации по авто-unseal и распределению ключей , а также опыт сообщества в настройке Argo CD с Vault .