0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[k8s] vaultに対してクラスタ内でHTTPS通信できるようにした話

Posted at

抱えていた課題

普段運用しているクラスタでは、クラスタ内に Vault を設置して、その Vault で Secret を管理しています。(↓ 参考)

ExternalSecrets を使って、Vault にある Secret を Kubernetes 内で使えるようにしているのですが、Vault との通信には HTTP を使っていました。↓

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-secret-store
spec:
  provider:
    vault:
      server: "http://vault.vault.svc.cluster.local:8200"

このままだと、クラスタ内に悪意のあるワークロードが入り込んだ場合、Secret が盗まれる可能性があり危険です。
そこで今回は、Vault との通信を HTTPS に変更し、さらに Vault に証明書を設定して、通信を暗号化することにしました。

実装

証明書の作成

基本的には、下記のドキュメントに従って設定を行いました。

環境変数を設定

export VAULT_K8S_NAMESPACE="vault"
export VAULT_HELM_RELEASE_NAME="vault"
export VAULT_SERVICE_NAME="vault"
export K8S_CLUSTER_NAME="cluster.local"
export WORKDIR="/tmp/vault"
mkdir -p ${WORKDIR}

秘密鍵を生成

openssl genrsa -out ${WORKDIR}/vault.key 2048

CSR(Certificate Signing Request)を作成

cat > ${WORKDIR}/vault-csr.conf <<EOF
[req]
default_bits = 2048
prompt = no
encrypt_key = yes
default_md = sha256
distinguished_name = kubelet_serving
req_extensions = v3_req
[ kubelet_serving ]
O = system:nodes
CN = system:node:*.${VAULT_K8S_NAMESPACE}.svc.${K8S_CLUSTER_NAME}
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.${VAULT_SERVICE_NAME}
DNS.2 = *.${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}
DNS.3 = *.${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}.svc
DNS.4 = *.${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}.svc.cluster.local
DNS.5 = ${VAULT_SERVICE_NAME}
DNS.6 = ${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}
DNS.7 = ${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}.svc
DNS.8 = ${VAULT_SERVICE_NAME}.${VAULT_K8S_NAMESPACE}.svc.cluster.local
IP.1 = 127.0.0.1
EOF
openssl req -new -key ${WORKDIR}/vault.key -out ${WORKDIR}/vault.csr -config ${WORKDIR}/vault-csr.conf

証明書を発行

cat | kubectl create -f - <<EOF
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
   name: vault.svc
spec:
   signerName: kubernetes.io/kubelet-serving
   expirationSeconds: 8640000
   request: $(cat ${WORKDIR}/vault.csr|base64|tr -d '\n')
   usages:
   - digital signature
   - key encipherment
   - server auth
EOF

Approve

kubectl certificate approve vault.svc

証明書から secret を作成

kubectl get csr vault.svc -o jsonpath='{.status.certificate}' | openssl base64 -d -A -out ${WORKDIR}/vault.crt
kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d > ${WORKDIR}/vault.ca
kubectl create secret generic vault-tls -n $VAULT_K8S_NAMESPACE --from-file=vault.key=${WORKDIR}/vault.key --from-file=vault.crt=${WORKDIR}/vault.crt --from-file=vault.ca=${WORKDIR}/vault.ca

Vault の設定

Helm の values.yaml に証明書の設定を追加します。

global:
  enabled: true
  tlsDisable: false
extraEnvironmentVars:
  VAULT_CACERT: /vault/userconfig/vault-tls/vault.ca
  VAULT_TLSCERT: /vault/userconfig/vault-tls/vault.crt
  VAULT_TLSKEY: /vault/userconfig/vault-tls/vault.key
volumes:
  - name: userconfig-vault-tls
    secret:
      defaultMode: 420
      secretName: vault-tls
volumeMounts:
  - mountPath: /vault/userconfig/vault-tls
    name: userconfig-vault-tls
    readOnly: true
standalone:
  enabled: true
  config: |
    ui = true
    listener "tcp" {
      address = "[::]:8200"
      cluster_address = "[::]:8201"
      tls_cert_file = "/vault/userconfig/vault-tls/vault.crt"
      tls_key_file  = "/vault/userconfig/vault-tls/vault.key"
      tls_client_ca_file = "/vault/userconfig/vault-tls/vault.ca"
    }
    storage "file" {
      path = "/vault/data"
    }
ingress:
  enabled: true
  ingressClassName: nginx
  tls:
    - hosts:
        - vault.example.com
      secretName: cluster-tls
  pathType: Prefix
  hosts:
    - host: vault.example.com
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

ドキュメントとは異なる点は以下の 2 点です。

ExternalSecrets の設定

ClusterSecretStore の設定を変更して、Vault との通信を HTTPS に変更します。

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-secret-store
spec:
  provider:
    vault:
      server: "https://vault.vault.svc.cluster.local:8200" # HTTPS に変更
      path: k8s
      version: v2
      namespace: vault
      auth:
        kubernetes:
          mountPath: kubernetes
          role: k8s-cluster
          serviceAccountRef:
            name: vault-auth
            namespace: vault
      caProvider: # 追加
        type: Secret
        namespace: vault
        name: vault-tls
        key: vault.ca

これで、Vault との通信が HTTPS に変更されました。

おわりに

今回は、Vault との通信を HTTPS に変更しました。
これにより、クラスタ内での Secret のやりとりがより安全になりました。

次回は cert-manager を使って、証明書の自動更新を行えるようにしたいと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?