在 AKS 和 EKS 上啟用 Workload Identity Federation

本主題說明如何為 AKS 和 EKS 平台上的 Apigee hybrid 安裝啟用 Workload Identity Federation。

如要在 GKE 上安裝,請按照「在 GKE 上啟用 Workload Identity Federation for GKE」一文的操作說明操作。

總覽

Workload Identity Federation 可讓在 Google Cloud 外部執行的應用程式,使用外部身分提供者的憑證,模擬 Google Cloud Platform 服務帳戶。

使用 Workload Identity Federation,可讓應用程式採用外部環境提供的驗證機制,並取代服務帳戶金鑰,進而提升安全性。

如需總覽,請參閱「使用 Workload Identity Federation 的最佳做法」。

設定 Workload Identity Federation

如要搭配使用 Workload Identity Federation 與 Apigee hybrid,請先設定叢集,然後將這項功能套用至 Apigee hybrid 安裝。

事前準備

這些操作說明假設您已完成 Apigee Hybrid 安裝作業。IAM 服務帳戶和 Kubernetes 服務帳戶會在初始安裝期間建立。如需安裝 Apigee Hybrid 的總覽,請參閱「總覽」。

如要在 AKS 上安裝,請務必啟用 OpenID Connect (OIDC) 核發者。您必須啟用這項功能,Workload Identity Federation 才能存取叢集的 OpenID Connect 中繼資料和 JSON Web Key Set (JWKS)。

將叢集設為使用 Workload Identity Federation。

  1. 使用下列指令,確認目前的 gcloud 設定已設為 Google Cloud 專案 ID:
    gcloud config get project
  2. 視需要設定目前的 gcloud 設定:

    gcloud config set project PROJECT_ID
  3. 啟用 Security Token Service API:

    使用下列指令,確認已啟用 Security Token Service API:

    gcloud services list --enabled --project PROJECT_ID | grep sts.googleapis.com

    如果 API 尚未啟用:

    控制台

    啟用 Security Token Service API (如果尚未啟用)。

    啟用 API 所需的角色

    您必須具備 serviceusage.services.enable 權限,才能啟用 API。如果您建立了專案,可能已透過「擁有者」角色 (roles/owner) 取得這項權限。否則,您可以透過「Service Usage 管理員」角色 (roles/serviceusage.serviceUsageAdmin) 取得這項權限。瞭解如何授予角色。

    啟用 API

    指令列

    使用下列指令啟用 API:

    gcloud services enable sts.googleapis.com --project PROJECT_ID
  4. 建立 workload identity pool 和提供者。

    必要的角色

    如要取得設定 Workload Identity Federation 所需的權限,請要求管理員授予您專案的下列 IAM 角色:

    如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和組織的存取權」。

    您或許也能透過自訂角色或其他預先定義的角色,取得必要權限。

    或者,IAM 擁有者 (roles/owner) 基本角色也包含設定身分聯盟的權限。請勿在正式環境中授予基本角色,但可以在開發或測試環境中授予。

    如要建立 workload identity pool 和提供者,請按照下列步驟操作:

    1. 判斷 AKS 叢集的核發者網址:

      AKS

      az aks show -n NAME -g RESOURCE_GROUP --query "oidcIssuerProfile.issuerUrl" -otsv

      更改下列內容:

      • NAME:叢集名稱。
      • RESOURCE_GROUP:叢集的資源群組。

      指令會輸出核發者網址。在後續步驟中,您會需要核發者網址。

      如果指令未傳回核發者網址,請確認您已啟用 OIDC 核發者功能。

      EKS

      aws eks describe-cluster --name NAME --query "cluster.identity.oidc.issuer" --output text
      

      將 NAME 替換為叢集名稱。

      指令會輸出核發者網址。您在後續步驟中會需要核發者網址。

      其他 Kubernetes

      連線至 Kubernetes 叢集,並使用「kubectl」判斷叢集的核發者網址:

      kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
      

      您在後續步驟中會需要核發者網址。

    2. 選用:如果 OIDC 發行者不開放公開存取,請下載叢集的 JSON Web Key Set (JWKS):
      kubectl get --raw /openid/v1/jwks > cluster-jwks.json
      

      如要確認 OIDC 供應商是否公開,您應該能使用 CURL 指令存取供應商網址,並收到 200 回應。

    3. 建立新的 workload identity pool:
      gcloud iam workload-identity-pools create POOL_ID \
        --location="global" \
        --description="DESCRIPTION" \
        --display-name="DISPLAY_NAME"
                  

      更改下列內容:

      • POOL_ID:集區的專屬 ID。
      • DISPLAY_NAME:(選用) 集區名稱。
      • DESCRIPTION:(選用) 您選擇的集區說明。授予集區身分的存取權時,會顯示這段說明。

      例如:

      gcloud iam workload-identity-pools create my-wi-pool --display-name="My workload pool" --description="My workload pool description"
    4. 將叢集新增為 workload identity pool 提供者。根據 OIDC 核發者是否可公開存取,選擇建立提供者的指令:

      可公開存取

      如果 OIDC 核發者可公開存取,請使用下列指令建立提供者:

      gcloud iam workload-identity-pools providers create-oidc WORKLOAD_PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --attribute-mapping="google.subject=assertion.sub"

      不公開

      如果 OIDC 核發者無法公開存取,請使用下列指令建立提供者:

        gcloud iam workload-identity-pools providers create-oidc WORKLOAD_PROVIDER_ID \
        --location="global" \
        --workload-identity-pool="POOL_ID" \
        --issuer-uri="ISSUER" \
        --jwks-file="cluster-jwks.json" \
        --attribute-mapping="google.subject=assertion.sub"

      更改下列內容:

      • WORKLOAD_PROVIDER_ID:您選擇的不重複 workload identity pool 提供者 ID。
      • POOL_ID::您先前建立的 workload identity pool ID 。
      • ISSUER:使用先前確定的核發者網址做為核發者 URI。

      attribute-mapping="google.subject=assertion.sub" 會將 Kubernetes 主體對應至 IAM 主體。

