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) 섹션에 설명된 단계를 수정해야 해요:
다음 단계는 각 데이터센터에 대해 반복돼요:
- 시크릿에 원하는 접근 수준을 인가하는 Vault 정책을 만든다.
- (추가) 각각 인증서를 발급할 수 있는 도메인을 설정하는 컨트롤러와 connect inject용 Vault PKI 역할을 만든다.
- 정책을 접근이 필요한 각 Consul on Kubernetes 서비스 어카운트와 연결하는 Vault Kubernetes auth 역할을 만든다.
- Consul on Kubernetes Helm 차트에서 Vault Kubernetes auth 역할을 구성한다.
사전 요구 사항 (Prerequisites)
이 주제에 설명된 통합을 구현하기 전에 다음 사전 요구 사항을 완료해요:
- 시크릿 백엔드로서의 Vault 문서의 시스템 통합(Systems Integration) 섹션에 설명된 단계를 완료했는지 확인한다.
- 시크릿 백엔드로서의 Vault 문서의 데이터 통합 개요(Data Integration Overview) 섹션에 익숙해야 한다.
- Kubernetes에서 Vault를 서버 TLS 인증서 제공자로 구성한다.
- 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)
- Consul 컨트롤러와 connect inject가 새 인증서/키 쌍을 가져와 Kubernetes
mutatingwebhookconfiguration에 제공할 수 있도록 인증서 발급 URL에 대한["create", "update"]접근을 허용하는 정책을 만들어요.path리소스에서 참조되는 시크릿의 경로는global.secretsBackend.vault.controller.tlsCert.secretName및global.secretsBackend.vault.connectInject.tlsCert.secretNameHelm 구성에서 구성할 값과 동일해요(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
- Consul 구성 요소가 자동 암호화 인증서를 가져오기 위해 Consul 서버와 통신할 수 있도록 CA URL에 대한
["read"]접근을 허용하는 정책을 만들어요.path리소스에서 참조되는 시크릿의 경로는global.secretsBackend.vault.controller.caCert.secretName및global.secretsBackend.vault.connectInject.caCert.secretNameHelm 구성에서 구성할 값과 동일해요(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
- 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""
- 마지막으로 컨트롤러와 connect inject 웹훅을 위한 Kubernetes auth 역할을 만들어야 해요.
path리소스에서 참조되는 시크릿의 경로는global.secretsBackend.vault.controllerRole및global.secretsBackend.vault.connectInjectRoleHelm 구성에서 구성할 값과 동일해요(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/