將 Azure 身分識別提供者 連線 至 Azure Kubernetes Service 中的 Azure 金鑰保存庫 秘密存放區 CSI 驅動程式 (AKS)

Azure Kubernetes Service 上的秘密存放區容器 儲存體 介面 (CSI) 驅動程式 (AKS) 提供各種識別型存取 Azure 金鑰保存庫 的方法。 本文概述使用角色型訪問控制 (RBAC) 或 OpenID 連線 (OIDC) 安全性模型來存取金鑰保存庫和 AKS 叢集的時機這些方法和最佳做法。

您可以使用下列其中一個存取方法:

CSI 驅動程式的必要條件

使用 Microsoft Entra 工作負載 ID 存取

Microsoft Entra 工作負載 ID 是 Pod 上執行的應用程式用來向其他 Azure 服務進行驗證的身分識別,例如軟體中的工作負載。 秘密存放區 CSI 驅動程式會與原生 Kubernetes 功能整合,以與外部識別提供者同盟。

在此安全性模型中,AKS 叢集會作為令牌簽發者。 然後,Microsoft Entra 識別符會使用 OIDC 來探索公開簽署密鑰,並在交換服務帳戶令牌之前驗證服務帳戶令牌的真實性。 若要讓工作負載交換投影到其磁碟區的服務帳戶令牌以取得 Microsoft Entra 令牌,您需要 Azure SDK 中的 Azure 身分識別客戶端連結庫或 Microsoft 驗證連結庫 (MSAL)

注意

  • 此驗證方法會取代 Microsoft Entra Pod 受控識別(預覽)。 自 2022 年 10 月 24 日起,Azure Kubernetes Service 中的 開放原始碼 Microsoft Entra Pod 受控識別 (預覽版) 已被取代。
  • Microsoft Entra 工作負載 ID 同時支援 Windows 和 Linux 叢集。

設定工作負載身分識別

  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 命令建立受控識別。

    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 命令存取密鑰保存庫秘密、存取密鑰和憑證。

    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。

    注意

    此步驟假設您有已啟用 OIDC 簽發者 URL 的現有 AKS 叢集。 如果您尚未啟用它,請參閱 使用 OIDC 簽發者 更新 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 應用程式、服務帳戶簽發者和主體之間建立同盟身分識別認證。 使用下列命令取得 Microsoft Entra 應用程式的物件識別碼。 請務必使用 Kubernetes 服務帳戶名稱和其命名空間來更新 和 serviceAccountNamespace 的值serviceAccountName

    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 命令,在受控識別、服務帳戶簽發者和主體之間建立同盟身分識別認證。

    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. SecretProviderClass使用 kubectl apply 命令與下列 YAML 指令稿部署 。

    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
    

    注意

    如果您使用 objectAlias 而非 objectName,請更新 YAML 腳本來加以考慮。

    注意

    若要讓 SecretProviderClass 正常運作,請務必在本節中objects參考秘密、密鑰或憑證之前,先填入您的 Azure 金鑰保存庫。

  8. 使用 kubectl apply 命令和下列 YAML 腳本部署範例 Pod。

    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
    

使用受控識別進行存取

Microsoft Entra 受控標識碼是系統管理員用來向其他 Azure 服務驗證自己的身分識別。 受控識別會使用 RBAC 與外部識別提供者同盟。

在此安全性模型中,您可以將叢集資源的存取權授與共享受控角色的小組成員或租使用者。 角色會檢查範圍以存取keyvault和其他認證。 當您在 AKS 叢集上啟用適用於秘密存放區 CSI 驅動程式的 Azure 金鑰保存庫 提供者時,它會建立使用者身分識別。

設定受控識別

  1. 使用 az aks show 命令和附加元件所建立的使用者指派受控識別來存取密鑰保存庫。 您也應該擷取身分識別的 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
    

    或者,您可以建立新的受控識別,並使用下列命令將它指派給虛擬機器(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 命令授與密鑰保存庫秘密、存取密鑰和憑證的身分識別許可權存取權。

    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. SecretProviderClass使用下列 YAML 建立 。 請務必針對 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
    

    注意

    如果您使用 objectAlias 而非 objectName,請務必更新 YAML 腳本。

    注意

    為了讓 SecretProviderClass 能夠正常運作,請務必在本節中objects參考秘密、密鑰或憑證之前,先填入您的 Azure 金鑰保存庫。

  4. SecretProviderClass使用 命令將 套用kubectl apply至您的叢集。

    kubectl apply -f secretproviderclass.yaml
    
  5. 使用下列 YAML 建立 Pod。

    # 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. 使用 命令將 Pod 套用 kubectl apply 至叢集。

    kubectl apply -f pod.yaml
    

驗證 金鑰保存庫 秘密

Pod 啟動之後,您可以在部署 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 金鑰保存庫 設計會區分密鑰、秘密和憑證。 金鑰保存庫 服務的憑證功能是設計來使用密鑰和秘密功能。 當您建立金鑰保存庫憑證時,它會建立具有相同名稱的可尋址密鑰和秘密。 此密鑰允許驗證作業,而秘密允許擷取憑證值做為秘密。

金鑰保存庫憑證也包含公用 x509 憑證元數據。 金鑰保存庫會將憑證的公用和私用元件儲存在秘密中。 您可以藉由在 objectTypeSecretProviderClass指定 來取得每個個別元件。 下表顯示哪些物件對應至與憑證相關聯的各種資源:

Object 傳回值 傳回整個憑證鏈結
key 公鑰,格式為 Privacy Enhanced Mail (PEM)。 N/A
cert PEM 格式的憑證。 No
secret 私鑰和憑證,格式為 PEM。 Yes

停用現有叢集上的附加元件

注意

停用附加元件之前,請確定 SecretProviderClass 使用中。 嘗試在 存在時 SecretProviderClass 停用附加元件會導致錯誤。

  • 使用 az aks disable-addons 命令搭配azure-keyvault-secrets-provider附加元件,停用現有叢集中秘密存放區 CSI 驅動程式功能的 Azure 金鑰保存庫 提供者。

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

注意

當您停用附加元件時,現有的工作負載應該沒有任何問題,或看到掛接的秘密中的任何更新。 如果 Pod 重新啟動或建立新的 Pod 作為相應增加事件的一部分,Pod 將無法啟動,因為驅動程式不再執行。

下一步

在本文中,您已瞭解如何建立並提供身分識別來存取 Azure 金鑰保存庫。 如果您想要設定額外的組態選項或執行疑難解答,請繼續進行下一篇文章。