使用代理程式本身的身分驗證外部服務

代理身分可讓 Cloud de Confiance by S3NS 上的代理使用自己的身分,向外部服務和託管於 Cloud Run 或 Google Kubernetes Engine (GKE) 的工作負載進行驗證。使用 OpenID Connect (OIDC) ID 權杖,即可將代理連結至第三方雲端平台 (例如 Amazon Web Services (AWS) 和 Microsoft Azure)、自訂 API、API Gateway 和地端部署後端。

當代理依據自身權限執行操作時,代理身分會核發 OIDC ID 權杖,這是一種 JSON Web Token (JWT),可聲明代理的 SPIFFE 身分,並由代理信任網域 (代管 Workload Identity 集區) 的核發者金鑰簽署。外部系統可以透過Cloud de Confiance 安全權杖服務代管的公開端點,驗證這些 ID 權杖,不需Cloud de Confiance 憑證或 SDK:

  • 發布 OpenID 供應商中繼資料和公開金鑰端點 (jwks_uri) 的 OpenID Connect Discovery 1.0 端點 (/.well-known/openid-configuration)。
  • JSON Web Key Set (JWKS) 端點 (/openid/jwks),用於提供有效的公開金鑰,驗證代理 ID 權杖上的簽章。

如要使用代理的身分向 Cloud de Confiance API 和資源進行驗證,請參閱「使用代理的身分向 Cloud de Confiance 進行驗證」。如要代表使用者存取服務,請參閱「使用驗證管理工具透過三足式 OAuth 進行驗證」。

事前準備

  1. 確認您選擇了正確的驗證方式。 請參閱「代理身分總覽」,瞭解 SPIFFE 身分、信任網域和代理憑證的運作方式。
  2. 建立及部署代理,並啟用 Agent Identity。
  3. 請確認外部服務或識別資訊提供者符合下列規定:

  4. 找出代理和目標外部服務的下列設定值:

    • 核發者網址 (iss 宣告):貴組織 (https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN) 或專案 (https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/TRUST_DOMAIN) 的 workload identity pool 核發者網址。
    • 允許的目標對象 (aud 宣告):外部服務或識別資訊提供者在驗證 ID 權杖時預期的目標對象 URI。
  5. 確認您具備完成這項工作所需的角色。

必要的角色

如要取得使用 Agent Identity 部署代理所需的權限,請要求管理員授予您專案的下列 IAM 角色:

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

這些預先定義的角色具備必要權限,可部署具備 Agent Identity 的代理。如要查看確切的必要權限,請展開「Required permissions」(必要權限) 部分:

所需權限

必須具備下列權限,才能部署具備 Agent Identity 的代理:

  • 將代理部署至 Gemini Enterprise Agent Platform 的 Agent Runtime:
    • aiplatform.reasoningEngines.create
    • aiplatform.reasoningEngines.update
  • 將代理服務部署至 Cloud Run:
    • run.services.create
    • run.services.update

您或許還可透過自訂角色或其他預先定義的角色取得這些權限。

取得代理的 OIDC ID 權杖

如要設定代理程式,取得 OIDC ID 權杖並傳送至外部服務,請完成下列工作:

  1. 使用代理身分設定代理
  2. 在應用程式程式碼中要求 OIDC ID 權杖

使用代理身分設定代理

部署代理時啟用 Agent Identity:

  • 如果將代理部署至 Gemini Enterprise Agent Platform 的 Agent Runtime,請將 identity_type 設為 AGENT_IDENTITY:

    remote_app = client.agent_engines.create(
        agent=app,
        config={
            "identity_type": types.IdentityType.AGENT_IDENTITY,
            "requirements": ["google-cloud-aiplatform[agent_engines,adk]"],
        },
    )
    
  • 如要將容器化代理服務部署至 Cloud Run,請傳遞 --identity-type=agent-identity 旗標:

    gcloud run deploy SERVICE_NAME \
        --image=IMAGE_URL \
        --identity-type=agent-identity \
        --no-allow-unauthenticated

    更改下列內容:

    • SERVICE_NAME:Cloud Run 服務的名稱。
    • IMAGE_URL:代理程式的容器映像檔網址。

