Как стать автором
Обновить
2298.58
МТС
Про жизнь и развитие в IT

Наш путь delivery of secrets: как мы пришли к связке Bank-Vaults и Vault Secret Operator

Уровень сложностиСредний
Время на прочтение7 мин
Количество просмотров1.5K

Привет, Хабр! Меня зовут Натиг Нагиев, я Devops-инженер в МТС Диджитал.

На нашем проекте мы обеспечиваем авторизацию внешних клиентов в продуктах МТС. Это Mission Critical система, где мы оптимизировали и гарантировали доставку секретов в контейнеры с микросервисом, избавлялись от дополнительных рабочих нагрузок и исключали внешние зависимости. В прошлом материале я сравнил разные инструменты, которые мы перебрали, а в этом расскажу про наше итоговое решение — связку Bank-Vaults и Vault Secrets Operator.

Что мы используем

Bank-Vaults

В самой документации этот инструмент назван «швейцарским армейским ножом» для Vault. Он позволяет автоматизировать рутинные задачи: распечатывать кластера, автоматически обновлять токены, задавать такие первоначальные настройки, как методы аутентификации, политики, аренды и так далее.

С помощью этого инструмента мы:

  • Решаем проблему с автоматизацией распечатывания кластера Vault (средствами laC). Он устраняет проблему ручного создания Opaque Secret в Kubernetes, который хранит в себе Unseal токены для быстрого и автоматического распечатывания кластера

  • Используем протокол Raft в качестве бэкенд хранилища. Bank-Vault позволяет быстро восстанавливать кластера в случае падения Raft. Конфигурация с Raft описана манифестами в helm чарте и раскатывается дополнительно с помощью ArgoCD. Это позволяет быстро передеплоить Vault-кластер с Raft без использования внешних зависимостей в качестве storage backend, как у нас это было в связке с Consul.

  • Автоматизируем изменения опций Vault (средствами laC). Доставляем вместе с процессом развертывания кластера Vault начальные параметры, которые сразу необходимо задать в дефолтной конфигурации

Vault Secrets Operator

Как понятно из названия, это kubernetes-оператор, который позволяет синхронизировать в Kubernetes Opaque Secrets секреты из Vault. C ним не нужно подключать внешние зависимости, как это было с Vault CSI Provider, где используются CSI хранилища.

С его помощью мы:

  • Больше не описываем каждый секрет в values файлах микросервисов. А вот в CSI Provider маппинг каждого секрета нужно описывать вручную.

  • Ушли от монтирования секретов в файловую систему в качестве volume/volumeMounts, так как все наши сервисы идентичны по функциональности и могут забирать секреты из переменных окружения.

  • Отказались от использования CSI. Vault Secrets Operator решил нам проблему, связанную с внешними зависимости в качестве CSI хранилищ.

Настройка Bank-Vaults

С помощью Bank-Vaults мы автоматизировали доставку токенов в Opaque Secrets средствами IaC. Если с кластером Vault что-то произойдет, то быстрее и проще будет переразвернуть кластер, так как уже есть Opaque Secret с Unseal токенами и сам Vault кластер деплоится чартом Bank-Vaults с помощью ArgoCD.

Пример Opaque Secret „vault-unseal-keys“
Пример Opaque Secret „vault-unseal-keys“

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

Bank-Vaults позволяет включить или изменить некоторые дефолтные конфигурации сразу при развертывании Vault-кластера. В разделе External Config указываем метод авторизации, в нашем случае Kubernetes Auth, настраиваем KV Secret Engine версии 2, а также тут есть важный момент: если ранее мы вручную настраивали команду vault auth tune для изменения времени аренды секретов, то теперь директива auth.type.roles.ttl настраивает эту опцию на 30 секунд сразу при развертывании.

Хочу подробнее остановиться на конфигурации Unseal. В ней указывается общее количество Unseal-токенов, secretShares — в нашем случае их 5 и количество токенов для распечатывания кластера, secretThreshold — у нас их 3. Важным элементом является зарезервированный kubernetes.secretNamespace, который формирует как раз Opaque Secret vault-unseal-keys, хранящий в себе root- и unseal-токены при условии хранения этих токенов в Kubernetes.

Команда сайдкарного контейнера, отвечающего за начальное распечатывание кластера Vault, запускается с одной из опций --k8s-secret-name. Этой опции в качестве аргумента передается vault-unseal-keys - имя Opaque Secret. Соответственно, эта команда парсит секрет на наличие unseal-токенов для распечатывания кластера.

Выглядит команда следующим образом:

