從共用信任的機群工作負載向 Google Cloud API 驗證身分

本頁面說明如何設定應用程式,以便從機群向Google Cloud Compute Engine API 或 AI Platform API 等 API 進行驗證,這些機群在整個機群中具有共用的信任模型。如果機群的信任模型不一,請參閱「Authenticate to Google Cloud APIs from mixed-trust fleet workloads」(預先發布版)。

本頁面適用於平台管理員和營運人員,以及想要透過程式從車隊工作負載向 Google CloudAPI 進行驗證的安全工程師。如要進一步瞭解說明文件中提及的使用者角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。 Google Cloud

閱讀本頁面之前,請務必熟悉下列概念:

關於共用信任環境的機群 Workload Identity 聯盟

機群 Workload Identity 聯盟可讓您使用內建Google Cloud 和 Kubernetes 驗證機制,從機群工作負載向 API 進行驗證。 Google Cloud 使用 Fleet Workload Identity 聯盟,就不必使用安全性較低的方法,例如在 Pod 中掛接存取權杖,或儲存長期有效的憑證。

根據預設,機群主專案會使用 Google 管理的工作負載身分集區,為整個機群中的實體佈建身分。機群或機群主專案中具有相同 IAM 識別碼的任何實體,都會被 IAM 視為同一項目。在共用信任環境 (例如單一租戶機群) 中大規模授予存取權時,這種隱含的身分相同性很有用,因為其他實體是否無意間取得資源的類似權限並不重要。

事前準備

  • 確認您已安裝下列指令列工具:

    如果您使用 Cloud Shell 做為與 Google Cloud互動的 Shell 環境,系統會為您安裝這些工具。

  • 確認您已初始化 gcloud CLI,以便搭配專案使用。

準備您的叢集

機群中的應用程式必須先註冊至機群,並正確設定使用機群 Workload Identity Federation,才能接收聯盟身分。下列各節說明如何為不同類型的叢集設定機群 Workload Identity 聯盟。

GKE

如果是 GKE 叢集,請按照下列步驟操作:

  1. 如果尚未啟用,請在 Google Kubernetes Engine 叢集上啟用 GKE 的 Workload Identity 聯盟
  2. 向機群註冊叢集

您也可以在建立叢集和註冊車隊時,啟用 Workload Identity Federation for GKE。

外部叢集 Google Cloud

下列類型的叢集會自動啟用機群工作負載身分聯合驗證,並在建立叢集時註冊至機群:

  • VMware 上的 Google Distributed Cloud (僅限軟體)
  • 裸機上的 Google Distributed Cloud (僅限軟體)
  • GKE on AWS
  • GKE on Azure

附加的叢集

使用 GKE Multi-Cloud API 註冊的 EKS 和 AKS 附加叢集,預設會啟用機群 Workload Identity 聯盟。如果其他附加叢集符合必要條件,即可註冊啟用機群 Workload Identity 聯盟。請按照「註冊叢集」一文中的叢集類型操作說明進行。

在應用程式中使用機群 Workload Identity 聯盟

