Amazon Web Services ブログ

AWS Secrets & Configuration Provider を Kubernetes Secrets Store CSI Driver で使用する方法

この記事は How to use AWS Secrets & Configuration Provider with your Kubernetes Secrets Store CSI driver を翻訳したものです。

AWS Secrets Manager を使用して、Amazon Elastic Kubernetes Service (Amazon EKS) の Kubernetes Pod で使用するために、AWS Secrets Manager からシークレットを安全に取得できるようになりました。AWS Secrets and Config Provider (ASCP) の登場により、Amazon EKS 上で動作するアプリケーションにシークレットを提供するために使用される業界標準の Kubernetes Secrets StoreContainer Storage Interface (CSI) ドライバー の、使いやすいプラグインが利用できます。ASCP を使用して、ファイルシステムや etcd を介してシークレットをフェッチする従来の Kubernetes ワークロードに互換性を提供できるようになりました。これまでは、設定ファイルに平文でシークレットを保存するか、ファイルシステム経由で安全にシークレットを参照およびアクセスするために Kubernetes etcd で暗号化を使用する必要がありました。また、シークレットをローテーションするためにはカスタムコードを書く必要があり、メンテナンスに課題が発生しました。Pod からのセキュアなアクセスを実現するためには、クラスターを分割してアクセスを制御する必要があり、運用負荷が増大していました。

ASCP を使えば、Secrets Manager でシークレットを安全に保管および管理し、カスタムコードを記述しなくても、Kubernetes 上で動作するアプリケーションからシークレットを取得することができます。また、AWS Identity and Access Management (IAM) とリソースポリシーをシークレットに使用することで、Kubernetes クラスター内の特定の Pod にアクセスを制限できるというメリットもあります。これにより、どの Pod がどのシークレットにアクセスできるかを厳密にコントロールできます。Secrets Store CSI Driver の Rotation Reconciler 機能を有効にした場合、ASCP はドライバーと連携してシークレットプロバイダーから最新のシークレットを取得します。ASCP がインストールされて有効になると、Pod の起動時にアプリケーションは常に最新バージョンのシークレットを受け取ることができるようになり、Secrets Manager のライフサイクル管理機能の恩恵を受けることができます。このように、ネイティブに統合されたシークレット管理ソリューションの恩恵を受けるだけでなく、単一のプロバイダーで構成を提供できるようになります。

概要

この記事では、Kubernetes クラスター上の Secrets Store CSI Driver と連携するように、AWS Secrets & Configuration Provider (ASCP) を設定する方法を紹介します。Secrets Store CSI Driver は、Kubernetes が外部のシークレットストアに保存されたシークレットをボリュームとして Pod にマウントすることを可能にします。ボリュームが接続されると、データはコンテナのファイルシステムにマウントされます。この例では、外部シークレットストアは Secrets Manager です。

図1: 概要

このソリューションには、次の手順が含まれています。これらの手順について、次のセクションで詳しく説明します。

  1. IAM Roles for Service Accounts (IRSA) を使って Pod のアクセスを制限する
  2. Kubernetes Secrets Store CSI Driver をインストールする
  3. AWS Secrets & Configuration Provider をインストールする
  4. SecretProviderClass カスタムリソースを作成してデプロイする
  5. 構成されたシークレットに基づくボリュームをマウントするように Pod を構成してデプロイする
  6. コンテナにマウントされたボリュームからシークレットと設定をロードする

前提条件

このソリューションには、次の前提条件があります。

ソリューションのデプロイ

ステップ 1: IAM Roles for Service Accounts を使用して Pod のアクセスを制限する

IAM Roles for Service Accounts (IRSA) を使用して、Pod のシークレットアクセスを制限します。これを設定することで、プロバイダーは Pod のアイデンティティを取得し、このアイデンティティを IAM ロールと交換します。すると、ASCP は Pod のIAM ロールを引き受け、Secrets Manager から Pod がアクセスを許可されているシークレットのみを取得します。これにより、別の Pod に属する別のコンテナを対象としたシークレットに、コンテナがアクセスすることを防ぎます。

以下のコマンドを実行して Open ID Connect (OIDC) を有効にしてください。<REGION><CLUSTERNAME> は自分の値に置き換えてください。

eksctl utils associate-iam-oidc-provider --region=<REGION> --cluster=<CLUSTERNAME> --approve #Only run this once

Service Account のロールを作成するには、次のコマンドを実行して、(前提条件のセクションで準備した) ポリシーを Service Account に関連付けます。<NAMESPACE><CLUSTERNAME><IAM_policy_ARN><SERVICE_ACCOUNT_NAME> を自分の値に置き換えてください。

