通过kubectl port-forward无法在HTTPS下运行Vault UI求助
问题描述
在AWS EKS的Kubernetes集群中运行Vault集群,已完成初始化与解封。执行kubectl port-forward service/vault 8200:8200端口转发后,访问https://localhost:8200时收到提示Client sent an HTTP request to an HTTPS server.,查看Vault Pod日志发现错误:http: TLS handshake error from 127.0.0.1:38678: remote error: tls: unknown certificate。
问题根源
- 协议混淆:部分请求误以HTTP方式访问了HTTPS端口,触发第一个错误;
- 证书信任缺失:本地客户端未信任Vault使用的EKS签发证书,导致TLS握手失败;
- 证书生成脚本错误:脚本中获取签发证书时指定了错误的命名空间,导致生成的证书无效。
修复步骤
1. 修正证书生成脚本的命名空间错误
脚本中获取签发证书的命令指定了错误的命名空间kubecf,需替换为Vault所在的${NAMESPACE}变量:
# 原错误命令 serverCert=$(kubectl get csr ${CSR_NAME} -n kubecf -o jsonpath='{.status.certificate}') # 修正后 serverCert=$(kubectl get csr ${CSR_NAME} -n ${NAMESPACE} -o jsonpath='{.status.certificate}')
2. 确保访问时携带CA证书
本地访问Vault必须指定信任的CA证书,否则客户端无法验证证书合法性:
- 使用Vault CLI访问:
export VAULT_ADDR=https://localhost:8200 export VAULT_CACERT=/path/to/your/vault.ca # 替换为你本地的vault.ca文件路径 vault status - 使用浏览器访问:
将vault.ca导入浏览器的根证书信任库,或临时手动确认信任该证书(仅测试环境可用)。
3. 验证证书内容正确性
重新生成证书后,检查证书的SAN字段是否包含127.0.0.1及相关域名:
openssl x509 -in /tmp/vault.crt -text -noout | grep -A 10 "Subject Alternative Name"
确认输出中包含IP Address:127.0.0.1以及Vault服务的DNS域名。
4. 检查Vault Pod的证书挂载情况
确认Vault Pod已正确挂载证书secret:
kubectl exec -n vault vault-0 -- ls /vault/userconfig/vault-server-tls/
应输出vault.crt、vault.key、vault.ca三个文件,且文件内容非空。
原始配置参考
Vault Terraform Helm配置
resource "helm_release" "vault" { name = "vault" namespace = kubernetes_namespace.vault.id chart = "vault" repository = "https://helm.releases.hashicorp.com" version = "0.22.0" values = [ <<EOF global: tlsDisable: false ui: enabled: true server: extraEnvironmentVars: VAULT_CACERT: /vault/userconfig/vault-server-tls/vault.ca extraVolumes: - type: secret name: vault-server-tls nodeSelector: | eks.amazonaws.com/nodegroup: "vault-${var.environment}" tolerations: - key: "nodegroup" operator: "Equal" value: "vault" effect: "NoSchedule" logLevel: "debug" ha: enabled: true nodes: 3 raft: enabled: true setNodeId: true config: | ui = true listener "tcp" { tls_disable = 0 tls_cert_file = "/vault/userconfig/vault-server-tls/vault.crt" tls_key_file = "/vault/userconfig/vault-server-tls/vault.key" tls_client_ca_file = "/vault/userconfig/vault-server-tls/vault.ca" address = "[::]:8200" cluster_address = "[::]:8201" } storage "raft" { path = "/vault/data" } service_registration "kubernetes" {} seal "awskms" { region = "${var.aws_region}" kms_key_id = "${aws_kms_key.vault.key_id}" } EOF , ] }
修正后的证书生成脚本
#!/bin/bash -e SERVICE=vault SECRET_NAME=vault-server-tls TMPDIR=/tmp SLEEP_TIME=15 KUBECTL_INSTALLATION_URL=https://storage.googleapis.com/kubernetes-release/release/v1.23.6/bin/linux/amd64/kubectl # Name of the CSR echo "Name the CSR: vault-csr" export CSR_NAME=vault-csr # Install OpenSSL echo "Install openssl" yum install -y openssl 2>&1 # Install Kubernetes cli echo "Install Kubernetes cli" curl -o kubectl ${KUBECTL_INSTALLATION_URL} chmod +x ./kubectl mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$PATH:$HOME/bin kubectl version --short --client # Create a private key echo "Generate certificate Private key" openssl genrsa -out ${TMPDIR}/vault.key 2048 # Create CSR echo "Create CSR file" cat <<EOF >${TMPDIR}/csr.conf [req] req_extensions = v3_req distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = ${SERVICE} DNS.2 = ${SERVICE}.${NAMESPACE} DNS.3 = ${SERVICE}.${NAMESPACE}.svc DNS.4 = ${SERVICE}.${NAMESPACE}.svc.cluster.local DNS.5 = vault-0.vault-internal DNS.6 = vault-1.vault-internal DNS.7 = vault-2.vault-internal IP.1 = 127.0.0.1 EOF # Sign the CSR echo "Sign the CSR" openssl req -new -key ${TMPDIR}/vault.key -subj "/CN=${SERVICE}.${NAMESPACE}.svc" -out ${TMPDIR}/server.csr -config ${TMPDIR}/csr.conf echo "Create a CSR Manifest file" cat <<EOF >${TMPDIR}/csr.yaml apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: ${CSR_NAME} spec: groups: - system:authenticated request: $(cat ${TMPDIR}/server.csr | base64 | tr -d '\n') signerName: beta.eks.amazonaws.com/app-serving usages: - digital signature - key encipherment - server auth EOF echo "Create CSR from manifest file" kubectl create -f ${TMPDIR}/csr.yaml sleep ${SLEEP_TIME} echo "Fetch the CSR from kubernetes" kubectl get csr ${CSR_NAME} # Approve Cert echo "Approve the Certificate" kubectl certificate approve ${CSR_NAME} # 修正命名空间错误 serverCert=$(kubectl get csr ${CSR_NAME} -n ${NAMESPACE} -o jsonpath='{.status.certificate}') echo "${serverCert}" | openssl base64 -d -A -out ${TMPDIR}/vault.crt echo "Fetch Kubernetes CA Certificate" kubectl get secret -o jsonpath="{.items[?(@.type==\"kubernetes.io/service-account-token\")].data['ca\.crt']}" | base64 --decode > ${TMPDIR}/vault.ca 2>/dev/null || true echo "Create secret containing the TLS Certificates and key" echo kubectl create secret generic ${SECRET_NAME} \ --namespace "${NAMESPACE}" \ --from-file=vault.key=${TMPDIR}/vault.key \ --from-file=vault.crt=${TMPDIR}/vault.crt \ --from-file=vault.ca=${TMPDIR}/vault.ca kubectl create secret generic ${SECRET_NAME} \ --namespace "${NAMESPACE}" \ --from-file=vault.key=${TMPDIR}/vault.key \ --from-file=vault.crt=${TMPDIR}/vault.crt \ --from-file=vault.ca=${TMPDIR}/vault.ca
内容的提问来源于stack exchange,提问作者Murakami
相关产品推荐
相关产品推荐

