エージェント自身の ID を使用して外部サービスに対して認証する

Agent Identity を使用すると、 Cloud de Confiance by S3NS のエージェントは独自の ID を使用して、外部サービスや Cloud Run または Google Kubernetes Engine(GKE)でホストされているワークロードに対して認証を行うことができます。OpenID Connect(OIDC)ID トークンを使用すると、エージェントをアマゾン ウェブ サービス(AWS)や Microsoft Azure などのサードパーティのクラウド プラットフォーム、カスタム API、API Gateway、オンプレミス バックエンドに接続できます。

エージェントが独自の権限で動作する場合、Agent Identity は OIDC ID トークンを発行します。これは、エージェントの SPIFFE ID をアサートし、エージェントの信頼ドメイン(マネージド ワークロード ID プール)の発行者鍵によって署名された JSON Web Token(JWT)です。外部システムは、Cloud de Confiance Security Token Service によってホストされているパブリック エンドポイントを介して、Cloud de Confiance 認証情報や SDK なしでこれらの ID トークンを検証できます。

  • OpenID プロバイダのメタデータと公開鍵エンドポイント(jwks_uri)を公開する OpenID Connect Discovery 1.0 エンドポイント(/.well-known/openid-configuration)。
  • エージェント ID トークンの署名の検証に使用されるアクティブな公開鍵を提供する JSON Web Key Set(JWKS)エンドポイント(/openid/jwks)。

エージェント独自の ID を使用して Cloud de Confiance API とリソースに対してエージェントを認証するには、エージェント独自の ID を使用して Cloud de Confiance に対して認証するをご覧ください。エンドユーザーに代わってサービスにアクセスするには、認証マネージャーで 3-legged OAuth を使用して認証するをご覧ください。

始める前に

  1. 正しい認証方法を選択していることを確認します。エージェント ID の概要で、SPIFFE ID、信頼ドメイン、エージェント認証情報の仕組みを確認する。
  2. Agent Identity を有効にしてエージェントを作成してデプロイします。
  3. 外部サービスまたは ID プロバイダが次の要件を満たしていることを確認します。

  4. エージェントとターゲットの外部サービスについて、次の構成値を特定します。

    • 発行元 URL(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 プールの発行元 URL。
    • 許可されたオーディエンス(aud クレーム): ID トークンの検証時に外部サービスまたは ID プロバイダが想定するオーディエンス URI。
  5. このタスクを完了するために必要なロールが付与されていることを確認します。

必要なロール

Agent Identity を使用してエージェントをデプロイするために必要な権限を取得するには、プロジェクトに対する次の IAM ロールを付与するよう管理者に依頼してください。

  • Gemini Enterprise Agent Platform の Agent Runtime にエージェントをデプロイする: Vertex AI ユーザー (roles/aiplatform.user)
  • エージェント サービスを Cloud Run にデプロイする: Cloud Run 管理者 (roles/run.admin)

ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

これらの事前定義ロールには、Agent Identity を使用してエージェントをデプロイするために必要な権限が含まれています。必要とされる正確な権限については、「必要な権限」セクションを開いてご確認ください。

必要な権限

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. エージェント ID を使用してエージェントを構成する
  2. アプリケーション コードで OIDC ID トークンをリクエストする

Agent Identity を使用してエージェントを構成する

エージェントをデプロイするときに、エージェント ID を有効にします。

  • エージェントを 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: エージェントのコンテナ イメージの 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 URL を呼び出し続けるには、リクエストごとに(たとえば、Python で bind_id_token=False を設定して)証明書のバインドをオプトアウトするか、GOOGLE_API_ENABLE_RUNTIME_BOUND_TOKEN=false を使用してランタイム環境全体でオプトアウトします。サポートされているライブラリのバージョンと例については、証明書バインド トークンを無効にするをご覧ください。

mTLS 経由で証明書バインディングを適用するエンドポイントを呼び出す場合は、mTLS handshake 中にエージェントの 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 またはバックエンド エンドポイントの URL。

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 URL や api.example.com など)。
  • EXTERNAL_SERVICE_ENDPOINT: エージェントが呼び出す mTLS API またはバックエンド エンドポイントの URL。

