Featured image of post Настройка PKI в HashiCorp Vault как Intermediate CA

Настройка PKI в HashiCorp Vault как Intermediate CA

Vault PKI в Kubernetes (оффлайн)

Что такое Vault и зачем он нужен написал в своём ТГ канале
Присоединяйся Telegram

Цель: Построить цепочку выпуска сертификатов.
Можно облегчить задачу и поместить один сертификат как wildcard для всех приложений, но это противоречит безопасности, так как если серт будет скомпроментирован придётся его заменять на всех сервисах (приложениях), поэтому мы пойдём путём Best Practices и для каждого приложения будет выпускаться свой ключ и свой сертификат.

Требования:

  • Готовый Kubernetes-кластер (или K3S)
  • Установленный HashiCorp Vault
  • корпоративный Root CA, который подпишет CSR от Vault как Intermediate CA

Данный гайд - это часть общего взаимодействия. Vault из этого мануала может быть установлен и сконфигурирован как отдельно так и совместно с общим планом.

План действий:

  • Включить PKI в Vault
  • Сгенерировать CSR
  • Подписать CSR на Windows Root CA как Intermediate CA
  • Загрузить signed.crt в Vault
  • Назначить default issuer
  • Настроить pki/config/urls
  • Создать роль pki/roles/k8s-domain
  • Создать policy cert-manager
  • Включить auth/kubernetes
  • Настроить reviewer service account и auth/kubernetes/config
  • Создать роль auth/kubernetes/role/cert-manager

Шаг 1. Вход в Vault

Авторизуемся в Vault с помощью Root Token из init-vault.json

1
2
3
kubectl -n vault exec -it vault-0 -- sh
export VAULT_ADDR="http://127.0.0.1:8200"
vault login

Шаг 2. Включение PKI secrets engine

Чтобы Vault обладал функциями pki их нужно включить:

1
2
3
vault secrets enable pki
vault secrets tune -max-lease-ttl=43800h pki
vault secrets list | grep pki

Шаг 3. Генерация CSR для Intermediate CA

Vault будет работать как подчиненный (SubCA) центр сертификации. Поэтому сделаем запрос к главному ЦА, и станем SubCA который сможет раздавать сертификаты.
Здесь указывайте ваш домен, на который будут выпускаться сертификаты.
Создаём запрос на сертификат для CA.

1
2
3
vault write -field=csr pki/intermediate/generate/internal \
  common_name=".k8s.domain.local Intermediate CA" \
  ttl=43800h > /tmp/vault-intermediate.csr

Скопировать CSR из pod наружу, подписать его на корпоративном Root CA как SubCA / Intermediate CA.

Пример для запроса у Windows CA:

1
certreq -submit -config "CA-MY-SERVER\ROOT-CA" -attrib "CertificateTemplate:SubCA" vault-intermediate.csr signed.crt

Далее закинуть обратно на мастер ноду куба и проверить, что сертификат действительно CA:

1
openssl x509 -in signed.crt -noout -text | grep -A4 "Basic Constraints"

Должно быть CA:TRUE

Шаг 4. Загрузка подписанного сертификата в Vault

Мы получили файл signed.crt закидываем его внутрь пода Vault.

1
kubectl -n vault cp signed.crt vault-0:/tmp/signed.crt

Заходим в под и добавляем сертификат:

1
2
3
kubectl -n vault exec -it vault-0 -- sh
export VAULT_ADDR="http://127.0.0.1:8200"
vault write pki/intermediate/set-signed certificate=@/tmp/signed.crt

Шаг 5. Назначение default issuer

1
vault list pki/issuers

Видим наш запрос, копируем ID и вставляем вместо <ID_ISSUER>

1
vault write pki/config/issuers default="<ID_ISSUER>"

Проверяем запрос и добавленный сертификат:

1
2
vault read pki/config/issuers
vault read pki/cert/ca

Шаг 6. Настройка URL-адресов для промежуточного CA

1
2
3
vault write pki/config/urls \
  issuing_certificates="http://vault.vault.svc:8200/v1/pki/ca" \
  crl_distribution_points="http://vault.vault.svc:8200/v1/pki/crl"

Проверяем:

1
vault read pki/config/urls

На этом этапе:

1
2
3
Vault Intermediate CA работает
default issuer назначен
AIA / CRL настроены

Шаг 7. Роль PKI для сертификатов Kubernetes

Создаём роль, от имени которой cert-manager будет подписывать сертификаты. Указываем вместо k8s.domain.local наш домен.

1
2
3
4
5
6
7
8
vault write pki/roles/k8s-domain \
  allowed_domains="k8s.domain.local" \
  allow_subdomains=true \
  allow_bare_domains=true \
  enforce_hostnames=true \
  require_cn=false \
  max_ttl="720h" \
  ttl="168h"

Проверка:

1
vault read pki/roles/k8s-domain

Тестово пробуем выдать сертификат:

1
2
3
vault write pki/issue/k8s-domain \
  common_name="test.k8s.domain.local" \
  ttl="24h"

Шаг 8. Политика Vault для cert-manager

Внутри pod Vault

1
kubectl -n vault exec -it vault-0 -- sh

Создаём policy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat > /tmp/cert-manager.hcl <<'EOF'
path "pki/sign/k8s-domain" {
  capabilities = ["create", "update"]
}
path "pki/cert/ca" {
  capabilities = ["read"]
}
path "pki/ca_chain" {
  capabilities = ["read"]
}
EOF

Применяем:

1
vault policy write cert-manager /tmp/cert-manager.hcl

Проверяем:

1
vault policy read cert-manager

Шаг 9. Kubernetes Auth в Vault

Для Vault нужно включить auth/kubernetes и дать ему reviewer token, чтобы он мог валидировать service account tokens через Kubernetes TokenReview API.
Актуальная документация cert-manager отдельно описывает использование Kubernetes Service Account для аутентификации в Vault.

Включаем auth method

1
vault auth enable kubernetes || true

Создаём reviewer service account

1
kubectl -n vault create serviceaccount vault-token-reviewer

Даём права на TokenReview

1
2
3
kubectl create clusterrolebinding vault-token-reviewer-binding \
  --clusterrole=system:auth-delegator \
  --serviceaccount=vault:vault-token-reviewer

Создаём secret для service account token

Создаём файл с токеном:

1
nano vault-token-reviewer-secret.yaml

Содержимое:

1
2
3
4
5
6
7
8
apiVersion: v1
kind: Secret
metadata:
  name: vault-token-reviewer-token
  namespace: vault
  annotations:
    kubernetes.io/service-account.name: vault-token-reviewer
type: kubernetes.io/service-account-token

Применяем:

1
kubectl apply -f vault-token-reviewer-secret.yaml

Шаг 9.5. Извлекаем reviewer JWT и CA кластера

Получаем токен на мастере кубернетес:

1
REVIEWER_JWT=$(kubectl -n vault get secret vault-token-reviewer-token -o jsonpath='{.data.token}' | base64 -d)

Проверяем:

1
echo $REVIEWER_JWT | head

Получаем CA Kubernetes

1
kubectl -n vault get secret vault-token-reviewer-token -o jsonpath='{.data.ca\.crt}' | base64 -d > /tmp/k8s-ca.crt

Копируем CA в pod

1
kubectl cp /tmp/k8s-ca.crt vault/vault-0:/tmp/k8s-ca.crt

Выполняем vault write:

1
2
3
4
5
kubectl -n vault exec -it vault-0 -- sh -c "
vault write auth/kubernetes/config \
  kubernetes_host=https://kubernetes.default.svc:443 \
  token_reviewer_jwt='$REVIEWER_JWT' \
  kubernetes_ca_cert=@/tmp/k8s-ca.crt"

Проверяем:

1
vault read auth/kubernetes/config

Шаг 9.6. Создаём роль для cert-manager

1
2
3
4
5
vault write auth/kubernetes/role/cert-manager \
  bound_service_account_names=cert-manager \
  bound_service_account_namespaces=cert-manager \
  policies=cert-manager \
  ttl=1h

Проверка:

1
vault read auth/kubernetes/role/cert-manager

Настройка Vault как SubCa завершена.
Теперь нужно установить cert-manager, если его нет и подключить его к Vault.

Информацию можно использовать в свободном доступе, с указанием ссылки на сайт
Telegram GitHub YouTube