下列步驟說明如何設定已註冊叢集中的工作負載,以使用機群 Workload Identity 聯盟:

  1. 找出叢集工作負載身分集區和身分識別提供者的名稱:

    gcloud container fleet memberships describe MEMBERSHIP_ID \
        --project=FLEET_PROJECT_ID \
        --format="table(authority.identityProvider,authority.workloadIdentityPool,name)"
    

    更改下列內容:

    • MEMBERSHIP_ID:叢集成員名稱。這通常是叢集的名稱。
    • FLEET_PROJECT_ID:機群主機專案的專案 ID。

    輸出結果會與下列內容相似:

    IDENTITY_PROVIDER: IDENTITY_PROVIDER
    WORKLOAD_IDENTITY_POOL: WORKLOAD_IDENTITY_POOL
    NAME: projects/FLEET_PROJECT_ID/locations/MEMBERSHIP_LOCATION/memberships/MEMBERSHIP_ID
    

    這項輸出內容包含下列資訊:

    • IDENTITY_PROVIDER:叢集的 IDP。
    • MEMBERSHIP_LOCATION:車隊會員的位置。這通常與叢集位置相同。
    • WORKLOAD_IDENTITY_POOL:與 Fleet 相關聯的workload identity pool 名稱。這個值的語法為 FLEET_PROJECT_ID.svc.id.goog
  2. 建立 Kubernetes 命名空間。您也可以使用任何現有命名空間,包括 default 命名空間。

    kubectl create namespace NAMESPACE
    

    NAMESPACE 替換為命名空間的名稱。

  3. 在命名空間中建立新的 Kubernetes ServiceAccount。您也可以使用任何現有的 ServiceAccount,包括命名空間中的 default ServiceAccount。

    kubectl create serviceaccount KSA_NAME \
        --namespace=NAMESPACE
    

    KSA_NAME 改為 ServiceAccount 的名稱。

  4. 將下列資訊清單儲存為 adc-config-map.yaml。這個 ConfigMap 包含工作負載的 ADC 設定。

    kind: ConfigMap
    apiVersion: v1
    metadata:
      namespace: NAMESPACE
      name: my-cloudsdk-config
    data:
      config: |
        {
          "type": "external_account",
          "audience": "identitynamespace:WORKLOAD_IDENTITY_POOL:IDENTITY_PROVIDER",
          "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
          "token_url": "https://sts.googleapis.com/v1/token",
          "credential_source": {
            "file": "/var/run/secrets/tokens/gcp-ksa/token"
          }
        }
    
  5. 部署 ConfigMap:

    kubectl create -f adc-config-map.yaml
    
  6. 將下列資訊清單儲存為 workload-config.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
      namespace:  NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      containers:
      - name: sample-container
        image: google/cloud-sdk:slim
        command: ["sleep","infinity"]
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /var/run/secrets/tokens/gcp-ksa/google-application-credentials.json
        volumeMounts:
        - name: gcp-ksa
          mountPath: /var/run/secrets/tokens/gcp-ksa
          readOnly: true
      volumes:
      - name: gcp-ksa
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              path: token
              audience: WORKLOAD_IDENTITY_POOL
              expirationSeconds: 172800
          - configMap:
              name: my-cloudsdk-config
              optional: false
              items:
              - key: "config"
                path: "google-application-credentials.json"
    

    部署這項工作負載時,Pod 中的 gcp-ksa 磁碟區會包含下列資料:

    • 您部署的 ConfigMap 中的資料,會以 google-application-credentials.json 為檔名。這個檔案是 ADC 憑證設定檔
    • Kubernetes ServiceAccount 權杖,格式為 token。Kubernetes 會將 ServiceAccount 的已簽署 JWT 掛接為投射的 ServiceAccount 權杖檔案

    Pod 中的容器會將 gcp-ksa 磁碟區掛接到 /var/run/secrets/tokens/gcp-ksa 路徑,並設定 ADC 在該路徑中尋找憑證設定 JSON 檔案。

  7. 部署工作負載:

    kubectl apply -f workload-config.yaml
    

替代做法:模擬 IAM 服務帳戶

或者,您也可以在叢集中設定 Kubernetes ServiceAccount,模擬 IAM 服務帳戶並執行 IAM 服務帳戶可執行的任何授權動作。這種做法可能會增加維護負擔,因為您必須在 IAM 和 Kubernetes 中管理服務帳戶配對。

