Hashicorp Vault — gcs + gcpckms

Управление секретами и почему это так важно для нас?

Привет! Меня зовут Евгений, я работаю на позиции Lead DevOps в EXANTE. В этой статье мы разберем жизненный опыт сетапа high availability Hashicorp Vault с gcp storage backend и auto unseal в k8s.

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

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

Мы решили сделать наш продукт cloud native, и для этого нужно было изменить подход к разработке и инфраструктуре, провести рефакторинг наших легаси сервисов, начать двигаться в сторону микросервисной архитектуры, разворачивать сервисы в cloud k8s, использовать managed ресурсы (redis, postgres).

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

Почему Hashicorp Vault?

У нас есть несколько причин:

  1. Нам нужен был готовый инструмент, который может изменить ситуацию с управлениям секретами в моменте без необходимости глобальных доработок кода наших приложений. Также этот инструмент должен иметь возможность интеграции с chef.

  2. Hashicorp Vault — наиболее популярный инструмент с необходимой функциональностью (хранение секретов, управление доступом к секретам, инъекция секретов в поды k8s, интеграция с chef, gitlab ci).

  3. Наличие практического опыта у наших devops инженеров в конфигурировании HA и unseal.

  4. Возможность в дальнейшем интегрировать в наш k8s кластер Secret injection webhook.

Где и в какой конфигурации мы разворачиваем Hashicorp Vault?

dee1d20e06713d2361d3d371e482a62c.png

Мы разворачиваем Hashicorp Vault в k8s кластере на отдельном нодпуле.

С точки зрения конфигурации, мы используем подход с автоматическим распечатыванием хранилища при помощи gcpckms в момент рестарта подов Hashicorp Vault. В качестве storage backend для хранения данных Hashicorp Vault мы используем Google Cloud Storage, так как это позволяет просто и дешево кластеризовать сервис Hashicorp Vault.

Почему нам так важен автоматический unseal?

d679a51e89c90ca4a3ec3f1ee1953be7.png

Здесь все довольно просто — на данный момент большая часть сервисов получает секреты в виде переменных окружения при помощи Vault Secret injection webhook, именно поэтому нам необходим автоматический unseal: без него мы потенциально столкнемся с недоступностью сервисов Hashicorp Vault и отсутствием возможности передать переменные окружения в сервисы при любых манипуляциях с подами (рестарт, новый релиз и т.д.)

Что необходимо иметь для настройки HA с gcs storage backend и gcpckms auto unseal?

  1. Сервисный аккаунт для Hashicorp Vault.

  2. GCS bucket.

  3. Keyring + cryptokey.

Мы создаем необходимые сущности при помощи terraform.

Подробнее про iam политики для сервисного аккаунта и про связку keyring и cryptokey gcpckms можно прочитать в официальной документации. 

Каким образом мы разворачиваем Hashicorp Vault в k8s?

В k8s кластере мы используем подход GitOps при помощи инструмента Flux CD. Соответственно все новые приложения деплоятся в кластер через репозиторий Flux CD. Мы не будем вдаваться в подробности использования GitOps в этой статье.
Для шифрования первичных секретов (необходимых для развертывания Hashicorp Vault) мы используем SOPS. SOPS — редактор зашифрованных файлов, поддерживающий форматы YAML, JSON, ENV, INI и BINARY и шифрующий с помощью AWS KMS, GCP KMS, Azure Key Vault, age и PGP. Мы используем age, и ключ для расшифровки находится в секретах k8s.


Мы конфигурируем Hashicorp Vault следующим образом:


— HA режим (3 реплики).

— GCS storage backend.

— Auto unseal при помощи gcpckms.

В первую очередь нам необходимо создать секрет с именем vault-gcs, положив в него наш сервисный аккаунт. Этот файл мы создаем по шаблону ниже и шифруем при помощи SOPS.

apiVersion: v1
kind: Secret
metadata:
    name: vault-gcs
    namespace: vault
type: Opaque
data:
    Vault_gcs_key.json: 


Для корректной работы Hashicorp Vault в указанной конфигурации необходимо пробросить в под файл с нашим сервисным аккаунтом и указать дополнительные переменные окружения. Таким образом, мы наполняем файл values.yaml:

server:
  enabled: true
  extraEnvironmentVars:
    GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/vault-gcs/vault_gcs_key.json
    GOOGLE_PROJECT: your-project
  extraVolumes:
  - name: vault-gcs
    path: /vault/userconfig
    type: secret

Далее мы продолжаем наполнять values.yaml. Важно корректно настроить конфиг HA для работы в несколько реплик и поддержки gcs storage backend + gcpckms unseal. В конечном итоге values.yaml выглядит следующим образом:

server:
  enabled: true
  extraEnvironmentVars:
    GOOGLE_APPLICATION_CREDENTIALS: /vault/userconfig/vault-gcs/vault_gcs_key.json
    GOOGLE_PROJECT: your-project
  extraVolumes:
  - name: vault-gcs
    path: /vault/userconfig
    type: secret
  ha:
    config: |
      ui = true
      listener "tcp" {
        address = "[::]:8200"
        cluster_address = "[::]:8201"
      }
      storage "gcs" {
        bucket     = "bucket-name"
        ha_enabled = "true"
      }
      seal "gcpckms" {
        project     = "gcp-project-name"
        region      = "global"
        key_ring    = "your-keyring"
        crypto_key  = "your-cryptokey"
      }
    enabled: true
    replicas: 3

Дополнительно в нашем helm chart используются настройки внутреннего ingress, но они довольно специфичные и для общего понимания не требуются. Помимо этого, мы отключаем использование vault-agent-injector, данные параметры можно настроить самостоятельно на основе примера в официальном helm-chart.

Установка в кластер производится при помощи Flux CD и полностью автоматизирована, используется официальный helm chart от hashicorp.

После успешной установки мы имеем три пода vault-0, vault-1, vault-2 в неймспейсе vault. Для успешного запуска сервиса достаточно выполнить команду:

kubectl exec -ti vault-0 -- vault operator init

В результате выполнения получаем root token и пять recovery keys. 

Настоятельно рекомендуем сохранить эти данные, так как их утрата является фатальной и фактически отрезает доступ к управлению Hashicorp Vault кластером.

Мы провели сравнительное тестирование производительности Hashicorp Vault с разными storage backend. Мы запускали его с postgresql, consul, aws s3, gcs. В наших тестах gcs был примерно в 10 раз медленнее, чем postgresql.


Поскольку для нас скорость отдачи секретов не критична и приоритетом является возможность удобного auto unseal, быстрой интеграции с storage backend — было принято решение использовать gcs.

Наш k8s работает в такой конфигурации с Hashicorp Vault два года, на текущий момент мы не встречали проблем в использовании данной конфигурации.

Итоги:

Hashicorp Vault для нас — это постоянно доступный, единый и безопасный источник правды с разграничением доступа к секретам и различными методами авторизации. Это простой в использовании и конфигурировании инструмент, имеющий актуальную документацию. Он позволяет интегрировать Secret injection webhook, который предоставляет необходимую функциональность: создавать последующие секреты внутри кластера без SOPS шифрования, импортируя их прямо из хранилища, интегрировать практически любые другие инструменты и импортировать в них секреты из хранилища (ci, k8s поды, chef и т.д), но об этом — в следующий раз!

© Habrahabr.ru