建立憑證設定檔

如要部署可存取 Google Cloud 資源的 Kubernetes 工作負載,請先為每個 IAM 服務帳戶建立憑證設定檔:

  1. 使用下列指令,列出 IAM 服務帳戶 (也稱為「Google 服務帳戶」):
    gcloud iam service-accounts list --project PROJECT_ID

    您需要為下列 IAM 服務帳戶建立憑證設定檔:

    Prod

    正式環境:

    DISPLAY NAME                 EMAIL                                                              DISABLED
    apigee-cassandra             apigee-cassandra@my_project_id.iam.gserviceaccount.com             False
    apigee-mart                  apigee-mart@my_project_id.iam.gserviceaccount.com                  False
    apigee-metrics               apigee-metrics@my_project_id.iam.gserviceaccount.com               False
    apigee-runtime               apigee-runtime@my_project_id.iam.gserviceaccount.com               False
    apigee-synchronizer          apigee-synchronizer@my_project_id.iam.gserviceaccount.com          False
    apigee-udca                  apigee-udca@my_project_id.iam.gserviceaccount.com                  False
    apigee-watcher               apigee-watcher@my_project_id.iam.gserviceaccount.com               False
    

    如果您在 v1.15.1 以上版本使用 Apigee hybrid 營利功能,也需要為 apigee-mint-task-scheduler 服務帳戶建立憑證設定檔。

    DISPLAY NAME                 EMAIL                                                              DISABLED
    ...
    apigee-mint-task-scheduler   apigee-mint-task-scheduler@my_project_id.iam.gserviceaccount.com   False
    ...

    非正式環境

    非正式環境:

    DISPLAY NAME         EMAIL                                                      DISABLED
    apigee-non-prod      apigee-non-prod@my-project.iam.gserviceaccount.com      False
    
  2. 為上一個清單中的每個 IAM 服務帳戶建立憑證設定檔。您需要這些憑證設定檔,才能設定 Apigee hybrid 使用 Workload Identity Federation:

    Code

    gcloud iam workload-identity-pools create-cred-config \
      projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/WORKLOAD_PROVIDER_ID \
      --service-account=SERVICE_ACCOUNT_EMAIL \
      --credential-source-file=/var/run/service-account/token \
      --credential-source-type=text \
      --output-file=SERVICE_ACCOUNT_NAME-credential-configuration.json
      

    範例

    gcloud iam workload-identity-pools create-cred-config \
      projects/123123123123/locations/global/workloadIdentityPools/my-wi-pool/providers/my-wi-provider \
      --service-account=apigee-cassandra@myhybridporg.iam.gserviceaccount.com \
      --credential-source-file=/var/run/service-account/token \
      --credential-source-type=text \
      --output-file=apigee-cassandra-credential-configuration.json
      

    其中:

    • PROJECT_NUMBER:workload identity pool 所在專案的專案編號。請務必使用專案編號,而非專案 ID。
    • POOL_ID:workload identity pool 的 ID
    • WORKLOAD_PROVIDER_ID:workload identity pool 提供者的 ID
    • SERVICE_ACCOUNT_EMAIL:服務帳戶的電子郵件地址 (如果您將 Kubernetes ServiceAccount 設為使用 IAM 服務帳戶模擬)。

    [Cloud 用戶端程式庫](/apis/docs/cloud-client-libraries)、gcloud CLI 和 Terraform 會根據憑證設定檔判斷下列事項:

    • 外部憑證的取得來源
    • 要使用的 workload identity pool 和提供者
    • 要模擬的服務帳戶

