Vault Dedicated および External Secrets Operator を使用して、アプリのシークレットを保護する

このチュートリアルでは、オープンソースツール「 External Secrets Operator 」を使用して、 IBM Cloud Kubernetes Service クラスター上で実行されるアプリケーションのシークレットを IBM Cloud Vault Enterpriseで管理する方法について学びます。

あなたは組織に所属する開発者であり、所属チームでは Kubernetes Service を使用して、 IBM Cloud 上にコンテナ化されたアプリケーションやサービスをデプロイしています。 アプリケーションのシークレットを、 IBM Cloud が提供するマネージドサービス「 HashiCorp Vault 」であるVault Dedicatedに保存することをお勧めします。ここでは、保存中のデータを暗号化したり、ライフサイクルを管理したり、簡単にローテーションを行ったりすることができます。

Vault Dedicated と External Secrets Operator を使用することで、 Kubernetes クラスタ内で実行されるアプリケーションで使用されるシークレットを一元管理し、セキュリティを確保することができます。 デプロイ時にシークレットを埋め込むのではなく、実行時にVault Dedicatedからシークレットを安全に取得するようにアプリを設定することができます。 例えば、以下のシナリオがあるとします。

この図は、 Secrets Manager と Kubernetes クラスター間の基本的なデータフローを示しています。
の外部シークレットのフロー

  1. 開発者は、 Kubernetes クラスターにデプロイしたいアプリケーションのシークレットを保存するために、Vault Dedicated を使用します。
  2. HashiCorp Vault プロバイダーを使用して、Vault Dedicatedインスタンスに接続するようにExternal Secrets Operatorを設定します。
  3. 外部シークレットコントローラーは、Kubernetes APIを使用して定義した構成ファイル内のExternalSecretsオブジェクトをフェッチします。
  4. アプリケーションの実行時、コントローラーはVault Dedicatedからシークレットデータを取得し、 ExternalSecrets オブジェクトを、お使いのクラスター用の Kubernetes シークレットに変換します。

このシナリオは、Kubernetes クラスターで実行されるワークロードのコンプライアンスの準備に影響を及ぼす可能性のある、サード・パーティー・ツールを特徴としています。 コミュニティやサードパーティ製のツールを追加する場合は、アプリのコンプライアンス維持はご自身の責任であり、問題が発生した際には該当するプロバイダーと連携してトラブルシューティングを行う必要がある点にご留意ください。 詳細については、IBM Cloud Kubernetes Service 使用の際の責任を参照してください。

開始前に

開始する前に、アカウント資格情報を作成し、リソースをプロビジョニングできるように、必ず管理者プラットフォーム・アクセス権限 を使用するようにしてください。 以下の前提条件も必要です。

jq は、JSONデータのスライスとフィルタリングに役立ちます。 このチュートリアルにあるjqを使用して、保管された環境変数を取得・使用します。

環境を設定する

Vault Dedicatedおよび Kubernetes Service を利用するには、 IBM Cloud アカウントクラスターを作成し、Vault Dedicatedインスタンスへのアクセスを設定する必要があります。

Kubernetes クラスターを作成する

IBM Cloud アカウントで Kubernetes クラスターを作成します。

  1. IBM Cloud CLI を使用して、コマンド・ラインから IBM Cloud にログインします。

    ibmcloud login
    

    ログインに失敗した場合は、ibmcloud login --ssoコマンドを実行して再試行してください。 フェデレーテッドIDを使用してログインする場合は、--ssoパラメーターが必要です。 このオプションを使用する場合、CLI 出力にリストされているリンクに移動して、ワンタイム・パスコードを生成します。

  2. クラスターを作成するアカウント、リージョン、およびリソースグループを選択してください。

    ibmcloud target -r REGION -g RESOURCE_GROUP
    

    REGION を対象のリージョン(例: au-syd )に、 RESOURCE_GROUP をリソースグループ名に置き換えてください。

  3. Kubernetes クラスターを作成します。

    ibmcloud ks cluster create vpc-gen2 --zone ZONE --flavor FLAVOR --workers 1 --name eso-test-cluster --vpc-id VPC_ID --subnet-id SUBNET_ID
    

    ZONE、 FLAVOR、 VPC_ID、および SUBNET_ID を、それぞれの値に置き換えてください。 Kubernetes クラスターのプロビジョニングには、5~15分かかります。

  4. 次の手順に進む前に、クラスタのプロビジョニングが正常に完了していることを確認してください。

    ibmcloud ks worker ls --cluster eso-test-cluster
    

    ワーカー・ノードがプロビジョニングを終了すると、ステータスは 「レディー」 に変わります。

  5. CLI で、Kubernetes クラスターのコンテキストを設定します。

    ibmcloud ks cluster config --cluster eso-test-cluster
    
  6. kubectlコマンドが正しく実行され、Kubernetesコンテキストがクラスターに設定されていることを確認します。

    kubectl config current-context
    

