Webhook 인증서용 Vault PKI 사용

Webhook 인증서용 Vault PKI 사용 (Webhook Certificate)

Consul 컨트롤러와 connect inject webhook에서 Vault가 발급한 TLS 인증서를 사용하도록 Consul Helm 차트를 구성하는 방법을 설명하는 문서예요.

출처: 문서

본문

이 주제는 Consul 컨트롤러와 connect inject webhook에서 Vault가 발급한 TLS 인증서를 사용하도록 Consul Helm 차트를 구성하는 방법을 설명해요.

개요 (Overview)

Vault를 사용하지 않는 Consul Helm 차트 구성에서는 webhook-cert-manager가 컨트롤러 또는 connect inject의 mutatingwebhookconfiguration에 유효한 인증서가 갱신되도록 보장해 Kubernetes가 이 각 서비스와 통신할 수 있게 해요.

Vault가 Kubernetes에서 컨트롤러 및 connect inject 웹훅 인증서 제공자(Webhook Certificate Provider)로 구성되면:

  • webhook-cert-manager는 더 이상 클러스터에 배포되지 않아요.
  • 컨트롤러와 connect inject는 주입된 Vault 에이전트를 통해 각자의 Vault PKI 마운트에서 웹훅 인증서를 가져와요.
  • 컨트롤러와 connect inject는 각각 자신의 PKI 마운트에서 인증서를 받을 수 있는 필요한 권한을 가진 자체 Vault 역할로 구성되어야 해요.
  • 컨트롤러와 connect inject는 각각 자신의 mutatingwebhookconfiguration을 로컬로 업데이트해 Kubernetes가 이벤트를 중계할 수 있게 해요.
  • Vault가 인증서 회전을 관리하고 각 웹훅에 인증서를 회전시켜 줘요.

Vault를 컨트롤러 및 connect inject 웹훅 인증서 제공자로 사용하려면 데이터 통합(Data Integration) 섹션에 설명된 단계를 수정해야 해요:

다음 단계는 각 데이터센터에 대해 반복돼요:

  1. 시크릿에 원하는 접근 수준을 인가하는 Vault 정책을 만든다.
  2. (추가) 각각 인증서를 발급할 수 있는 도메인을 설정하는 컨트롤러와 connect inject용 Vault PKI 역할을 만든다.
  3. 정책을 접근이 필요한 각 Consul on Kubernetes 서비스 어카운트와 연결하는 Vault Kubernetes auth 역할을 만든다.
  4. Consul on Kubernetes Helm 차트에서 Vault Kubernetes auth 역할을 구성한다.

사전 요구 사항 (Prerequisites)

이 주제에 설명된 통합을 구현하기 전에 다음 사전 요구 사항을 완료해요:

  1. 시크릿 백엔드로서의 Vault 문서의 시스템 통합(Systems Integration) 섹션에 설명된 단계를 완료했는지 확인한다.
  2. 시크릿 백엔드로서의 Vault 문서의 데이터 통합 개요(Data Integration Overview) 섹션에 익숙해야 한다.
  3. Kubernetes에서 Vault를 서버 TLS 인증서 제공자로 구성한다.
  4. Kubernetes에서 Vault를 서비스 메시 인증서 제공자로 구성한다.

PKI 엔진 부트스트랩 (Bootstrapping the PKI Engines)

컨트롤러와 connect inject 웹훅을 위한 TLS 인증서를 제공하도록 PKI 시크릿 엔진을 활성화하고 구성하려면 다음 명령을 실행해요:

  • 각각에 PKI 시크릿 엔진을 마운트한다:
$ vault secrets enable -path=controller pki
$ vault secrets enable -path=connect-inject pki
  • 더 긴 TTL을 활성화하도록 엔진 마운트를 튜닝한다:
$ vault secrets tune -max-lease-ttl=87600h controller
$ vault secrets tune -max-lease-ttl=87600h connect-inject
  • 각각에 대한 루트 CA를 생성한다:
$ vault write -field=certificate controller/root/generate/internal \
        common_name="<helm release name>-controller-webhook" \
        ttl=87600h
$ vault write -field=certificate connect-inject/root/generate/internal \
        common_name="<helm release name>-connect-injector" \
        ttl=87600h

Vault 정책 만들기 (Create Vault Policies)

  1. Consul 컨트롤러와 connect inject가 새 인증서/키 쌍을 가져와 Kubernetes mutatingwebhookconfiguration에 제공할 수 있도록 인증서 발급 URL에 대한 ["create", "update"] 접근을 허용하는 정책을 만들어요. path 리소스에서 참조되는 시크릿의 경로는 global.secretsBackend.vault.controller.tlsCert.secretName 및 global.secretsBackend.vault.connectInject.tlsCert.secretName Helm 구성에서 구성할 값과 동일해요(Consul on Kubernetes Helm 차트 업데이트 참고).