在應用程式程式碼中要求 OIDC ID 權杖

在代理程式的應用程式程式碼中,使用 Google Auth 用戶端程式庫,為目標外部對象要求 OIDC ID 權杖。用戶端程式庫會處理權杖產生、本機快取,以及從中繼資料伺服器自動更新。

根據預設,支援的 Google Auth 用戶端程式庫會將憑證指紋納入權杖的 cnf (x5t#S256) 宣告,以加密方式將 OIDC ID 權杖繫結至代理程式的專屬 X.509 憑證。接收服務可以選擇根據雙向 TLS (mTLS) 握手期間提供的用戶端憑證驗證這項聲明,或者如果未強制執行憑證繫結,則忽略該聲明。

如果 ID 權杖中含有 cnf 宣告,Cloud Run 會自動強制執行憑證繫結。如果代理使用繫結的 ID 權杖呼叫 Cloud Run 服務,您必須透過 mTLS 連線呼叫其 mTLS 端點 (*.mtls.run.app)。如要改為繼續呼叫標準 *.run.app 網址,請選擇不採用個別要求 (例如在 Python 中設定 bind_id_token=False) 或整個執行階段環境 (使用 GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN=false) 的憑證繫結。如需支援的程式庫版本和範例,請參閱「停用憑證繫結權杖」。

呼叫透過 mTLS 強制執行憑證繫結的端點時,請設定用戶端工作階段,在 mTLS 握手期間提供代理的 X.509 憑證 (例如在 Python 中呼叫 authed_session.configure_mtls_channel())。

下列範例使用 google-auth 程式庫要求繫結憑證的 OIDC ID 權杖、視需要設定 mTLS 管道,並在外送要求中將權杖附加為 Bearer 權杖:

Python

from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import id_token

# 1. Specify the audience expected by the external receiver
# (for example, AWS Bedrock AgentCore or your external service URL).
target_audience = "https://EXTERNAL_SERVICE_AUDIENCE"

# 2. Create ID token credentials and an AuthorizedSession, which handles
# local token caching, automatic renewal before expiry, and the
# Bearer header.
credentials = id_token.fetch_id_token_credentials(audience=target_audience)
authed_session = AuthorizedSession(credentials)

# 3. Send the authenticated request to the external service.
response = authed_session.post(
    "https://EXTERNAL_SERVICE_ENDPOINT",
    json={"prompt": "Hello from Agent"},
)

更改下列內容:

  • EXTERNAL_SERVICE_AUDIENCE:接收服務預期的目標對象 URI (例如 bedrock.us-east-1.amazonaws.com 或 api.example.com)。
  • EXTERNAL_SERVICE_ENDPOINT:代理呼叫的外部 API 或後端端點網址。

Python (mTLS)

from google.auth.transport.requests import AuthorizedSession
from google.oauth2 import id_token

# 1. Specify the audience expected by the receiving service
# (for example, a regional Cloud Run mTLS URL or an on-premises mTLS endpoint).
target_audience = "https://EXTERNAL_SERVICE_AUDIENCE"

# 2. Create certificate-bound ID token credentials and configure the mTLS
# channel to present the agent's X.509 certificate.
credentials = id_token.fetch_id_token_credentials(audience=target_audience)
authed_session = AuthorizedSession(credentials)
authed_session.configure_mtls_channel()

# 3. Send the authenticated request over mTLS.
response = authed_session.post(
    "https://EXTERNAL_SERVICE_ENDPOINT",
    json={"prompt": "Hello from Agent"},
)

更改下列內容:

  • EXTERNAL_SERVICE_AUDIENCE:接收服務預期的目標對象 URI (例如區域 Cloud Run mTLS 網址或 api.example.com)。
  • EXTERNAL_SERVICE_ENDPOINT:代理呼叫的 mTLS API 或後端端點網址。

如需其他語言 (例如 Go、Node.js 和 Java) 的用戶端程式庫操作說明和範例,請參閱「取得 ID 權杖」。這些語言的用戶端程式庫支援 --identity-type=agent-identity。支援憑證繫結 ID 權杖的程式庫預設會繫結權杖,並允許您選擇不採用個別要求。

驗證 Agent Identity ID 權杖

外部服務收到代理程式的 OIDC ID 權杖時,請根據目標服務,使用下列任一方法驗證權杖:

使用內建的 Workload Identity Federation

如果接收服務執行的雲端平台支援內建 IAM 驗證或 OIDC Workload Identity Federation,您就不需要編寫自訂權杖驗證程式碼:

  • Cloud Run:如果接收服務在 Cloud Run 上執行,且具有經過驗證的輸入 (--no-allow-unauthenticated),Cloud Run 會在輸入層驗證傳入的 Agent Identity 權杖。如果權杖包含 cnf 宣告,請將呼叫代理程式設為指定接收服務的區域 mTLS 網址 (https://SERVICE_NAME-PROJECT_NUMBER.REGION.mtls.run.app),讓 Cloud Run 可以在 mTLS 握手期間驗證用戶端憑證。將接收服務的 Cloud Run 叫用者 (roles/run.invoker) 角色授予呼叫代理 詳情請參閱「向 Cloud Run 上的 MCP 伺服器進行驗證」。

    如果服務允許未經驗證的輸入,並在應用程式程式碼中驗證權杖,請參閱「以程式輔助方式驗證權杖」。

  • Amazon Bedrock:指定 Security Token Service 導覽網址或核發者網址,以及預期的目標對象,設定傳入 JWT 驗證。Cloud de Confiance 如需操作說明,請參閱 AWS 說明文件中的「設定傳入 JWT 授權方」。

  • Microsoft Entra ID:使用「Other issuer」(其他核發者) 情境設定聯合身分憑證。指定 Cloud de Confiance Security Token Service 核發者網址、預期目標對象和主體 ID (sub 宣告)。如需操作說明,請參閱 Microsoft Learn 說明文件中的「在應用程式與外部身分識別提供者之間建立信任關係」。

透過程式驗證權杖

如果代理傳送要求至自訂 API、微服務、API 閘道或地端部署工作負載,接收服務必須先驗證傳入的 OIDC ID 權杖,才能授予存取權。代理通常會在 Authorization: Bearer TOKEN HTTP 標頭中傳遞這個權杖。

如要透過程式輔助方式驗證傳入的 ID 權杖,請完成下列工作:

  1. 擷取並驗證權杖核發者網址
  2. 探索及快取公開簽署金鑰
  3. 驗證權杖簽章和宣告
  4. 選用:驗證憑證繫結 (cnf 宣告)
  5. 授權代理的 SPIFFE 身分

擷取及驗證權杖核發者網址

收到傳入要求時,請讀取未經驗證的 JWT 酬載,擷取 iss (核發者) 宣告。這項聲明包含代理信任網域的 workload identity pool 網址。這個網址是導覽文件和公開簽署金鑰的基準網址。

發出任何傳出網路要求前,請確認 iss 宣告與貴組織或專案預期的 Cloud de Confiance Security Token Service workload identity pool 網址相符:

  • 組織層級信任網域:

    https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN

    舉例來說,如果組織 ID 為 123456789012,則 TRUST_DOMAIN 為 agents.global.org-123456789012.system.id.goog。

  • 專案層級信任網域 (適用於沒有組織的專案):

    https://sts.googleapis.com/v1/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/TRUST_DOMAIN

    舉例來說,如果專案編號為 9876543210,則 TRUST_DOMAIN 為 agents.global.proj-9876543210.system.id.goog。

探索並快取公開簽署金鑰

驗證核發者網址後,請從 Cloud de Confiance Security Token Service 擷取公開簽署金鑰並快取:

  1. 查詢 OpenID Connect 探索端點:將 /.well-known/openid-configuration 附加至基本核發者網址,並傳送未經驗證的 HTTP GET 要求:

    使用任何要求資料之前,請先修改下列項目的值:

    • ORGANIZATION_ID:您的 Cloud de Confiance組織 ID。如果專案不屬於任何組織,請將 organizations/ORGANIZATION_ID 替換為 projects/PROJECT_NUMBER。
    • TRUST_DOMAIN:代理信任網域的工作負載身分集區 ID (例如 agents.global.org-123456789012.system.id.goog)。

    HTTP 方法和網址:

    GET https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN/.well-known/openid-configuration

    請展開以下其中一個選項,以傳送要求:

    成功的要求會傳回 HTTP 200 OK 狀態和 JSON 物件,其中包含 OpenID 提供者中繼資料,包括 jwks_uri 欄位:

    {
      "issuer": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog",
      "jwks_uri": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/openid/jwks",
      "authorization_endpoint": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/authorize",
      "token_endpoint": "https://sts.googleapis.com/v1/organizations/123456789012/locations/global/workloadIdentityPools/agents.global.org-123456789012.system.id.goog/token",
      "response_types_supported": [
        "id_token"
      ],
      "subject_types_supported": [
        "public"
      ],
      "id_token_signing_alg_values_supported": [
        "RS256"
      ]
    }
    
  2. 查詢 JSON Web Key Set (JWKS) 端點:將未經驗證的 HTTP GET 要求傳送至 OpenID 供應商中繼資料傳回的 jwks_uri 網址:

    使用任何要求資料之前,請先修改下列項目的值:

    • ORGANIZATION_ID:您的 Cloud de Confiance組織 ID。如果專案不屬於任何組織,請將 organizations/ORGANIZATION_ID 替換為 projects/PROJECT_NUMBER。
    • TRUST_DOMAIN:代理信任網域的工作負載身分集區 ID (例如 agents.global.org-123456789012.system.id.goog)。

    HTTP 方法和網址:

    GET https://sts.googleapis.com/v1/organizations/ORGANIZATION_ID/locations/global/workloadIdentityPools/TRUST_DOMAIN/openid/jwks

    請展開以下其中一個選項,以傳送要求:

    成功的要求會傳回 HTTP 200 OK 狀態,以及包含公開金鑰陣列的 JSON 物件,格式依據 RFC 7517:

    {
      "keys": [
        {
          "kty": "RSA",
          "use": "sig",
          "alg": "RS256",
          "kid": "4d1933f8e6c4e0b512c140989f6655c68997...",
          "n": "uQn4zN_1mQ0VpGv82-Wp3w...",
          "e": "AQAB"
        }
      ]
    }
    
  3. 快取導覽文件和金鑰:OpenID Connect 探索端點和 JWKS 端點的回應都包含下列 HTTP 快取標頭:

    Cache-Control: public, max-age=86400, must-revalidate
    

    將導覽文件和 JWKS 快取最多 24 小時 (86400 秒),以提升驗證效能並避免頻率限制。

    Cloud de Confiance 會定期輪替 workload identity pool 的私密和公開簽署金鑰。如果驗證器收到的權杖含有 kid (金鑰 ID),但本機金鑰快取中沒有該 ID,請先從 /openid/jwks 端點擷取新的 JWKS,再拒絕權杖。

    如果在查詢探索或 JWKS 端點時遇到 HTTP 錯誤,請參閱「排解 Agent Identity 驗證問題」。

驗證權杖簽章和聲明

如要以加密方式驗證權杖簽章和 JWT 宣告,請使用標準 OIDC 或 JWT 驗證程式庫 (例如 Google Tink),並執行下列操作:

  1. 簽章:在快取的 JWKS 中,找出與 JWT 標頭中 kid (金鑰 ID) 相符的公開金鑰。使用 alg 欄位 (RS256) 中指定的演算法驗證簽章。為確保向前相容性,請動態檢查 JWKS 中的 alg 和 kty 欄位,而非硬式編碼演算法類型。
  2. 核發者 (iss):確認 iss 宣告與信任網域中受信任的Cloud de Confiance workload identity pool 核發者網址相符。
  3. 目標對象 (aud):確認 aud 宣告與服務設定的目標對象 ID 相符。
  4. 核發時間 (iat) 和到期時間 (exp):確認 iat 聲明是在過去,且目前時間早於 exp 聲明 (允許小幅度的時鐘誤差,例如 1 到 2 分鐘)。

以下範例使用 Google Tink (tink.jwt),根據 JWKS JSON 酬載驗證代理身分 ID 權杖:

Python

import tink
from tink import jwt

# Initialize Tink JWT signature primitives (call once at application startup).
jwt.register_jwt_signature()


def verify_agent_identity_token(
    token: str,
    jwks_json: str,
    expected_issuer: str,
    expected_audience: str,
) -> jwt.VerifiedJwt:
    """Verifies an Agent Identity JWT against a JWKS JSON string using Tink.

    Args:
        token: The compact serialized JWT string.
        jwks_json: The JWKS JSON string fetched from the STS pool endpoint.
        expected_issuer: The expected token issuer ('iss' claim).
        expected_audience: The expected token audience ('aud' claim).

    Returns:
        jwt.VerifiedJwt: The verified JWT claims object.

    Raises:
        tink.TinkError: If the JWKS cannot be parsed, the key is not found,
            or token validation (signature, issuer, audience, expiration) fails.
    """
    # 1. Convert the JWKS JSON into a Tink public KeysetHandle.
    keyset_handle = jwt.jwk_set_to_public_keyset_handle(jwks_json)

    # 2. Instantiate the Tink JwtPublicKeyVerify primitive.
    jwt_verifier = keyset_handle.primitive(jwt.JwtPublicKeyVerify)

    # 3. Configure expected validation rules (issuer, audience, expiration).
    # Google Cloud STS sets 'typ': 'JWT' in the header, so
    # expected_type_header="JWT" is required.
    validator = jwt.new_validator(
        expected_issuer=expected_issuer,
        expected_audience=expected_audience,
        expected_type_header="JWT",
        allow_missing_expiration=False,
    )

    # 4. Cryptographically verify the signature and standard OIDC claims.
    return jwt_verifier.verify_and_decode(token, validator)

選用:驗證憑證繫結 (cnf 聲明)

如果接收服務透過 mTLS 強制執行憑證繫結,請根據 mTLS 握手期間提供的用戶端憑證,驗證 cnf (x5t#S256) 宣告:

  1. 終止相互傳輸層安全標準 (mTLS):設定伺服器或輸入 Proxy,根據 TLS 1.3 (RFC 9846),在 TLS 握手期間要求並驗證代理的 X.509 憑證。
  2. 計算憑證指紋 (x5t#S256):從 mTLS 連線中擷取分葉 X.509 用戶端憑證。計算 DER 編碼位元組的 SHA-256 雜湊,並對摘要進行 base64url 編碼,不使用 = 填補。
  3. 驗證 cnf (x5t#S256) 宣告:檢查已驗證的 JWT 酬載,找出 cnf 物件 ({"cnf": {"x5t#S256": "FINGERPRINT"}}),並根據 RFC 8705 第 6.1 節,驗證 x5t#S256 值是否與用戶端憑證指紋相符。如果呼叫端未透過 mTLS 提供用戶端憑證,或指紋不相符,請拒絕要求並傳送 HTTP 401 Unauthorized 回應。

授權代理的 SPIFFE 身分

驗證權杖的簽章和標準宣告後,請檢查已驗證的 sub (主體) 宣告,授權要求並在稽核記錄中記錄呼叫代理。

sub 宣告包含代理程式的專屬 SPIFFE ID,例如:

  spiffe://agents.global.org-123456789012.system.id.goog/resources/aiplatform/projects/9876543210/locations/us-central1/reasoningEngines/my-test-agent

在服務的授權邏輯中,先比較已驗證的 sub 宣告與信任代理 SPIFFE ID (或信任網域前置字元) 的許可清單,再授予受保護資源的存取權。

後續步驟