管理服務帳戶

Google Distributed Cloud (GDC) 實體隔離方案中的服務身分,可為工作負載或服務提供專屬身分,以程式輔助方式安全存取資源和微服務。這類特殊身分由應用程式或工作負載使用,而非由人員使用,且無法用於人員登入。與使用者帳戶類似,您可以授予服務身分權限和角色,定義其有權存取的內容。

您可能會注意到這個概念有兩種說法。GDC 控制台主要使用「服務身分」一詞,而 gdcloud 指令和 API 互動則通常使用「服務帳戶」。後者反映了基礎 Kubernetes 自訂資源 ProjectServiceAccount 的名稱。這兩個詞彙指的是同一個概念:工作負載的非人類身分。本文主要使用「服務身分」一詞。

服務身分可用於管理 GDC 基礎架構,例如:

  • 內部 Distributed Cloud 服務和工作負載,可安全存取 Distributed Cloud 控制層應用程式設計介面 (API)。例如,資料庫服務與 Kubernetes API 互動,以建立及刪除資料庫。
  • Distributed Cloud 中的客戶工作負載,可存取 Distributed Cloud 服務,並發出授權的應用程式設計介面 (API) 呼叫。舉例來說,服務身分可以管理客戶,使用 Vertex AI Workbench 筆記本,透過 Speech-to-Text API 轉錄音訊檔案。
  • 要與 Distributed Cloud 建立聯盟的外部工作負載。舉例來說,服務身分可以管理 Distributed Cloud 外部的應用程式,該應用程式可將文件數位化,但想使用光學字元辨識 (OCR) API 取代目前的 OCR 引擎。
  • Distributed Cloud 服務或系統控制器,安全存取客戶資源或使用者叢集。舉例來說,服務身分可以管理驗證和授權工作流程,其中在管理員叢集中執行的服務控制器,需要在客戶管理的使用者叢集中執行工作負載。

管理服務身分時,會涉及服務身分 (由 ProjectServiceAccount 資源表示) 和相關聯的憑證 (公開和私密金鑰組)。您可以使用 GDC 控制台、gdcloud CLI 或 API,管理服務身分的帳戶。使用 gdcloud CLI 時,服務身分功能是以全域 ProjectServiceAccount API 為基礎。由於 ProjectServiceAccount 資源是在全域層級設定,因此會在 gdcloud universe 的所有可用區運作。

事前準備

您必須擁有專案,才能完成本文件中的工作。如要瞭解如何建立專案,請參閱「建立專案」。

您也必須具備必要權限,並準備好環境。

要求 IAM 角色

如要在專案中建立、更新及刪除服務身分,請與 IAM 機構組織管理員或 IAM 專案管理員聯絡,要求取得「IAM 專案管理員」(project-iam-admin) 角色。

IAM 機構組織管理員可以為組織中的任何專案授予這個角色。IAM 專案管理員可以在特定專案範圍內授予這個角色。

準備環境

如要使用指令列工具管理服務身分,請完成下列設定:

建立服務身分

建立服務身分時,也需要建立帳戶和相關聯的憑證。

建立帳戶

如要為服務身分建立帳戶,請使用 GDC 控制台、gdcloud CLI 或 API,在專案中建立 ProjectServiceAccount 資源。

控制台

  1. 登入 GDC 控制台。
  2. 在導覽選單中,依序選取「Identity & Access」>「Service identities」。
  3. 按一下「 Create Service Identity」(建立服務身分)。 「Service Identity details」(服務身分詳細資料) 頁面隨即開啟。
  4. 在「Service identity name」(服務身分名稱) 欄位中,輸入服務身分的名稱。例如:testserviceidentity。
  5. 點選「建立」。

gdcloud

建立帳戶:

gdcloud iam service-accounts create NAME \
    --project=PROJECT

替換下列值:

  • NAME:ProjectServiceAccount 的名稱。專案命名空間中的名稱不得重複。
  • PROJECT:要在其中建立服務身分的專案。如果已設定 gdcloud init,請省略 --project 旗標。

這個指令會在 Management API 伺服器的專案命名空間中建立 ProjectServiceAccount。

