Azure Kubernetes Service (AKS) の Azure Key Vault Secrets Store CSI Driver に Azure ID プロバイダーを接続する

Azure Kubernetes Service (AKS) 上の Secrets Store Container Storage Interface (CSI) Driver には、Azure Key Vault に ID ベースでアクセスするためのさまざまな方法が用意されています。 この記事では、ロールベースのアクセス制御 (RBAC) または OpenID Connect (OIDC) セキュリティ モデルを使用してキー コンテナーと AKS クラスターにアクセスする場合のこれらの方法とベスト プラクティスについて説明します。

次のいずれかのアクセス方法を使用できます。

CSI ドライバーの前提条件

Microsoft Entra ワークロード ID を使用してアクセスする

Microsoft Entra ワークロード ID は、ポッドで実行されているアプリケーションが、ソフトウェアのワークロードなどの他の Azure サービスに対してそれ自体を認証するために使用する ID です。 Secret Store CSI Driver は、外部 ID プロバイダーとのフェデレーションのために、ネイティブの Kubernetes 機能と統合されます。

このセキュリティ モデルでは、AKS クラスターはトークン発行者として機能します。 その後、Microsoft Entra ID で OIDC を使って公開署名キーが検出され、サービス アカウント トークンの信頼性が検証されてから、それと Microsoft Entra トークンが交換されます。 ワークロードがボリュームに投影されたサービス アカウント トークンを Microsoft Entra トークンと交換するには、Azure SDK または Microsoft Authentication Library (MSAL) の Azure ID クライアント ライブラリが必要です

Note

  • この認証方法は、Microsoft Entra のポッド マネージド ID (プレビュー) に代わるものです。 Azure Kubernetes Service のオープンソースの Microsoft Entra ポッドマネージド ID (プレビュー) は、2022 年 10 月 24 日の時点で非推奨となりました。
  • Microsoft Entra ワークロード ID は、Windows と Linux クラスターの両方をサポートします。

ワークロード ID を構成する

  1. az account set コマンドを使用してサブスクリプションを設定します。

    export SUBSCRIPTION_ID=<subscription id>
    export RESOURCE_GROUP=<resource group name>
    export UAMI=<name for user assigned identity>
    export KEYVAULT_NAME=<existing keyvault name>
    export CLUSTER_NAME=<aks cluster name>
    
    az account set --subscription $SUBSCRIPTION_ID
    
  2. az identity create コマンドを使用して、マネージド ID を作成します。

    az identity create --name $UAMI --resource-group $RESOURCE_GROUP
    
    export USER_ASSIGNED_CLIENT_ID="$(az identity show -g $RESOURCE_GROUP --name $UAMI --query 'clientId' -o tsv)"
    export IDENTITY_TENANT=$(az aks show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query identity.tenantId -o tsv)
    
  3. az role assignment createコマンドを使用して、キー コンテナーのシークレット、アクセス キー、証明書にアクセスするための権限をワークロード ID に付与するロールの割り当てを作成します。

    export KEYVAULT_SCOPE=$(az keyvault show --name $KEYVAULT_NAME --query id -o tsv)
    
    az role assignment create --role "Key Vault Administrator" --assignee $USER_ASSIGNED_CLIENT_ID --scope $KEYVAULT_SCOPE
    
  4. az aks show コマンドを使用して、AKS クラスターの OIDC 発行者 URL を取得します。

    Note

    この手順では、OIDC 発行者 URL が有効な既存の AKS クラスターがあることを前提としています。 有効にしていない場合は、「OIDC Issuer を備えた AKS クラスターを更新する」を参照して有効にしてください。

    export AKS_OIDC_ISSUER="$(az aks show --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv)"
    echo $AKS_OIDC_ISSUER
    
  5. Microsoft Entra アプリケーション、サービス アカウントの発行者、およびサブジェクトの間に、フェデレーション ID 資格情報を確立してください。 次のコマンドを使って、Microsoft Entra アプリケーションのオブジェクト ID を取得します。 必ず、serviceAccountNameserviceAccountNamespace の値を Kubernetes のサービス アカウント名とその名前空間で更新してください。

    export SERVICE_ACCOUNT_NAME="workload-identity-sa"  # sample name; can be changed
    export SERVICE_ACCOUNT_NAMESPACE="default" # can be changed to namespace of your workload
    
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID}
      name: ${SERVICE_ACCOUNT_NAME}
      namespace: ${SERVICE_ACCOUNT_NAMESPACE}
    EOF
    
  6. az identity federated-credential create コマンドを使用して、マネージド ID、サービス アカウント発行者、およびサブジェクト間のフェデレーション ID 資格情報を作成します。

    export FEDERATED_IDENTITY_NAME="aksfederatedidentity" # can be changed as needed
    
    az identity federated-credential create --name $FEDERATED_IDENTITY_NAME --identity-name $UAMI --resource-group $RESOURCE_GROUP --issuer ${AKS_OIDC_ISSUER} --subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}
    
  7. kubectl apply コマンドと次の YAML スクリプトを使用して SecretProviderClass をデプロイします。

    cat <<EOF | kubectl apply -f -
    # This is a SecretProviderClass example using workload identity to access your key vault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-kvname-wi # needs to be unique per namespace
    spec:
      provider: azure
      parameters:
        usePodIdentity: "false"
        clientID: "${USER_ASSIGNED_CLIENT_ID}" # Setting this to use workload identity
        keyvaultName: ${KEYVAULT_NAME}       # Set to the name of your key vault
        cloudName: ""                         # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
        objects:  |
          array:
            - |
              objectName: secret1             # Set to the name of your secret
              objectType: secret              # object types: secret, key, or cert
              objectVersion: ""               # [OPTIONAL] object versions, default to latest if empty
            - |
              objectName: key1                # Set to the name of your key
              objectType: key
              objectVersion: ""
        tenantId: "${IDENTITY_TENANT}"        # The tenant ID of the key vault
    EOF
    

    Note

    objectAlias の代わりに objectName を使用する場合は、それを考慮するように YAML スクリプトを更新してください。

    Note

    SecretProviderClass が正しく機能するには、objects セクションで参照する前に、必ず Azure Key Vault にシークレット、キー、または証明書を設定します。

  8. kubectl apply コマンドと次の YAML スクリプトを使用してサンプル ポッドをデプロイします。

    cat <<EOF | kubectl apply -f -
    # This is a sample pod definition for using SecretProviderClass and workload identity to access your key vault
    kind: Pod
    apiVersion: v1
    metadata:
      name: busybox-secrets-store-inline-wi
      labels:
        azure.workload.identity/use: "true"
    spec:
      serviceAccountName: "workload-identity-sa"
      containers:
        - name: busybox
          image: registry.k8s.io/e2e-test-images/busybox:1.29-4
          command:
            - "/bin/sleep"
            - "10000"
          volumeMounts:
          - name: secrets-store01-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "azure-kvname-wi"
    EOF
    

