Pod から外部のVault を利用する - その2

自分備忘録用メモ。前の記事でデプロイしたTKGm v1.4 環境にデプロイしたPod から、外部Vault を利用する際の手順です。

ここでは、Vault Agent Injector のデプロイと、Vault Agent Injector を使って外部Vault と連携します。

手順

Vault Agent Injector のデプロイ

helm chart を利用して、Vault agent injector のデプロイします。アノテーションinjector.externalVaultAddr に外部Vaultのサービスを指定し、デプロイします。
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update
$ helm search repo hashicorp |grep vault
hashicorp/vault    	0.16.1       	1.8.3      	Official HashiCorp Vault Chart
helm upgrade --install vault hashicorp/vault --set "injector.externalVaultAddr=http://external-vault:8200" --namespace vault-test
$ k -n vault-test get pods
NAME                                    READY   STATUS    RESTARTS   AGE
devwebapp                               1/1     Running   0          11m
devwebapp-through-service               1/1     Running   0          3m53s
vault-agent-injector-6b99bdc4bd-746h6   1/1     Running   0          22s

この処理で、vault というサービスアカウントが作成されます。このサービスアカウントのシークレットは、Vault のKubernetes を用いた認証設定の際に必要になります。
$ k -n vault-test describe serviceaccount vault
Name:                vault
Namespace:           vault-test
Labels:              app.kubernetes.io/instance=vault
                     app.kubernetes.io/managed-by=Helm
                     app.kubernetes.io/name=vault
                     helm.sh/chart=vault-0.16.1
Annotations:         meta.helm.sh/release-name: vault
                     meta.helm.sh/release-namespace: vault-test
Image pull secrets:  <none>
Mountable secrets:   vault-token-jzqnw
Tokens:              vault-token-jzqnw
Events:              <none>

シークレット名を変数に入れておきます。
VAULT_HELM_SECRET_NAME=$(kubectl -n vault-test get secrets --output=json | jq -r '.items[].metadata | select(.name|startswith("vault-token-")).name')
$ kubectl -n vault-test describe secret $VAULT_HELM_SECRET_NAME
Name:         vault-token-jzqnw
Namespace:    vault-test
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: vault
              kubernetes.io/service-account.uid: b75f732f-d4f1-494d-b0c7-ec6652f02783

Type:  kubernetes.io/service-account-token

Data
====
namespace:  10 bytes
token:      ey...
ca.crt:     1070 bytes

Vault のAuth Method でKubernetes を有効化します。
$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/

Kubernetes を用いた認証では、この後設定するKubernetes のエンドポイントに対して、サービスアカウントの認証を行い、ポリシーに基づいた権限が付与されたトークンを返す様になります。
正しく設定するには、サービスアカウントのJSON Web トークン(JWT)、Kubernetes のCA 証明書、Kubernetes のAPI エンドポイントのURL が必要になります。
VTOKEN_REVIEW_JWT=$(kubectl -n vault-test get secret $VAULT_HELM_SECRET_NAME --output='go-template={{ .data.token }}' | base64 --decode)
KUBE_CA_CERT=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.certificate-authority-data}' | base64 --decode)
KUBE_HOST=$(kubectl config view --raw --minify --flatten --output='jsonpath={.clusters[].cluster.server}')

この情報を元に、Vault のKubernetes 接続設定を行います。
$ vault write auth/kubernetes/config \
        token_reviewer_jwt="$TOKEN_REVIEW_JWT" \
        kubernetes_host="$KUBE_HOST" \
        kubernetes_ca_cert="$KUBE_CA_CERT" \
        issuer="https://kubernetes.default.svc.cluster.local"
Success! Data written to: auth/kubernetes/config

サービスアカウントinternal-app に付与するポリシーの作成を行います。パスsecret/data/devwebapp/config に対して、Read権限を持ったポリシーを作成します。
$ vault policy write devwebapp - <<EOF
path "secret/data/devwebapp/config" {
  capabilities = ["read"]
}
EOF
Success! Uploaded policy: devwebapp

サービスアカウント、Namespace、ポリシー、TTLを設定したロールを作成します。
$ vault write auth/kubernetes/role/devweb-app \
        bound_service_account_names=internal-app \
        bound_service_account_namespaces=vault-test \
        policies=devwebapp \
        ttl=24h
Success! Data written to: auth/kubernetes/role/devweb-app

このロールは、Kubernetes のサービスアカウント<internal-app>、Namespace <vault-test> に対して、ポリシー<devwebapp> が有効なロールです。このロールで認証後に返されるトークンは、ポリシー<devwebapp> に基づいた権限が付与されており、有効期限(Time-Tol-Lived)は24時間になります。

Vault Agent Injector を使ったPod / 外部Vault 連携

Vault Agent Injector を使って、Pod から外部Vault のKVシークレットにストアされている値を利用します。Vault Agent Injector は、マニフェストに特定のアノテーションが含まれている場合にのみ、Pod またはDeployment に対してデプロイされます。
$ cat > pod-devwebapp-with-annotations.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: devwebapp-with-annotations
  namespace: vault-test
  labels:
    app: devwebapp-with-annotations
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "devweb-app"
    vault.hashicorp.com/agent-inject-secret-credentials.txt: "secret/data/devwebapp/config"
spec:
  serviceAccountName: internal-app
  containers:
    - name: app
      image: burtlo/devwebapp-ruby:k8s
      #env:
      #- name: VAULT_ADDR
      #  value: "http://external-vault:8200"
      #- name: VAULT_TOKEN
      #  value: "s.********"
EOF

指定したアノテーションは、prefix として vault.hashicorp.com が付きます。
  • agent-inject : Vault Agent Injector を有効化します。
  • role : Vault のKubernetes 認証のロールを指定します。
  • agent-inject-secret-FILEPATH : コンテナの /vault/secrets ディレクトリに書き込まれる credentials.txt というファイルのパスのプレフィックスとして指定します。値はVault で定義されたシークレットのパスです。
以前の方法では、アプリケーションの環境変数にVAULT_ADDRVAULT_TOKEN を指定していましたが、Vault Agent Injector を利用する事でこれらは必要なくなりますので、コメントアウトしています。
 
アプリケーションをデプロイします。
k -n vault-test apply -f pod-devwebapp-with-annotations.yaml
$ k -n vault-test get pods
NAME                                    READY   STATUS    RESTARTS   AGE
devwebapp                               1/1     Running   0          43h
devwebapp-through-service               1/1     Running   0          43h
devwebapp-with-annotations              2/2     Running   0          2m56s
vault-agent-injector-6b99bdc4bd-746h6   1/1     Running   0          43h
 
Vault Agent Injector により、Pod 内に追加のコンテナが作成され、アプリケーションコンテナのファイルパス /vault/secrets/credentials.txt にシークレットが自動的に書き込まれます。

ファイル /vault/secrets/credentials.txt に書き込まれたシークレットを、devwebapp-with-annotations Pod で確認します。 
$ k -n vault-test exec devwebapp-with-annotations -c app -- cat /vault/secrets/credentials.txt
data: map[password:salsa username:giraffe]
metadata: map[created_time:2021-10-02T04:16:33.641430016Z deletion_time: destroyed:false version:1]

テンプレートを適用することで、アプリケーションのニーズに合わせてこのデータを構造化する事も可能です。

このブログの人気の投稿

Tanzu Mission Control(TMC) の NetworkPolicy を試してみる