在大多數情況下,建議您直接在 IAM 允許政策中參照 Kubernetes 主體,按照「在應用程式中使用 Fleet Workload Identity Federation」一文中的操作說明,授予Google Cloud 資源的存取權。

  1. 找出叢集工作負載身分集區和身分識別提供者的名稱:

    gcloud container fleet memberships describe MEMBERSHIP_ID \
        --project=FLEET_PROJECT_ID \
        --format="table(authority.identityProvider,authority.workloadIdentityPool,name)"
    

    更改下列內容:

    • MEMBERSHIP_ID:叢集成員名稱。這通常是叢集的名稱。
    • FLEET_PROJECT_ID:機群主機專案的專案 ID。

    輸出結果會與下列內容相似:

    IDENTITY_PROVIDER: IDENTITY_PROVIDER
    WORKLOAD_IDENTITY_POOL: WORKLOAD_IDENTITY_POOL
    NAME: projects/FLEET_PROJECT_ID/locations/MEMBERSHIP_LOCATION/memberships/MEMBERSHIP_ID
    

    這項輸出內容包含下列資訊:

    • IDENTITY_PROVIDER:叢集的 IDP。
    • MEMBERSHIP_LOCATION:會員方案的適用地區。這通常與叢集位置相同。
    • WORKLOAD_IDENTITY_POOL:與 Fleet 相關聯的workload identity pool 名稱。這個值的語法為 FLEET_PROJECT_ID.svc.id.goog
  2. 建立應用程式可模擬的 IAM 服務帳戶。您也可以使用任何現有的 IAM 服務帳戶。

    gcloud iam service-accounts create IAM_SA_NAME \
        --project=IAM_SA_PROJECT_ID
    

    更改下列內容:

    • IAM_SA_NAME:IAM 服務帳戶的名稱。
    • IAM_SA_PROJECT_ID:含有 IAM 服務帳戶的專案 ID。這可能與機群主專案不同。
  3. 新增必要的 IAM 允許政策,授予 IAM 服務帳戶存取 Google Cloud API 所需的任何權限。您可以使用 gcloud iam service-accounts add-iam-policy-binding其他方法達成此目的。如要瞭解使用 Google Cloud API 時需要哪些權限,請參閱各項服務的說明文件,並在「瞭解角色」中查看具備必要權限的預先定義角色完整清單。

  4. 在命名空間中建立 Kubernetes ServiceAccount。您也可以使用現有的 Kubernetes ServiceAccount 和任何命名空間,包括 default ServiceAccount 和 default 命名空間。

    kubectl create serviceaccount KSA_NAME \
        --namespace=NAMESPACE
    

    更改下列內容:

    • KSA_NAME:ServiceAccount 的名稱。
    • NAMESPACE:命名空間的名稱。
  5. 建立 IAM 允許政策,讓叢集特定命名空間中的 Kubernetes ServiceAccount 模擬 IAM 服務帳戶:

    gcloud iam service-accounts add-iam-policy-binding IAM_SA_NAME@IAM_SA_PROJECT_ID.iam.gserviceaccount.com \
        --project=IAM_SA_PROJECT_ID \
        --role=roles/iam.workloadIdentityUser \
        --member="serviceAccount:WORKLOAD_IDENTITY_POOL[NAMESPACE/KSA_NAME]"
    

    WORKLOAD_IDENTITY_POOL 替換為工作負載身分集區的名稱。

  6. 將下列資訊清單儲存為 adc-config-map.yaml。這個 ConfigMap 包含工作負載的 ADC 設定。

    kind: ConfigMap
    apiVersion: v1
    metadata:
      namespace: K8S_NAMESPACE
      name: my-cloudsdk-config
    data:
      config: |
        {
          "type": "external_account",
          "audience": "identitynamespace:WORKLOAD_IDENTITY_POOL:IDENTITY_PROVIDER",
          "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/IAM_SA_NAME@GSA_PROJECT_ID.iam.gserviceaccount.com:generateAccessToken",
          "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
          "token_url": "https://sts.googleapis.com/v1/token",
          "credential_source": {
            "file": "/var/run/secrets/tokens/gcp-ksa/token"
          }
        }
    

    更改下列內容:

    • IAM_SA_NAME:要模擬的 IAM 服務帳戶名稱。
    • IAM_SA_PROJECT_ID:IAM 服務帳戶的專案 ID。
  7. 將下列資訊清單儲存為 workload-config.yaml

    apiVersion: v1
    kind: Pod
    metadata:
      name: my-pod
      namespace:  K8S_NAMESPACE
    spec:
      serviceAccountName: KSA_NAME
      containers:
      - name: my-container
        image: my-image
        command: ["sleep","infinity"]
        env:
          - name: GOOGLE_APPLICATION_CREDENTIALS
            value: /var/run/secrets/tokens/gcp-ksa/google-application-credentials.json
        volumeMounts:
        - name: gcp-ksa
          mountPath: /var/run/secrets/tokens/gcp-ksa
          readOnly: true
      volumes:
      - name: gcp-ksa
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              path: token
              audience: WORKLOAD_IDENTITY_POOL
              expirationSeconds: 172800
          - configMap:
              name: my-cloudsdk-config
              optional: false
              items:
                - key: "config"
                  path: "google-application-credentials.json"
    
    

    部署這項工作負載時,Pod 中的 gcp-ksa 磁碟區會包含下列資料:

    • 您部署的 ConfigMap 中的資料,會以 google-application-credentials.json 為檔名。這個檔案是 ADC 憑證設定檔
    • Kubernetes ServiceAccount 權杖,格式為 token。Kubernetes 會將 ServiceAccount 的已簽署 JWT 掛接為投射的 ServiceAccount 權杖檔案

    Pod 中的容器會將 gcp-ksa 磁碟區掛接到 /var/run/secrets/tokens/gcp-ksa 路徑,並設定 ADC 在該路徑中尋找憑證設定 JSON 檔案。

  8. 部署工作負載:

    kubectl apply -f workload-config.yaml
    

驗證機群 Workload Identity 聯盟設定

在本節中,您會建立 Cloud Storage 值區,並從使用機群 Workload Identity Federation 的 Pod 存取該值區。執行這些步驟前,請務必按照「在應用程式中使用機群 Workload Identity 聯盟」一節中的操作說明,設定 Workload Identity 聯盟。