マネージド ID を使用したデプロイ

Microsoft Entra マネージド ID は、管理者が他の Azure サービスに対して自身を認証するために使用する ID です。 マネージド ID は、RBAC を使用して外部 ID プロバイダーとフェデレーションします。

このセキュリティ モデルでは、マネージド ロールを共有するチーム メンバーまたはテナントに、クラスターのリソースへのアクセス権を与えることができます。 ロールは、キー コンテナーやその他の資格情報にアクセスするためのスコープが確認されます。 AKS クラスターで Secrets Store CSI Driver に対して Azure Key Vault プロバイダーを有効にすると、ユーザー ID が作成されます。

マネージド ID を構成する

  1. az aks show コマンドと、アドオンによって作成されたユーザー割り当てマネージド ID を使用して、キー コンテナーにアクセスしてください。 ID の clientId も取得する必要があります。これは、後の手順で SecretProviderClass を作成するときに使います。

    az aks show -g <resource-group> -n <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.objectId -o tsv
    az aks show -g <resource-group> -n <cluster-name> --query addonProfiles.azureKeyvaultSecretsProvider.identity.clientId -o tsv
    

    または、次のコマンドを使用して、新しいマネージド ID を作成し、仮想マシン (VM) スケール セットまたは可用性セット内の各 VM インスタンスに割り当てることができます。

    az identity create -g <resource-group> -n <identity-name>
    az vmss identity assign -g <resource-group> -n <agent-pool-vmss> --identities <identity-resource-id>
    az vm identity assign -g <resource-group> -n <agent-pool-vm> --identities <identity-resource-id>
    
    az identity show -g <resource-group> --name <identity-name> --query 'clientId' -o tsv
    
  2. az role assignment create コマンドを使用して、キー コンテナーのシークレット、アクセス キー、証明書へのアクセス許可を ID に付与するロールの割り当てを作成してください。

    export IDENTITY_OBJECT_ID="$(az identity show -g <resource-group> --name <identity-name> --query 'principalId' -o tsv)"
    export KEYVAULT_SCOPE=$(az keyvault show --name <key-vault-name> --query id -o tsv)
    
    az role assignment create --role "Key Vault Administrator" --assignee $IDENTITY_OBJECT_ID --scope $KEYVAULT_SCOPE
    
  3. 次の YAML を使用して SecretProviderClass を作成します。 userAssignedIdentityIDkeyvaultNametenantId、およびキー コンテナーから取得するオブジェクトには、独自の値を使用するようにしてください。

    # This is a SecretProviderClass example using user-assigned identity to access your key vault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-kvname-user-msi
    spec:
      provider: azure
      parameters:
        usePodIdentity: "false"
        useVMManagedIdentity: "true"          # Set to true for using managed identity
        userAssignedIdentityID: <client-id>   # Set the clientID of the user-assigned managed identity to use
        keyvaultName: <key-vault-name>        # Set to the name of your key vault
        cloudName: ""                         # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
        objects:  |
          array:
            - |
              objectName: secret1
              objectType: secret              # object types: secret, key, or cert
              objectVersion: ""               # [OPTIONAL] object versions, default to latest if empty
            - |
              objectName: key1
              objectType: key
              objectVersion: ""
        tenantId: <tenant-id>                 # The tenant ID of the key vault
    

    注意

    objectName の代わりに objectAlias を使う場合は、必ず YAML スクリプトを更新してください。

    Note

    SecretProviderClass が正しく機能するには、objects セクションで参照する前に、必ず Azure Key Vault にシークレット、キー、または証明書を設定します。

  4. kubectl apply コマンドを使用して SecretProviderClass をクラスターに適用します。

    kubectl apply -f secretproviderclass.yaml
    
  5. 次の YAML を使用してポッドを作成します。

    # This is a sample pod definition for using SecretProviderClass and the user-assigned identity to access your key vault
    kind: Pod
    apiVersion: v1
    metadata:
      name: busybox-secrets-store-inline-user-msi
    spec:
      containers:
        - name: busybox
          image: registry.k8s.io/e2e-test-images/busybox:1.29-4
          command:
            - "/bin/sleep"
            - "10000"
          volumeMounts:
          - name: secrets-store01-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
      volumes:
        - name: secrets-store01-inline
          csi:
            driver: secrets-store.csi.k8s.io
            readOnly: true
            volumeAttributes:
              secretProviderClass: "azure-kvname-user-msi"
    
  6. kubectl apply コマンドを使用してポッドをクラスターに適用します。

    kubectl apply -f pod.yaml
    