Go、Node.js、Java などの他の言語のクライアント ライブラリの手順と例については、ID トークンを取得するをご覧ください。これらの言語のクライアント ライブラリは --identity-type=agent-identity をサポートしています。証明書バインド ID トークンをサポートするライブラリは、デフォルトでトークンをバインドし、個々のリクエストをオプトアウトできます。

Agent Identity ID トークンを検証する

外部サービスがエージェントから OIDC ID トークンを受信したら、ターゲット サービスに基づいて次のいずれかの方法でトークンを検証します。

  • マネージド クラウド プラットフォーム(Cloud Run、AWS、Microsoft Azure など): 組み込みの Workload Identity 連携を使用して、カスタム確認コードを記述せずに受信トークンを検証します。
  • カスタム バックエンド サービス、API ゲートウェイ、オンプレミス ワークロード: 公開 OpenID Connect Discovery エンドポイントと JWKS エンドポイントを使用して、プログラムでトークンを検証します。

組み込みの Workload Identity 連携を使用する

受信サービスが、組み込みの IAM 認証または OIDC Workload Identity 連携をサポートするクラウド プラットフォームで実行されている場合は、カスタム トークン検証コードを記述する必要はありません。

  • Cloud Run: 受信サービスが認証済みの上り(内向き)トラフィック(--no-allow-unauthenticated)を使用して Cloud Run で実行されている場合、Cloud Run は上り(内向き)レイヤで受信エージェント ID トークンを検証します。トークンに cnf クレームが含まれている場合は、Cloud Run が mTLS handshake 中にクライアント証明書を検証できるように、受信サービスのリージョン mTLS URL(https://SERVICE_NAME-PROJECT_NUMBER.REGION.mtls.run.app)をターゲットとするように呼び出し元エージェントを構成します。受信サービスに対する Cloud Run 起動元(roles/run.invoker)ロールを呼び出し元エージェントに付与します。詳細については、Cloud Run で MCP サーバーに対して認証するをご覧ください。

    サービスで認証されていない上り(内向き)を許可し、アプリケーション コードでトークンを検証する場合は、プログラムでトークンを検証するをご覧ください。

  • Amazon Bedrock:Cloud de Confiance Security Token Service のディスカバリ URL または発行元 URL と、想定されるオーディエンスを指定して、インバウンド JWT 認証を構成します。手順については、AWS ドキュメントのインバウンド JWT 認可を構成するをご覧ください。

  • Microsoft Entra ID: その他の発行元シナリオでフェデレーション ID 認証情報を構成します。 Cloud de Confiance Security Token Service の発行元 URL、想定されるオーディエンス、サブジェクト ID(sub クレーム)を指定します。手順については、Microsoft Learn ドキュメントのアプリと外部 ID プロバイダの間に信頼関係を作成するをご覧ください。

プログラムでトークンを検証する

エージェントがカスタム API、マイクロサービス、API Gateway、またはオンプレミス ワークロードにリクエストを送信する場合、受信サービスはアクセスを許可する前に受信 OIDC ID トークンを検証する必要があります。通常、エージェントはこのトークンを Authorization: Bearer TOKEN HTTP ヘッダーで渡します。

受信した ID トークンをプログラムで検証するには、次のタスクを完了します。

  1. トークン発行元の URL を抽出して検証する
  2. 公開署名鍵を検出してキャッシュに保存する
  3. トークンの署名とクレームを検証する
  4. 省略可: 証明書のバインディング(cnf クレーム)を検証する
  5. エージェントの SPIFFE ID を認可する

トークン発行元の URL を抽出して検証する

受信リクエストが到着したら、未検証の JWT ペイロードを読み取り、iss(発行元)クレームを抽出します。このクレームには、エージェントの信頼ドメインの Workload Identity プールの URL が含まれています。この URL は、ディスカバリ ドキュメントと公開署名鍵のベース URL として機能します。

送信ネットワーク リクエストを行う前に、iss クレームが、組織またはプロジェクトの想定される Cloud de Confiance Security Token Service Workload Identity プール URL と一致することを確認します。

  • 組織レベルの信頼ドメイン:

    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 です。

公開署名鍵を検出してキャッシュに保存する

発行元 URL を検証したら、 Cloud de Confiance Security Token Service から公開署名鍵を取得してキャッシュに保存します。

  1. OpenID Connect Discovery エンドポイントにクエリを実行する: ベース発行元 URL に /.well-known/openid-configuration を追加し、未認証の HTTP GET リクエストを送信します。

    リクエストのデータを使用する前に、次のように置き換えます。

    • ORGANIZATION_ID: 実際の Cloud de Confiance組織 ID。組織のないプロジェクトの場合は、organizations/ORGANIZATION_ID を projects/PROJECT_NUMBER に置き換えます。
    • TRUST_DOMAIN: エージェントの信頼ドメインの Workload Identity プール ID(例: agents.global.org-123456789012.system.id.goog)。

    HTTP メソッドと URL:

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

    リクエストを送信するには、次のいずれかのオプションを展開します。

    リクエストが成功すると、HTTP 200 OK ステータスと、jwks_uri フィールドを含む OpenID プロバイダのメタデータを含む JSON オブジェクトが返されます。

    {
      "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)エンドポイントにクエリを実行する: OpenID プロバイダのメタデータで返された jwks_uri URL に、認証されていない HTTP GET リクエストを送信します。

    リクエストのデータを使用する前に、次のように置き換えます。

    • ORGANIZATION_ID: 実際の Cloud de Confiance組織 ID。組織のないプロジェクトの場合は、organizations/ORGANIZATION_ID を projects/PROJECT_NUMBER に置き換えます。
    • TRUST_DOMAIN: エージェントの信頼ドメインの Workload Identity プール ID(例: agents.global.org-123456789012.system.id.goog)。

    HTTP メソッドと URL:

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

    リクエストを送信するには、次のいずれかのオプションを展開します。

    リクエストが成功すると、HTTP 200 OK ステータスと、RFC 7517 に従ってフォーマットされた公開鍵の配列を含む JSON オブジェクトが返されます。

    {
      "keys": [
        {
          "kty": "RSA",
          "use": "sig",
          "alg": "RS256",
          "kid": "4d1933f8e6c4e0b512c140989f6655c68997...",
          "n": "uQn4zN_1mQ0VpGv82-Wp3w...",
          "e": "AQAB"
        }
      ]
    }
    
  3. ディスカバリ ドキュメントと鍵をキャッシュに保存する: OpenID Connect Discovery エンドポイントと JWKS エンドポイントの両方からのレスポンスには、次の HTTP キャッシュ ヘッダーが含まれます。

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

    検証パフォーマンスを向上させ、レート制限を回避するために、ディスカバリ ドキュメントと JWKS を最大 24 時間(86400 秒)キャッシュします。

    Cloud de Confiance は、Workload Identity プールの秘密署名鍵と公開署名鍵を定期的にローテーションします。検証ツールが、ローカル鍵キャッシュにない kid(鍵 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 プール発行元の URL と一致することを確認します。
  3. オーディエンス(aud): aud クレームが、サービスに構成されているオーディエンス ID と一致することを確認します。
  4. 発行時刻(iat)と有効期限(exp): iat クレームが過去のものであること、および現在の時刻が exp クレームよりも前であることを確認します(1 ~ 2 分程度のわずかなクロック スキューの許容範囲を考慮します)。

次の例では、Google Tink(tink.jwt)を使用して、JWKS JSON ペイロードに対して Agent Identity 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 handshake 中に提示されたクライアント証明書に対して cnf(x5t#S256)クレームを検証します。

  1. 相互 TLS(mTLS)を終了する: TLS 1.3(RFC 9846)に従って、TLS handshake 中にエージェントの X.509 証明書をリクエストして検証するようにサーバーまたは Ingress プロキシを構成します。
  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 ID を認可する

トークンの署名と標準クレームを確認したら、確認済みの 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(または信頼ドメインの接頭辞)の許可リストと比較してから、保護されたリソースへのアクセスを許可します。

次のステップ