本節不會說明如何使用 IAM 服務帳戶模擬方法驗證 Workload Identity Federation。

  1. 找出以數字呈現的專案編號:

    gcloud projects describe FLEET_PROJECT_ID \
        --format="value(projectNumber)"
    

    輸出結果會與下列內容相似:

    1234567890
    
  2. 建立 Cloud Storage bucket:

    gcloud storage buckets create gs://FLEET_PROJECT_ID-test-bucket \
        --location=LOCATION
    

    LOCATION 替換為 Google Cloud位置。

  3. 建立 IAM 允許政策,將 bucket 的存取權授予您建立的服務帳戶:

    gcloud storage buckets add-iam-policy-binding gs://FLEET_PROJECT_ID-test-bucket \
        --condition=None \
        --role=roles/storage.objectViewer \
        --member=principal://iam.googleapis.com/projects/FLEET_PROJECT_NUMBER/locations/global/workloadIdentityPools/FLEET_PROJECT_ID.svc.id.goog/subject/ns/NAMESPACE/sa/KSA_NAME
    

    更改下列內容:

    • FLEET_PROJECT_NUMBER:您的專案編號 (數字)。
    • FLEET_PROJECT_ID:您的專案 ID。
    • NAMESPACE:Kubernetes 命名空間的名稱,用於執行上一節中的 Pod。
    • KSA_NAME:Kubernetes ServiceAccount 的名稱,也就是前一節中 Pod 使用的名稱。
  4. 在 Pod 中建立殼層工作階段:

    kubectl exec -it pods/my-pod --namespace=NAMESPACE -- /bin/bash
    
  5. 試著列出值區中的物件:

    curl -X GET -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
    "https://storage.googleapis.com/storage/v1/b/FLEET_PROJECT_ID-test-bucket/o"
    

    輸出內容如下:

    {
      "kind": "storage#objects"
    }
    

使用驗證碼進行驗證

使用 Cloud 用戶端程式庫時,驗證程式庫會自動使用 ADC 尋找憑證,以便向 Google Cloud 服務進行驗證。您必須使用支援 Workload Identity 聯盟的 Cloud 用戶端程式庫。下表列出最低 Cloud 用戶端程式庫版本,以及如何查看目前版本的操作說明:

C++

大多數 Google Cloud C++ 用戶端程式庫都支援身分同盟,方法是使用 ChannelCredentials 物件 (透過呼叫 grpc::GoogleDefaultCredentials() 建立)。如要初始化這項憑證,您必須使用 gRPC 1.36.0 以上版本建構用戶端程式庫。

C++ 適用的 Cloud Storage 用戶端程式庫使用 REST API,而非 gRPC,因此不支援身分同盟。

Go

如果 Go 適用的用戶端程式庫使用 golang.org/x/oauth2 模組的 v0.0.0-20210218202405-ba52d332ba99 以上版本,即可支援身分同盟。

如要查看用戶端程式庫使用的這個模組版本,請執行下列指令:

cd $GOPATH/src/cloud.google.com/go
go list -m golang.org/x/oauth2

Java

如果 Java 適用的用戶端程式庫使用 com.google.auth:google-auth-library-oauth2-http 構件 0.24.0 以上版本,即可支援身分同盟。

如要查看用戶端程式庫使用的構件版本,請在應用程式目錄中執行下列 Maven 指令:

mvn dependency:list -DincludeArtifactIds=google-auth-library-oauth2-http

Node.js

如果 Node.js 的用戶端程式庫使用 google-auth-library 套件 7.0.2 以上版本,即可支援身分同盟。

如要查看用戶端程式庫使用的套件版本,請在應用程式目錄中執行下列指令:

npm list google-auth-library

建立 GoogleAuth 物件時,您可以指定專案 ID,也可以允許 GoogleAuth 自動尋找專案 ID。如要自動找出專案 ID,設定檔中的服務帳戶必須在專案中具備「瀏覽器」角色 (roles/browser),或是其他具備同等權限的角色。詳情請參閱 google-auth-library 套件的README

Python

如果 Python 適用的用戶端程式庫使用 google-auth 套件 1.27.0 以上版本,即可支援身分同盟。

如要查看用戶端程式庫使用的套件版本,請在安裝套件的環境中執行下列指令:

pip show google-auth

如要為驗證用戶端指定專案 ID,可以設定 GOOGLE_CLOUD_PROJECT 環境變數,也可以允許用戶端自動尋找專案 ID。如要自動尋找專案 ID,設定檔中的服務帳戶必須在專案中具備「瀏覽器」角色 (roles/browser),或具備同等權限的角色。詳情請參閱google-auth 套件的使用者指南

後續步驟

使用機群 Workload Identity 聯盟時,請參閱最佳做法,瞭解如何整理機群。