Vault Dedicatedインスタンスの準備を行う

Vault Dedicatedインスタンスを設定して、シークレットの利用を開始し、External Secrets Operatorの認証を設定してください。

  1. Vault Dedicated インスタンスの詳細を含む環境変数をエクスポートします。

    export VAULT_DEDICATED_ADDR="https://<your-vault_dedicated-instance-id>.vault.<region>.appdomain.cloud"
    export VAULT_DEDICATED_NAMESPACE="admin"
    

    <your-vault_dedicated-instance-id> を Vault Dedicated のインスタンス ID に、 <region> を Vault Dedicated のリージョン(例: au-syd )に置き換えてください。

  2. Vault DedicatedインスタンスからVaultトークンを取得してください。

    トークンは、Vault Dedicated UI から、または Vault CLI を使用して生成できます。 開発やテストの際には、ルートトークンを使用できます。 本番環境では、適切なポリシーを設定したトークンを作成してください。

    export VAULT_TOKEN="<your-vault-token>"
    
  3. Vault Dedicated における KV シークレット・エンジンのマウントポイントを確認してください。

    Vault 専用インスタンスでは、KV v2 シークレットエンジンがデフォルトで kv/ にマウントされています。 これは、Vault DedicatedのUIで確認するか、マウントを一覧表示することで確認できます。

    curl -k -X GET \
      -H "X-Vault-Token: $VAULT_TOKEN" \
      -H "X-Vault-Namespace: $VAULT_DEDICATED_NAMESPACE" \
      $VAULT_DEDICATED_ADDR/v1/sys/mounts | jq
    
  4. Vault Dedicated でテスト用シークレットを作成します。

    curl -k -X POST \
      -H "X-Vault-Token: $VAULT_TOKEN" \
      -H "X-Vault-Namespace: $VAULT_DEDICATED_NAMESPACE" \
      -d '{"data":{"username":"user123","password":"cloudy-rainy-coffee-book"}}' \
      $VAULT_DEDICATED_ADDR/v1/kv/data/example_username_password
    

    なお、Vault Dedicated では、KV シークレットエンジンのマウントパスとして kv/ が使用されます。

  5. シークレットが作成されたことを確認してください。

    curl -k -X GET \
      -H "X-Vault-Token: $VAULT_TOKEN" \
      -H "X-Vault-Namespace: $VAULT_DEDICATED_NAMESPACE" \
      $VAULT_DEDICATED_ADDR/v1/kv/data/example_username_password | jq
    

外部シークレット・オペレーターをインストールする

Helm を使用して、External Secrets Operator をインストールします。

  1. 「External Secrets」 Helm リポジトリを追加します。

    helm repo add external-secrets https://charts.external-secrets.io
    helm repo update
    
  2. External Secrets Operator をインストールします。

    helm install external-secrets \
      external-secrets/external-secrets \
      --namespace external-secrets \
      --create-namespace \
      --set installCRDs=true
    
  3. インストールを検証します。

    kubectl get pods -n external-secrets
    

    すべてのポッドが「 Running 」状態になるまで待ちます。

  4. カスタムリソース定義(CRD)がインストールされていることを確認してください。

    kubectl get crd | grep external-secrets
    

    secretstores、 clustersecretstores、 externalsecrets といった CRD が表示されるはずです。

Vault Dedicated 用の SecretStore を設定する

External Secrets Operator が Vault Dedicated インスタンスに接続する方法を定義する「 SecretStore 」リソースを作成します。

  1. Vaultトークンを使用して、 Kubernetes のシークレットを作成します。

    kubectl create secret generic vault-token \
      --namespace external-secrets \
      --from-literal=token="$VAULT_TOKEN"
    
  2. secretstore.yaml ファイルを作成します。

    touch secretstore.yaml
    
  3. ファイルに以下の設定を追加してください。

    apiVersion: external-secrets.io/v1beta1
    kind: SecretStore
    metadata:
      name: vault-dedicated-secretstore
      namespace: default
    spec:
      provider:
        vault:
          server: "<VAULT_DEDICATED_ADDR>"
          path: "kv"
          version: "v2"
          namespace: "admin"
          auth:
            tokenSecretRef:
              name: "vault-token"
              key: "token"
              namespace: "external-secrets"
    

    <VAULT_DEDICATED_ADDR> を、ご自身の Vault Dedicated インスタンスのアドレスに置き換えてください。 なお、 path は kv に設定されています。これは、Vault DedicatedにおけるKVシークレットエンジンのデフォルトのマウントポイントです。

  4. SecretStore の設定を適用します。

    kubectl apply -f secretstore.yaml
    
  5. SecretStore が有効であることを確認してください。

    kubectl get secretstore vault-dedicated-secretstore -n default
    kubectl describe secretstore vault-dedicated-secretstore -n default
    

    Vault Dedicated への接続に成功した場合、ステータスは「 有効 」と表示されるはずです。