$ vault policy write controller-tls-policy - <<EOF
path controller/issue/controller-role {
  capabilities = ["create", "update"]
}
EOF
$ vault policy write connect-inject-policy - <<EOF
path connect-inject/issue/connect-inject-role {
  capabilities = ["create", "update"]
}
EOF
  1. Consul 구성 요소가 자동 암호화 인증서를 가져오기 위해 Consul 서버와 통신할 수 있도록 CA URL에 대한 ["read"] 접근을 허용하는 정책을 만들어요. path 리소스에서 참조되는 시크릿의 경로는 global.secretsBackend.vault.controller.caCert.secretName 및 global.secretsBackend.vault.connectInject.caCert.secretName Helm 구성에서 구성할 값과 동일해요(Consul on Kubernetes Helm 차트 업데이트 참고).
$ vault policy write controller-ca-policy - <<EOF
path controller/cert/ca {
  capabilities = ["read"]
}
EOF
$ vault policy write connect-inject-ca-policy - <<EOF
path connect-inject/cert/ca {
  capabilities = ["read"]
}
EOF
  1. PKI 인증서의 허용 도메인을 구성해요.
$ vault write controller/roles/controller-role \
    allowed_domains="<Allowed-domains-string>" \
    allow_subdomains=true \
    allow_bare_domains=true \
    allow_localhost=true \
    generate_lease=true \
    max_ttl="720h"
$ vault write connect-inject/roles/connect-inject-role \
    allowed_domains="<Allowed-domains-string>" \
    allow_subdomains=true \
    allow_bare_domains=true \
    allow_localhost=true \
    generate_lease=true \
    max_ttl="720h"

각각의 <Allowed-domains-string>을 생성하려면 다음 스크립트를 템플릿으로 사용해요:

#!/bin/sh

# NAME is set to either the value from `global.name` from your Consul K8s value file, or your $HELM_RELEASE_NAME-consul
export NAME=consulk8s
# NAMESPACE is where the Consul on Kubernetes is installed
export NAMESPACE=consul
# DATACENTER is the value of `global.datacenter` from your Helm values config file
export DATACENTER=dc1

echo allowed_domains_controller="${NAME}-controller-webhook,${NAME}-controller-webhook.${NAMESPACE},${NAME}-controller-webhook.${NAMESPACE}.svc,${NAME}-controller-webhook.${NAMESPACE}.svc.cluster.local""

echo allowed_domains_connect_inject="${NAME}-connect-injector,${NAME}-connect-injector.${NAMESPACE},${NAME}-connect-injector.${NAMESPACE}.svc,${NAME}-connect-injector.${NAMESPACE}.svc.cluster.local""
  1. 마지막으로 컨트롤러와 connect inject 웹훅을 위한 Kubernetes auth 역할을 만들어야 해요. path 리소스에서 참조되는 시크릿의 경로는 global.secretsBackend.vault.controllerRole 및 global.secretsBackend.vault.connectInjectRole Helm 구성에서 구성할 값과 동일해요(Consul on Kubernetes Helm 차트 업데이트 참고).

Consul 컨트롤러 웹훅용 역할:

$ vault write auth/kubernetes/role/controller-role \
    bound_service_account_names=<Consul controller service account> \
    bound_service_account_namespaces=<Consul installation namespace> \
    policies=controller-ca-policy \
    ttl=1h

Consul 컨트롤러의 서비스 어카운트 이름을 찾으려면 다음을 실행할 수 있어요:

$ helm template --release-name ${RELEASE_NAME} --show-only templates/controller-serviceaccount.yaml hashicorp/consul -f values.yaml

Consul connect inject 웹훅용 역할:

$ vault write auth/kubernetes/role/connect-inject-role \
    bound_service_account_names=<Consul connect inject service account> \
    bound_service_account_namespaces=<Consul installation namespace> \
    policies=connect-inject-ca-policy \
    ttl=1h

Consul connect inject의 서비스 어카운트 이름을 찾으려면 아래 명령을 사용해요.

$ helm template --release-name ${RELEASE_NAME} --show-only templates/connect-inject-serviceaccount.yaml hashicorp/consul -f values.yaml

Consul on Kubernetes Helm 차트 업데이트 (Update Consul on Kubernetes Helm chart)

이제 Vault를 구성했으니 Vault의 서버 TLS 인증서를 사용하도록 Consul Helm 차트를 구성할 수 있어요:

values.yaml

global:
  secretsBackend:
    vault:
      enabled: true
      consulServerRole: "consul-server"
      consulClientRole: "consul-client"
      consulCARole: "consul-ca"
      controllerRole: "controller-role"
      connectInjectRole: "connect-inject-role"
      connectInject:
        caCert:
          secretName: "connect-inject/cert/ca"
        tlsCert:
          secretName: "connect-inject/issue/connect-inject-role"
  tls:
    enabled: true
    enableAutoEncrypt: true
    caCert:
      secretName: "pki/cert/ca"
server:
  serverCert:
    secretName: "pki/issue/consul-server"
  extraVolumes:
    - type: "secret"
      name: <vaultCASecret>
      load: "false"
connectInject:
  enabled: true

vaultCASecret은 Vault 통신에 사용되는 CA 인증서를 저장하는 Kubernetes 시크릿이에요. CA를 제공하려면 먼저 CA가 포함된 Kubernetes 시크릿을 만들어야 해요. 예를 들어 다음과 같이 Vault CA로 시크릿을 만들 수 있어요:

$ kubectl create secret generic vault-ca --from-file vault.ca=/path/to/your/vault/

더 알아보기 (Learn more)