Итак, с помощью новой конфигурации мы настроили автоматизацию средствами IaC и смогли минимизировать ручные операции сразу после развертывания кластера. Тем не менее оставалась нерешенной проблема периодической недоступности CSI-хранилищ, и мы стали искать новые варианты оптимизации и ускорения процесса доставки секретов в контейнеры с микросервисами.

Vault Secrets Operator

Этот инструмент мы взяли в работу сразу после выхода его стабильной версии v0.1.0 от 12 июня 2023 года. У него есть свой helm chart, с помощью которого он устанавливается поверх уже развернутого средствами Bank-Vaults кластера Vault:

helm upgrade --install vault-secrets-operator ./vault-secrets-operator -f values.yaml --create-namespace -n vault-secrets-operator

После установки создаются новые CRD (Custom Resource Definitions), среди них для нашего кейса используются VaultConnection, VaultAuth, VaultStaticSecret. Разберем их подробно:

  • VaultConnection отвечает за подключение. В нем указывается адрес кластера Vault. В данном случае это внутренний адрес, так как кластер разворачивается в Kubernetes. Также в нем можно дополнительно указать разные опции, например skipTLSVerify для пропуска валидации TLS:

  • VaultAuth описывает методы авторизации и их опции. Здесь в директиве VaultConnectionRef указываем название используемого подключения:

  • VaultStaticSecret отвечает за то, какие именно секреты мы забираем из Vault. В части spec.destination указывается, нужно ли создавать соответствующий результирующий Opaque Secret и, если да, то под каким именем. Также указываем точку монтирования секрета, его тип и по какому пути забирать секрет из Vault. И прописываем ссылку на VaultAuth, чтобы VaultStaticSecret смог забрать нужные секреты, использовав правильный метод авторизации:

Далее в values-файлах единого helm chart для всех микросервисов мы указываем, создавать ли эти три CRD-ресурса и, если да, то с какими опциями. Данные 10 строк вместе с темплейтами генерируют VaultConnection, VaultAuth, VaultStaticSecret для каждого микросервиса:

Если кратко и схематично, то выглядит это следующим образом:

Здесь также представлена вырезка из нашего values-файла со способом доставки секретов в переменные окружения контейнера с микросервисом
Здесь также представлена вырезка из нашего values-файла со способом доставки секретов в переменные окружения контейнера с микросервисом

С приведенными манифестами и конфигурациями можно ознакомиться в репозитории на Github.

Чем же хорош и плох Vault Secrets Operator

Плюсы этого инструмента:

  • Автоматизация доставки секретов: оператор автоматически извлекает секреты из Vault и преобразует их в Kubernetes Secrets, что упрощает процесс доставки и обновления секретов.

  • Интеграция с Kubernetes: применение стандартных примитивов Kubernetes, то есть Opaque Secrets, облегчает работу с секретами и снижает порог входа для использования Vault.

  • Автоматическое обновление секретов: он самостоятельно отслеживает изменения в Vault и обновляет Kubernetes Secrets, актуализируя секреты без ручного вмешательства разработчиков.

  • Масштабируемость: Vault Secrets Operator может управлять секретами для множества приложений и пространств имен, что делает его удобным для масштабируемых кластеров.

Из недостатков мы выделили для себя пока один, но он достаточно серьезный. Несмотря на то, что со стороны Vault обеспечивается высокая степень безопасности хранения секретов, чувствительные данные в итоге сохраняются в Kubernetes почти в открытом виде в качестве Opaque Secrets (base64 encoding).

Решаем проблему открытого хранения секретов в Kubernetes

Мы сейчас рассматриваем решения для шифрования секретов или доставки их в микросервисы, минуя Opaque Secrets, но пока они не внедрены из-за недостаточной зрелости или неудобства в наших кейсах.

Vault Response Wrapping Tokens

Он позволяет доставлять чувствительные данные, минуя такие абстракции Kubernetes, как Secrets, ConfigMaps:

Схема самого известного кейса использования wrapping token — метода авторизации AppRole, использующего role_id и secret_id
Схема самого известного кейса использования wrapping token — метода авторизации AppRole, использующего role_id и secret_id

Из его минусов можно отметить:

  • необходимость поддерживать функциональность в приложениях;

  • сложность масштабирования при большом количестве реплик;

  • необходимость автоматизации доставки wrapping token в микросервис.

Vault KMS Plugin