API

  1. 建立 ProjectServiceAccount 自訂資源 YAML 檔案,例如 my-project-sa.yaml:

    apiVersion: resourcemanager.global.gdc.goog/v1
    kind: ProjectServiceAccount
    metadata:
      name: NAME
      namespace: PROJECT
    spec:
      keys:
      - algorithm: ALGORITHM
        id: KEY_ID
        key: BASE64_ENCODED_KEY
        validAfter: "START_TIME"
        validBefore: "EXPIRATION_TIME"
    

    請替換下列變數:

    • NAME:ProjectServiceAccount 資源的名稱。專案命名空間中的名稱不得重複。
    • PROJECT:要在其中建立服務身分的專案。
    • ALGORITHM:金鑰的演算法。僅支援 ES256 金鑰。
    • KEY_ID:金鑰的專屬 ID。ID 用於判斷要驗證哪個金鑰。
    • BASE64_ENCODED_KEY:採用 Base64 編碼的 PEM 格式公開金鑰,用於驗證。用於產生這個公開金鑰的私密金鑰應採用 ECDSA P256 PEM 格式。
    • START_TIME:金鑰生效的開始時間,例如 2025-02-07T00:59:34Z。
    • EXPIRATION_TIME:金鑰的到期時間,例如 2026-02-07T00:59:34Z。
  2. 將 ProjectServiceAccount 自訂資源套用至全域 API 伺服器:

    kubectl --kubeconfig GLOBAL_API_SERVER_KUBECONFIG apply -f my-project-sa.yaml
    

    將 GLOBAL_API_SERVER_KUBECONFIG 變數替換為全域 API 伺服器的 kubeconfig 檔案路徑。

建立憑證

如要讓工作負載或應用程式以服務身分 (由您建立的帳戶代表) 進行驗證,您必須產生憑證。建立憑證時,系統會產生一組加密編譯私密和公開金鑰,並將公開金鑰與服務身分建立關聯。

如要為服務身分建立憑證,請使用 GDC 控制台、gdcloud CLI 或 API。

控制台

  1. 登入 GDC 控制台。
  2. 在導覽選單中,依序選取「Identity & Access」>「Service Identities」。
  3. 按一下要新增至金鑰的服務身分名稱。
  4. 按一下「 建立新金鑰」。
  5. 新金鑰會顯示在「Keys」(金鑰) 清單中,並會顯示對話方塊,確認您已成功建立金鑰。

gdcloud

gdcloud 指令會建立應用程式預設憑證 JSON 檔案,以及公開和私密金鑰組:

gdcloud iam service-accounts keys create APPLICATION_DEFAULT_CREDENTIALS_FILENAME \
    --project=PROJECT \
    --iam-account=NAME \
    --ca-cert-path=CA_CERTIFICATE_PATH

替換下列值:

  • APPLICATION_DEFAULT_CREDENTIALS_FILENAME:JSON 檔案的名稱。
  • PROJECT:選取要建立金鑰的專案。如果已設定 gdcloud init,則可省略 --project 旗標。
  • NAME:要新增金鑰的服務身分名稱。
  • CA_CERTIFICATE_PATH:選用:用於驗證驗證端點的憑證授權單位 (CA) 憑證路徑。如未指定這個路徑,系統會使用系統 CA 憑證。您必須在系統 CA 憑證中安裝 CA。

Distributed Cloud 會將公開金鑰新增至 ProjectServiceAccount 金鑰,用於驗證私密金鑰簽署的 JSON Web Token (JWT)。私密金鑰會寫入應用程式預設憑證 JSON 檔案。

以下範例顯示應用程式預設憑證 JSON 檔案:

{
"type": "gdch_service_account",
"format_version": "1",
"project": "project_name",
"private_key_id": "abcdef1234567890",
"private_key": "-----BEGIN PRIVATE KEY-----\nETC\n-----END PRIVATE KEY-----\n",
"name": "service_identity_name",
"ca_cert_path": "/path/to/ca.crt",
"token_uri": "https://service-identity.<Domain>/authenticate"
}