設定 Apigee Hybrid 以使用 Workload Identity Federation

  1. 將每個輸出檔案 (SERVICE_ACCOUNT_NAME-credential-configuration.json) 複製或移至下列圖表目錄 (或其子目錄)。這些檔案是您在「建立憑證設定檔」步驟中建立的。

    Prod

    服務帳戶 Apigee Helm chart 目錄
    apigee-cassandra apigee-datastore/
    apigee-mart apigee-org/
    apigee-metrics apigee-telemetry/
    apigee-mint-task-scheduler
    (如果使用 Apigee Hybrid 的營利功能)
    apigee-org/
    apigee-runtime apigee-env/
    apigee-synchronizer apigee-env/
    apigee-udca apigee-org/
    apigee-env/
    apigee-watcher apigee-org/

    非正式環境

    服務帳戶 Apigee Helm 圖表
    apigee-non-prod apigee-datastore/
    apigee-telemetry/
    apigee-org/
    apigee-env/
  2. 對叢集的覆寫檔案進行下列全域變更:

    程式碼

    gcp:
      workloadIdentity:
        enabled: false # must be set to false to use Workload Identity Federation
      federatedWorkloadIdentity:
        enabled: true
        audience: "AUDIENCE"
        credentialSourceFile: "/var/run/service-account/token"
    

    範例

    gcp:
      workloadIdentity:
        enabled: false
      federatedWorkloadIdentity:
        enabled: true
        audience: "//iam.googleapis.com/projects/123123123123/locations/global/workloadIdentityPools/my-wi-pool/providers/my-wi-provider"
        credentialSourceFile: "/var/run/service-account/token"
    

    其中 AUDIENCE 是 Workload Identity Provider 允許的目標對象。您可以在任何憑證設定檔中搜尋 audience: ,找出這個值。每個憑證設定檔中的目標對象值都相同。

    舉例來說,在下列 apigee-udca-credential-configuration.json 檔案範例中:

    {
      "universe_domain": "googleapis.com",
      "type": "external_account:,"
      "audience": "//iam.googleapis.com/projects/123123123123/locations/global/workloadIdentityPools/my-wi-pool/providers/my-wi-provider",
      "subject_token_type": "urn:ietf:params:oauth: token-type:jwt",
      "token_url": "https://sts.googleapis.com/v1/token",
      "service
      "impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/apigee-udca@my-project.iam.gserviceaccount.com:generateAccessToken",
      "credential_source": {
        "file": "/var/run/service-account/token",
        "format": {
          "type": "text"
        }
      }
    }

    目標對象值為 //iam.googleapis.com/projects/123123123123/locations/global/workloadIdentityPools/my-wi-pool/providers/my-wi-provider。

  3. 使用 Workload Identity Federation 設定各元件的覆寫值。請根據安裝方式,選取 JSON 檔案、Kubernetes Secret 或 Vault 的操作說明。

    憑證檔案

    將 serviceAccountPath 的值替換為對應 IAM 服務帳戶的憑證來源檔案。這必須是相對於圖表目錄的路徑。例如:

    envs:
    - name: ENVIRONMENT_NAME
      serviceAccountPaths:
        synchronizer: apigee-synchronizer-credential-configuration.json
        runtime: apigee-runtime-credential-configuration.json
        udca: apigee-udca-credential-configuration.json
    
    mart:
      serviceAccountPath: apigee-mart-credential-configuration.json
    
    connectAgent:
      serviceAccountPath: apigee-mart-credential-configuration.json
    
    metrics:
      serviceAccountPath: apigee-metrics-credential-configuration.json
    
    mintTaskScheduler: # Required for Monetization for Apigee hybrid (v1.15.1 and later)
      serviceAccountPath: apigee-mint-task-scheduler-credential-configuration.json
    
    udca:
      serviceAccountPath: apigee-udca-credential-configuration.json
    
    watcher:
      serviceAccountPath: apigee-watcher-credential-configuration.json
    

    K8s Secret

    1. 使用每個憑證設定檔的憑證來源檔案,建立新的 Kubernetes Secret。
      kubectl create secret -n APIGEE_NAMESPACE generic SECRET_NAME --from-file="client_secret.json=CREDENTIAL_CONFIGURATION_FILE"

      例如:

      kubectl create secret -n apigee generic udca-workload-identity-secret --from-file="client_secret.json=./apigee-udca-credential-configuration.json"
    2. 將 serviceAccountRef 的值替換為新密鑰。例如:
      udca:
        serviceAccountRef: udca-workload-identity-secret
      

    保管箱

    使用對應的憑證來源檔案,更新 Vault 中每個服務帳戶的服務帳戶金鑰 SAKEY。所有元件的程序都類似。以 UDCA 為例:

    SAKEY=$(cat .apigee-udca-credential-configuration.json); kubectl -n APIGEE_NAMESPACE exec vault-0 -- vault kv patch secret/apigee/orgsakeys udca="$SAKEY"

    詳情請參閱 Storing service account keys in Hashicorp Vault。

  4. 使用 helm upgrade 指令,將變更套用至每個受影響的元件:

    如果您更新了 Vault 服務帳戶金鑰,請更新 apigee-operator 圖表。

    helm upgrade operator apigee-operator/ \
      --namespace APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml
    

    按照下列順序更新其餘受影響的圖表:

    helm upgrade datastore apigee-datastore/ \
      --namespace APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml
    
    helm upgrade telemetry apigee-telemetry/ \
      --namespace APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml
    
    helm upgrade $ORG_NAME apigee-org/ \
      --namespace APIGEE_NAMESPACE \
      --atomic \
      -f overrides.yaml
    

    更新每個環境的 apigee-env 圖表,每次都替換 $ENV_RELEASE_NAME 和 ENV_NAME:

    helm upgrade $ENV_RELEASE_NAME apigee-env/ \
      --namespace APIGEE_NAMESPACE \
      --atomic \
      --set env=$ENV_NAME \
      -f overrides.yaml
    

    如需元件及其對應圖表的清單,請參閱 Apigee hybrid Helm 參考資料。