Key Vault シークレットを検証する

ポッドが起動すると、デプロイ YAML で指定されたボリューム パスにマウントされたコンテンツが使用できるようになります。 次のコマンドを使って、シークレットを検証し、テスト シークレットを表示します。

  1. 次のコマンドを使用して、シークレット ストアに保持されているシークレットを表示します。

    kubectl exec busybox-secrets-store-inline-user-msi -- ls /mnt/secrets-store/
    
  2. 次のコマンドを使用して、ストアにシークレットを表示します。 このコマンド例は、テスト シークレット ExampleSecret を示しています。

    kubectl exec busybox-secrets-store-inline-user-msi -- cat /mnt/secrets-store/ExampleSecret
    

証明書とキーの取得

Azure Key Vault の設計では、キー、シークレット、証明書が明確に区別されます。 Key Vault サービスの証明書機能は、キーとシークレットの機能を利用して設計されます。 Key Vault 証明書が作成されると、アドレス指定可能なキーとシークレットが同じ名前で作成されます。 このキーを使用すると認証操作が可能になり、シークレットでは証明書の値をシークレットとして取得できます。

Key Vault 証明書には、公開 x509 証明書メタデータも含まれます。 Azure Key Vault によって証明書の公開と非公開の両方の部分がシークレットに格納されます。 SecretProviderClassobjectType を指定することで、個々のコンポーネントを取得できます。 次の表は、証明書に関連付けられているさまざまなリソースにマップされるオブジェクトを示しています。

Object 戻り値 証明書チェーン全体を返します
key Privacy Enhanced Mail (PEM) 形式の公開キー。 該当なし
cert PEM 形式の証明書。 いいえ
secret PEM 形式の秘密キーと証明書。 はい

既存のクラスターでアドオンを無効にする

Note

アドオンを無効にする前に、使用中の SecretProviderClassないことを確認してください。 SecretProviderClass が存在している間にアドオンを無効にしようとすると、エラーが発生します。

  • azure-keyvault-secrets-provider アドオンを指定して az aks disable-addons コマンドを使い、既存のクラスターで Secrets Store CSI Driver 用 Azure Key Vault プロバイダー機能を無効にします。

    az aks disable-addons --addons azure-keyvault-secrets-provider -g myResourceGroup -n myAKSCluster
    

Note

アドオンを無効にする場合、既存のワークロードに問題がないこと、またはマウントされたシークレットに更新プログラムが表示されることが必要です。 ポッドが再起動するか、スケールアップ イベントの一部として新しいポッドが作成された場合、ドライバーが実行されなくなるため、ポッドの起動に失敗します。

次のステップ

この記事では、Azure キー コンテナーにアクセスするための ID を作成して提供する方法について説明しました。 追加の構成オプションを構成する場合、またはトラブルシューティングを実行する場合は、次の記事に進んでください。