本範例使用下列值:

  • project:組織中的專案命名空間。
  • private_key_id:指派給金鑰的 ID。
  • private_key:CLI 產生的 PEM 格式 ECDSA P256 私密金鑰。
  • name:服務身分的名稱。
  • ca_cert_path:用於驗證驗證端點的憑證授權單位 (CA) 憑證路徑。
  • token_uri:驗證端點的位址。

API

  1. 產生公開和私密金鑰組。下列指令以 openssl 為例,這是用於此用途的常見工具。

    openssl ecparam -name prime256v1 -genkey -noout -out "key.pem"
    openssl ec -in "key.pem" -pubout > "pub.pem"
    
  2. 將公開金鑰進行 Base64 編碼,並擷取金鑰 ID:

    KEY_ID=$(openssl pkey -in key.pem -pubout -outform der | openssl dgst -sha256 | sed 's/^.* //')
    BASE64_ENCODED_KEY=$(cat pub.pem | base64)
    
  3. 建立或更新 ProjectServiceAccount 自訂資源 YAML 檔案,並加入上一步產生的金鑰資訊:

    apiVersion: resourcemanager.global.gdc.goog/v1
    kind: ProjectServiceAccount
    metadata:
      name: NAME
      namespace: PROJECT
    spec:
      keys:
      - algorithm: ALGORITHM
        id: KEY_ID
        key: BASE64_ENCODED_KEY
        validAfter: "START_TIME"
        validBefore: "EXPIRATION_TIME"
    

    請替換下列變數:

    • NAME:ProjectServiceAccount 資源的名稱。專案命名空間中的名稱不得重複。
    • PROJECT:您要建立金鑰的專案。
    • ALGORITHM:金鑰的演算法。僅支援 ES256 金鑰。
    • KEY_ID:金鑰的專屬 ID。ID 用於判斷要驗證哪個金鑰。
    • BASE64_ENCODED_KEY:採用 Base64 編碼的 PEM 格式公開金鑰,用於驗證。用於產生這個公開金鑰的私密金鑰應採用 ECDSA P256 PEM 格式。
    • START_TIME:金鑰生效的開始時間,例如 2025-02-07T00:59:34Z。
    • EXPIRATION_TIME:金鑰的到期時間,例如 2026-02-07T00:59:34Z。
  4. 將 ProjectServiceAccount 自訂資源套用至全域 API 伺服器:

    kubectl --kubeconfig GLOBAL_API_SERVER_KUBECONFIG apply -f my-project-sa.yaml
    

    將 GLOBAL_API_SERVER_KUBECONFIG 變數替換為全域 API 伺服器的 kubeconfig 檔案路徑。

  5. 建立含有私密金鑰的應用程式預設憑證 JSON 檔案。請確認 JSON 檔案中的 KEY_ID 變數,與 ProjectServiceAccount 規格中使用的 KEY_ID 變數設為相同的值。

    cat <<EOF > "key_file.json"
    {
      "format_version": "1",
      "name": "NAME",
      "private_key": "$(tr '\n' '\t' < "key.pem" | sed 's/\t/\\n/g')",
      "private_key_id": "KEY_ID",
      "project": "PROJECT",
      "token_uri": "AUTH_URL",
      "type": "gdch_service_account"
    }
    EOF
    

    請替換下列變數:

    • NAME:服務身分的名稱。
    • KEY_ID:金鑰的專屬 ID。ID 用於判斷要驗證的金鑰,且必須與 ProjectServiceAccount 規格中使用的 KEY_ID 值相符。
    • PROJECT:組織中的專案命名空間。
    • AUTH_URL:驗證端點的位址。

如要瞭解如何使用產生的金鑰檔案,以這個服務身分進行驗證,請參閱「驗證及使用服務身分」。本節說明如何透過 gdcloud CLI 和用戶端程式庫,以程式輔助方式使用金鑰。

查看服務身分

本節說明如何查看服務身分和相關聯的公開金鑰。

查看服務身分清單

如要查看專案中的服務身分清單,請使用 GDC 控制台或 gdcloud CLI。