[作成] ExternalSecret

Vault Dedicated から取得するシークレットを定義する ExternalSecret リソースを作成します。

  1. externalsecret.yaml というファイルを作成します。

    touch externalsecret.yaml
    
  2. 以下の設定を追加してください。

    apiVersion: external-secrets.io/v1beta1
    kind: ExternalSecret
    metadata:
      name: vault-dedicated-app-secret
      namespace: default
    spec:
      refreshInterval: 1h
      secretStoreRef:
        name: vault-dedicated-secretstore
        kind: SecretStore
      target:
        name: my-k8s-secret
        creationPolicy: Owner
      data:
      - secretKey: username
        remoteRef:
          key: example_username_password
          property: username
      - secretKey: password
        remoteRef:
          key: example_username_password
          property: password
    

    refreshInterval は、External Secrets OperatorがVault Dedicatedに対して更新情報をポーリングする頻度を決定します。 デフォルト値および推奨値は1時間です。

  3. ExternalSecret の設定を適用します。

    kubectl apply -f externalsecret.yaml
    
  4. External Secrets Operator が Vault Dedicated からシークレットを取得したことを確認してください。

    kubectl get secret my-k8s-secret -o json | jq '.data | map_values(@base64d)'
    

    出力例:

    {
        "password": "cloudy-rainy-coffee-book",
        "username": "user123"
    }
    

    成功! これで、Vault Dedicatedインスタンスから機密データを取得し、 Kubernetes クラスターで使用できるようになりました。

クラスターへのアプリのデプロイ

これで、Vault Dedicatedのシークレットを使用するアプリケーションをクラスターにデプロイできるようになります。 アプリケーションの実行時、Vault Dedicated から取得されたシークレットデータは、クラスターで使用可能な Kubernetes シークレットに変換されます。

  1. そのシークレットを使用する簡単なテスト展開を作成します。

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-app
      namespace: default
    spec:
      containers:
      - name: app
        image: busybox
        command: ['sh', '-c', 'echo "Username: \$USERNAME"; echo "Password: \$PASSWORD"; sleep 3600']
        env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: my-k8s-secret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: my-k8s-secret
              key: password
    EOF
    
  2. ポッドのログを確認し、シークレットが注入されたことを確認してください。

    kubectl logs test-app -n default
    

    予期される出力:

    Username: user123
    Password: cloudy-rainy-coffee-book
    

アプリのデプロイ方法に関する具体例をもっと探していますか? アプリケーションのデプロイに関する詳細については、「 クラスタへの Kubernetes-nativeアプリのデプロイ 」をご覧ください。

(オプション) リソースのクリーンアップ

本チュートリアルで作成したリソースが今後不要な場合は、以下の手順を実行して、アカウントからリソースを削除できます。

  1. テスト Kubernetes クラスターを削除します。

    ibmcloud ks cluster rm --cluster eso-test-cluster
    
  2. Vault専用テストシークレットのクリーンアップ。

    curl -k -X DELETE \
      -H "X-Vault-Token: $VAULT_TOKEN" \
      -H "X-Vault-Namespace: $VAULT_DEDICATED_NAMESPACE" \
      $VAULT_DEDICATED_ADDR/v1/kv/metadata/example_username_password
    

注目すべき点

YAMLドキュメントを作成する際は、以下の点に留意してください:

  1. ポーリング間隔 :デフォルトでは、ポーリング間隔は1時間に設定されており(refreshInterval: 1h )、これが推奨値です。 この値は、 ExternalSecret テンプレートで変更できます。 この間隔は、 s、 m、または h の単位で表すことができます。

  2. Vault Dedicated のマウントパス :Vault Dedicated では、KV シークレットエンジンのデフォルトのマウントパスとして、 secret/ ではなく、 kv/ を使用します。 SecretStore の設定で、正しいパスを指定していることを確認してください。

  3. Vault Dedicated のネームスペース :Vault Dedicated では、Vault Enterprise のネームスペースが使用されます。 デフォルトの名前空間は admin です。 SecretStore の設定で、正しい名前空間を指定していることを確認してください。

  4. 認証方法 :このチュートリアルでは、簡便さを考慮してトークン認証を採用しています。 本番環境では、セキュリティを強化するため、 AppRole または Kubernetes の認証方法の使用をご検討ください。

  5. TLS 留意点 :Vault Dedicatedでは、 TLS 接続が必要です。 本番環境では、 skipTLSVerify を使用するのではなく、適切な証明書検証が設定されていることを確認してください。

次のステップ

お疲れさまでした。 このチュートリアルでは、External Secrets Operator を使用して、 Kubernetes クラスターにアプリケーションのシークレットを安全に設定するために、Vault Dedicated をセットアップする方法について学びました。 Vault Dedicated の利用を開始するのに役立つその他のリソースをご覧ください。