eksctl create iamserviceaccount --name <SERVICE_ACCOUNT_NAME> --namespace <NAMESPACE> --cluster <CLUSTERNAME> --attach-policy-arn <IAM_policy_ARN> --approve --override-existing-serviceaccounts

ステップ 2: Kubernetes Secrets Store CSI Driver をインストールする

kubectl をインストールしたターミナルから、以下の helm コマンドを実行して CSI ドライバーをインストールします。

helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts

次に、Rotation Reconciler 機能を使ったドライバーによる自動ローテーションをオンにするかどうか、言い換えると、更新されたシークレットを定期的に Pull する必要があるかを決定する必要があります。

更新されたシークレットを定期的に Pull する必要がない場合は、以下のコマンドで CSI ドライバーをインストールします。

helm -n kube-system install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver

注: 古いバージョンのドライバーを使用している場合は、–set grpcSupportedProviders=”aws” というフラグが必要になる場合があります。

現在アルファ版である Rotation Reconciler 機能を使ったドライバーによる自動ローテーションをオンにする場合は、次のコマンドを使用します (API コールのコストの考慮とローテーション頻度の適切なバランスを見つけるために、ローテーション間隔を任意に調整できます) 。

helm -n kube-system install csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --set enableSecretRotation=true --set rotationPollInterval=3600s

インストーラーが期待どおりに実行されたこと確認するには、次のコマンドを実行します。

kubectl get po --namespace=kube-system

出力には、以下のように Secrets Store CSI Driver の Pod とカスタムリソース定義 (CRD) がデプロイされていることが表示されます。

csi-secrets-store-qp9r8         3/3     Running   0          4m
csi-secrets-store-zrjt2         3/3     Running   0          4m
 
kubectl get crd
NAME                                               
secretproviderclasses.secrets-store.csi.x-k8s.io
secretproviderclasspodstatuses.secrets-store.csi.x-k8s.io

ステップ 3: AWS Secrets & Configuration Provider をインストールする

CSI ドライバーを使用すると、EKS の Kubernetes Pod にシークレットをマウントすることができます。CSI ドライバーがシークレットをマウントするために、Secrets Manager からシークレットを取得するには、AWS Secrets & Configuration Provider (ASCP) をインストールする必要があります。これを行うには、ターミナルで以下のコマンドを実行すると、リポジトリ全体をクローンしなくても、インストーラーファイルを適用できます。

curl -s https://raw.githubusercontent.com/aws/secrets-store-csi-driver-provider-aws/main/deployment/aws-provider-installer.yaml | kubectl apply -f -

ステップ 4: SecretProviderClass カスタムリソースを作成してデプロイする

Secrets Store CSI Driver を使用するためには、SecretProviderClass のカスタムリソースを作成する必要があります。これにより、CSI ドライバー自体に、ドライバーの設定とプロバイダー固有のパラメーターが提供されます。SecretProviderClass リソースには、少なくとも以下のコンポーネントが含まれている必要があります。

apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  name: aws-secrets
spec:
  provider: aws                               
  parameters:                                 # プロバイダー固有のパラメーター

ASCP を使用するためには、SecretsProviderClass を作成して、Secrets Manager からシークレットを取得する方法の詳細を提供します。SecretProviderClass は、必ずそれを参照する Pod と同じ Namespace に作成してください。以下は、SecretProviderClass の構成例です。

apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  name: aws-secrets
spec:
  provider: aws
  parameters:                    # プロバイダー固有のパラメーター
    objects:  |
      - objectName: "MySecret2"
        objectType: "secretsmanager"

ステップ 5: 構成されたシークレットに基づくボリュームをマウントするように Pod を構成してデプロイする

Deployment の YAML を更新して、secrets-store.csi.k8s.io ドライバーを使用し、先に作成した SecretProviderClassリソースを参照するようにします。ファイルをローカルデスクトップに保存します。

以下は、SecretProviderClass に基づくボリュームをマウントし、Secrets Manager からシークレットを取得するように Pod を構成する方法の例です。この例では、NGINX を使用しました。シークレットのためのマウントポイントと SecretProviderClass の設定は、Pod のデプロイ定義ファイルにあります。

kind: Pod
apiVersion: v1
metadata:
  name: nginx-secrets-store-inline
spec:
  serviceAccountName: aws-node
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - name: mysecret2
      mountPath: "/mnt/secrets-store"
      readOnly: true
  volumes:
    - name: mysecret2
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: "aws-secrets"

Pod の起動時と再起動時には、CSI ドライバーはプロバイダーバイナリを呼び出して、Secrets Manager と Parameter Store からそれぞれシークレットとコンフィグを取得します。この情報を正常に取得した後、CSI ドライバーはそれらの情報をコンテナのファイルシステムにマウントします。次のコマンドを実行して、再起動後にボリュームが正しくマウントされていることを確認できます。