控制台

  1. 登入 GDC 控制台。
  2. 選取專案。
  3. 在導覽選單中,依序點選「Identity & Access」(身分與存取權) >「Service Identities」(服務身分),即可查看專案的服務身分清單。

gdcloud

列出專案中的服務身分帳戶:

gdcloud iam service-accounts list \
    --project=PROJECT

將 PROJECT 替換為專案 ID。

查看服務身分的公開金鑰清單

列出專案中向服務身分帳戶註冊的公開金鑰:

gdcloud iam service-accounts keys list \
    --project=PROJECT \
    --iam-account=NAME

更改下列內容:

  • PROJECT:專案 ID。
  • NAME:要使用的服務身分帳戶名稱。

授予服務身分權限

如要將權限授予服務身分,請使用 GDC 控制台或 gdcloud CLI 建立角色繫結,為其指派一或多個角色。

控制台

  1. 登入 GDC 控制台。
  2. 選取專案。
  3. 在導覽選單中,依序選取「Identity & Access」>「Access」。
  4. 在「Member」(成員) 清單中,按一下「Add member」(新增成員)。「使用者與角色」頁面隨即顯示。
  5. 在「Member type」(成員類型) 清單中,選取「Service identity」(服務身分)。
  6. 在「Service identity」(服務身分) 清單中,選取要指派角色繫結的服務身分。
  7. 在「Role」(角色) 清單中,選取要指派給服務身分的角色,例如「Backup Creator」(備份建立者)。
  8. 選用:如要新增其他角色,請按一下「 Add another role」(新增其他角色)。 選取其他角色。
  9. 按一下「新增」。

gdcloud

您可以將服務身分帳戶繫結至專案命名空間中的角色,或繫結至其他命名空間中的角色。

  • 將帳戶繫結至專案命名空間中的角色:

    gdcloud iam service-accounts add-iam-policy-binding \
        --project=PROJECT \
        --role=ROLE \
        --iam-account=NAME
    

    更改下列內容:

    • PROJECT:要在其中建立角色繫結的專案。如果已設定 gdcloud init,則可省略 --project 旗標。
    • ROLE:要指派給帳戶的預先定義角色。請以 Role/name 格式指定角色,其中 Role 是 Kubernetes 類型 IAMRole,name 則是預先定義角色的名稱。例如,如要指派專案檢視者角色,請將角色設為 IAMRole/project-viewer。
    • NAME:要使用的服務身分帳戶名稱。
  • 將帳戶繫結至其他命名空間中的角色:

    gdcloud iam service-accounts add-iam-policy-binding \
        --role=ROLE \
        --role-namespace=ROLE_NAMESPACE \
        --iam-account=NAME
    

    更改下列內容:

    • ROLE:要指派給帳戶的預先定義角色。請以 Role/name 格式指定角色,其中 Role 是 Kubernetes 類型 IAMRole,name 則是預先定義角色的名稱。例如,如要指派專案檢視者角色,請將角色設為 IAMRole/project-viewer。
    • ROLE_NAMESPACE:要與帳戶繫結的角色命名空間,而非專案命名空間。
    • NAME:要使用的服務身分帳戶名稱。

驗證及使用服務身分

建立服務身分並產生金鑰檔案後,您可以使用金鑰檔案向 GDC 服務和叢集進行驗證。驗證機制可讓您取得短期存取權杖,用於 API 呼叫或設定叢集存取權。

使用服務身分進行驗證的方法有兩種:

使用 gdcloud CLI 進行驗證

如要使用服務身分執行動作,必須先啟用其金鑰檔案。啟用後,您可以使用 gdcloud CLI 取得權杖或產生 kubeconfig 檔案。

使用金鑰授權服務身分

gdcloud auth activate-service-account 指令會使用服務身分驗證 gdcloud CLI。這樣一來,您就能使用服務身分帳戶權限 (而非使用者帳戶),對 Distributed Cloud 資源執行動作。

使用金鑰為服務身分提供授權:

  1. 如果您還沒有憑證金鑰檔案,請建立一個。

  2. 執行下列指令,啟用服務身分:

    gdcloud auth activate-service-account --key-file=KEY_FILE
    

    將 KEY_FILE 替換為憑證金鑰檔案的路徑,通常為 JSON 格式。

    成功啟用後,gdcloud 會使用服務身分的憑證,而非您的使用者憑證。