Это сравнительно новый инструмент, у которого есть несколько важных плюсов:

  • Не требуются внешние интеграции, так как используется нативный Transit Secret Engine от Vault.

  • Объекты вроде Secrets и ConfigMap шифруются прямо в etcd.

  • Так как он развертывается как static pod на control plane узлах или на тех узлах, где запущен kube-apiserver, то во взаимодействии между vault-kms-plugin и kube-apiserver отсутствуют лишние абстракции. Плагин по сути создает обычный Unix сокет и получает запросы шифрования через этот сокет от kube-apiserver.

Недостатки:

  • Настройка требует вмешательства в control plane кластера Kubernetes, а также не стоит забывать про настройки со стороны Vault c использованием Transit Key.

  • Если потерять или пересоздать KMS-ключ, Vault KMS Plugin не сможет дальше расшифровать и получить секреты.

Bank-Vaults Mutating Admission Webhook

Сейчас мы считаем этот инструмент самым подходящим для решения проблемы безопасного хранения секретов в Kubernetes. Он обходит механизм Kubernetes Secrets, внедряя секреты, полученные из Vault, прямо в pod. Mutating Webhook внедряет исполняемый файл vault-env в поды в качестве Init Container и может запрашивать секреты из Vault через аннотации и специальные переменные среды, считывая значения этих переменных непосредственно из Vault.

Работа инструмента с аннотациями напоминает Vault Agent Injector. Но Mutating Webhook удобнее и проще, так как отсутствует темплейтинг и своеобразный синтаксис, а также режим работы sidecar-less. По другим пунктам для сравнения можно пройтись в официальной документации.

Пример манифеста Deployment с подключением аннотаций и env для работы с Bank-Vaults Mutating Webhook
Пример манифеста Deployment с подключением аннотаций и env для работы с Bank-Vaults Mutating Webhook

Для наших задач он подходит по нескольким причинам:

  • Мы уже используем Bank-Vaults, и Mutating Webhook является частью их стека.

  • Это простое решение, которое применяет только аннотации и переменные окружения.

  • Данные не сохраняются на диске или в etcd — все секреты хранятся in-memory и доступны только процессу, который их запросил.

  • Отсутствует постоянное соединение с Vault, что влияет на нагрузку в Kubernetes, то есть sidecar-less режим.

  • Токен Vault, используемый для чтения секретов, удаляется из памяти перед запуском контейнера с микросервисом, минимизируя риск утечки.

Если вам интересен Mutating Webhook, то вот полезные ссылки про него:

С манифестами и командами для внедрения Bank-Vaults Mutating Webhook можно также ознакомиться на Github.

Нет предела совершенству

На текущем этапе связка Vault Secrets Operator и Bank-Vaults решает большинство наших проблем. Остается одна — хранение секретов почти в прозрачном виде, так как Opaque Secrets предусматривает из всей своей безопасности только энкодинг в base64, а все мы с вами знаем насколько "безопасна" эта безопасность =).

Мы решаем эту проблему защитой на уровне кластеров: они находятся в закрытом контуре и защищены на нескольких уровнях. При этом на рынке уже есть решения для шифрования или передачи секретов в обход Kubernetes Opaque Secrets: Vault Response Wrapping Tokens, Vault KMS Plugin, Bank-Vaults Mutating Admission Webhook. Возможно, для ваших задач они окажутся подходящим решением. Что же, на этом все. Желаю вам успехов и безопасных деплоев!

Теги:
Хабы:
Всего голосов 14: ↑14 и ↓0+16
Комментарии7

Полезные ссылки

7 ошибок, из-за которых сервисы кибербезопасности не дадут результата

Время на прочтение7 мин
Количество просмотров1.3K
Всего голосов 6: ↑6 и ↓0+7
Комментарии0

Зумеры не просто слушают — они хотят, чтобы их слушали. Как баг изменил наш взгляд на продукт

Время на прочтение6 мин
Количество просмотров2.4K
Всего голосов 19: ↑18 и ↓1+19
Комментарии10

Бьем автоматизацией по ручной работе с данными: как мы избавились от рутины с ML-моделями

Уровень сложностиПростой
Время на прочтение7 мин
Количество просмотров5.4K
Всего голосов 27: ↑26 и ↓1+27
Комментарии4

Наша кузница кадров: как мы обучаем и помогаем строить карьерный трек инженеров поддержки

Время на прочтение8 мин
Количество просмотров953
Всего голосов 12: ↑11 и ↓1+14
Комментарии0

Миссия выполнима: стандартизировать производственный процесс в крупной компании и учесть запросы всех продуктовых команд

Время на прочтение6 мин
Количество просмотров791
Всего голосов 4: ↑4 и ↓0+7
Комментарии0

Информация

Сайт
www.mts.ru
Дата регистрации
Дата основания
Численность
свыше 10 000 человек
Местоположение
Россия