kubectl exec -it nginx-secrets-store-inline -- ls /mnt/secrets-store/

次のような応答が返ってくるはずです。

MySecret2

Step 6: コンテナにマウントされたボリュームからシークレットと設定をロードする

シークレットとコンフィグの両方が、マウント操作中の Pod の初期化時にフェッチされます。これにより、ネイティブの Kubernetes Secret を使用するときに少しの遅延が追加されますが、カスタムツールまたはサードパーティツールを使用してシークレットを取得する場合も同じです。初期化後、Pod には影響がありません。ASCP は、Rotation Reconciler コンポーネントとともに、マウントパスと Kubernetes Secret シークレット内の値を更新します。ワークロードの Pod は、ファイルシステムを監視して変更を追跡し、新しい認証情報を自動的にピックアップするようにします。環境変数の場合は、Pod を再起動する必要があります。

追加の機能

CSI ドライバーは、シークレットを Kubernetes Secret と同期させることもできます。これを行うには、オプションの secretObjects フィールドを使用して、同期された Kubernetes Secret オブジェクトの目的の状態を定義します。同期にはボリュームマウントが必要です。以下は、AWS Secrets Manager から Kubernetes Secret にシークレットを同期させる SecretProviderClass のカスタムリソースの例です。

apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  name: aws-secrets
spec:
  provider: aws
  secretObjects:       # [オプション] SecretObject は同期された K8s Secret オブジェクトの望ましい状態を定義する
  - data:
  - key: username      # 投入されるデータフィールド
    objectName: ACSPSecrets   # 同期するマウントされたコンテンツの名前、オブジェクト名またはオブジェクトのエイリアスが指定可能 
  secretName: ACSPEKSSecret     # Kubernetes Secret オブジェクトの名前
  type: Opaque         # Kubernetes Secret オブジェクトのタイプ 例) Opaque, kubernetes.io/tls

  parameters:          # プロバイダー固有のパラメーター
    objects: |
      array:
        - |
          objectName: "arn:aws:ssm:us-east-1:[ACCOUNT]:parameter/MyConfigValue"
          objectVersion: "1"# [オプション] オブジェクトバージョン、空の場合は最新がデフォルト
        - |
          objectName: "arn:aws:secretsmanager:us-east-1:[ACCOUNT]:secret:MySecret-00AABB"
          objectVersion: "00112233AABB00112233445566778899"
        - |
          objectName: "MyConfigValue2"
          objectType: "ssmparameter"# オブジェクトタイプ、シークレットには secretsmanager、コンフィグには ssmparameter
          objectVersion: "1"
        - |
          objectName: "MySecret2"
          objectType: "secretsmanager"
          objectVersion: "00112233AABB00112233445566778899"
        - |
          objectName: "MySecret3"
          objectType: "secretsmanager"
          objectVersionLabel: "AWSCURRENT"# [オプション] オブジェクトバージョンステージ、空の場合は最新がデフォルト

サポートされている Kubernetes Secret のタイプは以下の通りです。

  • Opaque
  • kubernetes.io/basic-auth
  • bootstrap.kubernetes.io/token
  • kubernetes.io/dockerconfigjson
  • kubernetes.io/dockercfg
  • kubernetes.io/ssh-auth
  • kubernetes.io/service-account-token
  • kubernetes.io/tls

また、Deployment の YAML で、新しい Kubernetes Secret を参照するために Deployment 内の環境変数を設定するオプションもあります。以下は、同期された Kubernetes Secret から環境変数を作成する Deployment YAML の例です。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: ASCPEKSSecret
              key: username
        volumeMounts:
        - name: mysecret2
          mountPath: "/mnt/secrets-store"
          readOnly: true
      volumes:
        - name: mysecret2
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "aws-secrets"

結論

この記事では、新しい AWS Secrets & Configuration Provider (ASCP) を実行中の Amazon EKS やその他の Kubernetes クラスターで動作させるためのセットアップおよび構成方法について説明しました。ASCP を使用することで、暗号化や自動ローテーション機能によって、シークレットの保護を強化することができます。これにより、アプリケーションのセキュリティ設定の細かい調整ではなく、アプリケーションの開発に集中することができます。

この投稿について質問がある場合は、AWS Secrets Manager フォーラムで新しいスレッドを開始するか、AWS サポートにお問い合わせください。

AWS セキュリティの How-to や、ニュース、機能発表をもっと知りたいですか? Twitter でフォローしてください。

翻訳はプロフェッショナルサービスの杉田が担当しました。