將存取權授予 Kubernetes 服務帳戶

  1. 使用下列指令列出 Kubernetes 服務帳戶:
    kubectl get sa -n APIGEE_NAMESPACE
  2. 授予 Kubernetes 服務帳戶權限,模擬相關聯的 IAM 服務帳戶,如下表所示。表格會顯示預設的 Apigee IAM 服務帳戶名稱。如果您使用自訂服務帳戶名稱,請使用對應的身分與存取權管理服務帳戶:
    Kubernetes 服務帳戶 IAM 服務帳戶
    組織層級 Kubernetes 服務帳戶
    apigee-connect-agent-ORG_NAME-ORG_HASH_ID apigee-mart
    apigee-mart-ORG_NAME-ORG_HASH_ID apigee-mart
    apigee-metrics-apigee-telemetry apigee-metrics
    apigee-open-telemetry-collector-apigee-telemetry apigee-metrics
    apigee-mint-task-scheduler-ORG_NAME-ORG_HASH_ID
    (如果使用 Apigee Hybrid 的營利功能)
    apigee-mint-task-scheduler
    apigee-udca-ORG_NAME-ORG_HASH_ID apigee-udca
    apigee-watcher-ORG_NAME-ORG_HASH_ID apigee-watcher
    環境層級 Kubernetes 服務帳戶
    apigee-runtime-ORG_NAME-ENV_NAME-ENV_HASH_ID apigee-runtime
    apigee-synchronizer-ORG_NAME-ENV_NAME-ENV_HASH_ID apigee-synchronizer
    Cassandra 備份與還原 (如已啟用)
    apigee-cassandra-backup-sa apigee-cassandra
    apigee-cassandra-restore-sa apigee-cassandra

    其中:

    • ORG_NAME:貴組織名稱的前 15 個字元。
    • ORG_HASH_ID:組織全名的不重複雜湊 ID。
    • ENV_NAME:環境名稱的前 15 個字元。
    • ENV_HASH_ID:組織和環境名稱的不重複雜湊 ID。

    例如:

    • apigee-connect-agent-myhybridorg-123abcd
    • apigee-runtime-myhybridorg-prodenv-234bcde

    使用下列指令,授予各個 Kubernetes 服務帳戶模擬適當 IAM 服務帳戶的權限:

    gcloud iam service-accounts add-iam-policy-binding \
      IAM_SA_NAME@PROJECT_ID.iam.gserviceaccount.com \
        --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/subject/MAPPED_SUBJECT" \
        --role=roles/iam.workloadIdentityUser

    其中:

    • IAM_SA_NAME:服務帳戶的名稱。
    • PROJECT_ID:與 Apigee 組織相關聯的專案 ID。
    • PROJECT_NUMBER:您建立 workload identity pool 的專案編號。
    • POOL_ID:workload identity pool ID。
    • MAPPED_SUBJECT:對應至 google.subject 的 ID 權杖中,宣告的 Kubernetes ServiceAccount。舉例來說,如果您對應 google.subject=assertions.sub,且 ID 權杖包含 "sub": "system:serviceaccount:default:my-kubernetes-serviceaccount",則 MAPPED_SUBJECT 為 system:serviceaccount:default:my-kubernetes-serviceaccount。

如要進一步瞭解 Workload Identity Federation 和最佳做法,請參閱「使用 Workload Identity Federation 的最佳做法」。