授權服務身分後,您可以使用 gdcloud 列印存取權杖。您可以將這個權杖做為不記名權杖,用來驗證 HTTP 要求。權杖會授予 AUDIENCES 參數中定義的服務存取權。

列印指定服務身分帳戶的身分權杖:

gdcloud auth print-identity-token --audiences=AUDIENCES

將 AUDIENCES 替換為權杖的預期接收者或服務。只能指定一個目標對象。

產生 kubeconfig 檔案

授權服務身分後,您可以產生 kubeconfig 檔案,向 Kubernetes 叢集進行驗證。

  1. 設定 gdcloud core/organization_console_url 屬性:

    gdcloud config set core/organization_console_url
    https://GDC_URL
    

    將 GDC_URL 替換為貴機構的網址。

  2. 使用現行服務身分產生 kubeconfig 檔案,以便存取叢集:

    • 可用區叢集:

      export KUBECONFIG=KUBECONFIG_PATH
      gdcloud clusters get-credentials CLUSTER_NAME --zone ZONE
      

      更改下列內容:

      • KUBECONFIG_PATH:要儲存產生的 kubeconfig 檔案的路徑。
      • CLUSTER_NAME:可用區叢集的名稱。

      • ZONE:叢集所在的可用區名稱。

    • 全域 API 伺服器:

      export KUBECONFIG=KUBECONFIG_PATH
      gdcloud clusters get-credentials global-api
      

      將 KUBECONFIG_PATH 替換為要儲存所產生 kubeconfig 檔案的路徑。

系統會產生 kubeconfig 檔案,並設定為以服務身分進行驗證。以下是 YAML 檔案範例:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: <REDACTED>
    server: <REDACTED>
  name: cluster-name
contexts:
- context:
    cluster: cluster-name
    user: gdch_console-<REDACTED>_cluster-name
  name: cluster-name-gdch_console-<REDACTED>_cluster-name
current-context: cluster-name-gdch_console-gdc1-staging-gpcdemolabs-com_cluster-name
kind: Config
preferences: {}
users:
- name: gdch_console-<REDACTED>_cluster-name
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1
      args:
      - --audience=<REDACTED>
      command: gdcloud-k8s-auth-plugin
      env: null
      installHint: Run 'gdcloud components install gdcloud-k8s-auth-plugin' to use
        plugin
      interactiveMode: Never
      provideClusterInfo: false

使用用戶端程式庫以程式輔助方式驗證

下列範例說明如何使用標準 Google Cloud 用戶端程式庫,以程式輔助方式向 GDC API 進行驗證。這些程式庫會使用產生的服務帳戶金鑰檔案,產生 Security Token Service (STS) 存取權杖,或使用服務身分的憑證設定服務用戶端。這個方法不需要事先取得 gdcloud 授權。

Python

import google.auth
from google.auth.transport import requests
import requests as reqs

api_endpoint = "https://console.org-1.zone1.google.gdch.test"

# Load the GDC credentials (via GOOGLE_APPLICATION_CREDENTIALS or default path)
creds, project_id = google.auth.default()

# Apply the required audience for the GDC Management API
creds = creds.with_gdch_audience(api_endpoint)

def fetch_gdch_token():
    sesh = reqs.Session()
    # Note: Set verify to False only if bypassing self-signed cert verification.
    # Otherwise, rely on the "ca_cert_path" present in your gdch_credentials.json
    sesh.verify = False
    req = requests.Request(session=sesh)

    # Refresh the credentials to fetch the STS access token
    creds.refresh(req)

    print("Access Token:", creds.token)

fetch_gdch_token()

Java

import com.google.auth.oauth2.GdchCredentials;
import com.google.auth.oauth2.GoogleCredentials;

import java.io.FileInputStream;
import java.io.InputStream;

public class GdchAuthExample {
    public static void main(String[] args) throws Exception {
        // Path to your service account JSON file
        String credentialsPath = "/path/to/gdch/credentials.json";
        String apiAudience = "https://console.org-1.zone1.google.gdch.test";

        try (InputStream credentialsStream = new FileInputStream(credentialsPath)) {
            // Load the generic Google credentials from the stream
            GoogleCredentials credentials = GoogleCredentials.fromStream(credentialsStream);

            // Verify it loaded as GdchCredentials
            if (credentials instanceof GdchCredentials) {
                // Cast and attach the targeted GDC audience
                GdchCredentials gdch = ((GdchCredentials) credentials).createWithGdchAudience(apiAudience);

                // Force negotiation with the GDC Auth Server to fetch the token
                gdch.refreshIfExpired();

                System.out.println("Access Token: " + gdch.getAccessToken().getTokenValue());
            } else {
                System.err.println("The provided file is not a valid GdchCredentials format.");
            }
        }
    }
}

Go

package main

import (
  "context"
  "fmt"
  "log"

  "cloud.google.com/go/auth/credentials"
)

func main() {
  ctx := context.Background()
  apiEndpoint := "https://console.org-1.zone1.google.gdch.test"

  // Load default credentials. The STSAudience parameter is specifically
  // required for the GDC auth flow to correctly negotiate the token.
  creds, err := credentials.DetectDefault(&credentials.DetectOptions{
    STSAudience: apiEndpoint,
  })
  if err != nil {
    log.Fatalf("Failed to detect credentials: %v", err)
  }

  // Fetch an access token
  token, err := creds.Token(ctx)
  if err != nil {
    log.Fatalf("Failed to retrieve token: %v", err)
  }

  fmt.Printf("Access Token: %s\n", token.Value)
}

C++

[](std::string const& keyfile, std::string const& audience) {
  auto is = std::ifstream(keyfile);
  is.exceptions(std::ios::badbit);  // Minimal error handling in examples
  auto contents = std::string(std::istreambuf_iterator<char>(is.rdbuf()), {});
  auto options =
      google::cloud::Options{}.set<google::cloud::UnifiedCredentialsOption>(
          google::cloud::MakeGDCHServiceAccountCredentials(contents, audience));
  return google::cloud::speech_v1::AdaptationClient(
      google::cloud::speech_v1::MakeAdaptationConnection(options));
}

刪除服務身分

刪除服務身分後,ProjectServiceAccount 和相關聯的公開金鑰會一併刪除,現有的私密金鑰也會失效,應用程式將無法再透過該服務身分存取專案資源。

如要刪除服務身分,請使用 GDC 控制台或 gdcloud CLI。

控制台

  1. 登入 GDC 控制台。
  2. 在導覽選單中,依序選取「Identity & Access」>「Service Identities」。
  3. 勾選要刪除的服務身分核取方塊。
  4. 點選「刪除」。
  5. 確認對話方塊隨即顯示。在「Confirm by typing the following below」(在下方輸入以下內容以確認) 欄位中,輸入 remove。
  6. 點選「刪除」。

gdcloud

執行下列指令,刪除服務身分帳戶:

gdcloud iam service-accounts delete NAME \
    --project=PROJECT

更改下列內容:

  • NAME:要 刪除的服務身分帳戶名稱。
  • PROJECT:專案 ID。

刪除憑證

如要停用特定金鑰組,但不想刪除整個服務身分帳戶,可以從服務身分帳戶中刪除公開金鑰。這項操作會使對應的私密金鑰失效。

如要刪除公開金鑰,請使用 GDC 控制台或 gdcloud CLI。

控制台

  1. 登入 GDC 控制台。
  2. 在導覽選單中,依序選取「Identity & Access」>「Service Identities」。
  3. 按一下服務身分名稱,找出要刪除的金鑰。
  4. 按一下「 刪除」。
  5. 在確認對話方塊中點按「刪除」。

gdcloud

從專案中的服務身分帳戶,移除具有金鑰 ID 的公開金鑰:

gdcloud iam service-accounts keys delete KEY_ID \
    --project=PROJECT \
    --iam-account=NAME

更改下列內容:

  • KEY_ID:金鑰的專屬 ID。
  • PROJECT:專案 ID。
  • NAME:服務身分帳戶的名稱。