從 Agent Runtime 到 Google MCP 的 Agent Gateway 輸出

1. 簡介

本程式碼實驗室將探討 AI 代理存取遠端 Google Cloud Model Context Protocol (MCP) 伺服器時,Agent Gateway 的輸出管理功能。

從獨立聊天機器人到具備多代理工作流程的自治系統,AI 應用程式都能動態叫用外部工具。為代理程式提供受控存取權,讓代理程式查詢資料庫、擷取網頁內容及執行動作,是確保代理程式安全且有效率的關鍵。不過,在企業環境中,確保代理程式工具的執行安全是一大挑戰。如果代理程式具有直接網路存取權,提示詞注入攻擊或模型幻覺可能會導致代理程式洩露私密資料或執行破壞性指令。

如要大規模管理自主代理,Agent Gateway 會提供集中式零信任強制執行點,直接整合至 Agent Platform 架構。Agent Gateway 不會依賴各個應用程式或代理程式碼專屬的自訂實作項目,而是在平台層級強制執行網路路由、代理程式管理和執行階段安全措施。

當 Agent Gateway 以輸出 (代理至任何位置) 模式運作時,會代理設定為使用閘道的所有代理輸出要求。系統會使用專屬的代理程式身分驗證每個代理程式工作負載要求,並使用 Identity-Aware Proxy (IAP) 政策授權。系統會動態解碼並檢查 MCP 工具呼叫,確保符合政策規定。安全管理員可以集中強制執行精細權限,確保代理只能叫用核准的端點和方法。

建構內容

  • 輸出模式下的 Agent Gateway (agent-to-anywhere)
  • Identity-Aware Proxy (IAP) 授權擴充功能
  • 具有代理身分的 Agent Runtime ADK 代理
  • Agent Registry,內含 Google API 和 MCP 端點
  • 使用 IAM 存取權控管的授權政策
  • 使用 MCP 查詢的 BigQuery 資料集

figure1

圖 1. 程式碼研究室架構

課程內容

  • 如何依結構化設定順序部署 Agent Gateway
  • 如何將授權政策從模擬測試模式轉換為強制執行模式
  • 如何在 Agent Registry 中註冊 Google API 端點和 MCP 伺服器
  • 如何稽核 Agent Gateway 記錄,驗證輸出管理

需求條件

  • 已啟用計費功能的 Google Cloud 雲端專案
  • 佈建網路服務、BigQuery 資料集和 Agent Platform 資源的 IAM 權限
  • 已安裝 Google Cloud CLI (gcloudbq 元件) 的 POSIX 相容 Shell (bashzsh)
  • 指令列工具:gitcurljq (JSON 處理器)、Python 3 和 uv (Python 套件管理工具)

2. 概念

部署順序

使用管理控制項部署 Agent Gateway 時,請務必按照結構化設定順序操作,確保代理程式在初始化時能存取必要資源,並順利發出網路要求。

本程式碼研究室使用下列部署順序:

  • 以模擬執行模式啟動:如果代理程式執行階段設定為在閘道完全佈建前,將撥出電話轉送至閘道,工作負載就會無法初始化。請先在 DRY_RUN 模式中設定閘道授權擴充功能,確保代理程式流量抵達閘道時,不會有任何要求遭到捨棄。
  • 註冊所有服務:使用 Agent Gateway 的所有代理、MCP 伺服器和端點都必須註冊至 Agent Registry。如果來源或目的地未註冊,系統會拒絕要求。部署在 Agent Runtime 和 Google MCP 伺服器上的代理程式會自動註冊。任何 Google API 端點或自訂 MCP 伺服器都必須手動註冊。
  • 強制執行授權政策:授權政策用於授予代理主體 roles/iap.egressor 角色,並將其繫結至目標登錄資源,允許已註冊的代理存取代理元件。使用模擬測試模式評估代理程式行為,然後定義政策,允許所選輸出流量通過閘道。政策設定完成後,請切換至「強制執行」ENFORCED模式,讓閘道主動強制執行控管政策。

figure2

圖 2. 部署順序

輸出路由拓撲

閘道通常會管理傳送至後端服務的連入流量 (ingress)。Agent Gateway 在輸出 (代理至任何位置) 模式下運作,可做為代理式工作負載的集中式零信任輸出 Proxy。

當 AI 應用程式或代理工作負載嘗試叫用外部工具或 API 時,Agent Gateway 會攔截外送要求,並根據控管政策進行評估,然後再轉送至目的地:

  • 私人網路 (VPC):以企業內部 API、微服務、私人 VPC 中代管的資料庫,以及可透過混合式連線存取的內部部署或跨雲端網路為目標的輸出流量。
  • 外部網路 (網際網路):以第三方網路服務、SaaS API 或公開端點為目標的出站流量。
  • AI 服務和 Agent Platform:以代管的 Google Cloud API、基礎模型、Google MCP 端點 (例如 BigQuery) 和平台控管服務 (Agent Registry 和 IAP 政策) 為目標的輸出流量。

figure3

圖 3. Agent Gateway 輸出轉送拓撲

本 Codelab 的重點是從 Agent Runtime 上的自訂代理傳出的流量,該代理會以 BigQuery 的遠端 Google MCP 伺服器端點為目標。

3. 設定

必要的 IAM 角色

如要在本程式碼研究室中建立資源,您必須具備下列角色:

類別

必要 IAM 角色 (ID)

說明

API 管理

roles/serviceusage.serviceUsageAdmin

啟用 Google Cloud API 服務

網路和閘道

roles/networkservices.admin

佈建 Agent Gateway

Service Extensions

roles/serviceextensions.admin

設定轉送擴充功能

網路安全

roles/networksecurity.admin

部署授權政策

Agent Registry

roles/agentregistry.admin

允許目錄存取的主機

Vertex AI 和代理程式

roles/aiplatform.admin

部署 Agent Runtime 工作負載

輸出政策

roles/iap.admin

套用 roles/iap.egressor 政策

BigQuery

roles/bigquery.admin

設定結構定義和測試資料集

Cloud Storage

roles/storage.admin

管理部署作業暫存值區

記錄和稽核

roles/logging.viewer

檢查追蹤記錄和稽核記錄

或者,您也可以使用廣泛的基本角色 (例如 roles/admin) 或舊版角色 roles/owner

存取專案

本程式碼研究室使用單一 Google Cloud 雲端專案。設定步驟會使用 gcloud CLI 和 Linux 殼層指令。

首先,請存取 Google Cloud 雲端專案指令列:

設定專案 ID

gcloud config set project SET_YOUR_PROJECT_ID_HERE

驗證工作階段

# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login

設定殼層環境變數

# set custom var for slug (eg, "foo") and region preference
export SLUG="foo"
export REGION="us-central1"
export MREGION="us"
echo ${SLUG}
echo ${REGION}
echo ${MREGION}
# create project vars (automatic)
export PROJ_ID=$(gcloud config list --format="value(core.project)")
export PROJ_NO=$(gcloud projects describe ${PROJ_ID} --format="value(projectNumber)")
export ORG_ID=$(gcloud projects get-ancestors ${PROJ_ID} --format="value(id)" | tail -n 1)
echo ${PROJ_ID}
echo ${PROJ_NO}
echo ${ORG_ID}
# create resource vars (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-ata"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export RE_AGENT_NAME="agent-dj"
export RE_AGENT_ID_SET="principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJ_NO}"
export STAGING_BUCKET="agent-staging-${PROJ_NO}"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${RE_AGENT_NAME}
echo ${RE_AGENT_ID_SET}
echo ${STAGING_BUCKET}
# create local dir for config files
mkdir -p cfg

啟用 API 服務

# enable google apis (agent platform bundle, part 1)
gcloud services enable \
  agentregistry.googleapis.com \
  aiplatform.googleapis.com \
  apphub.googleapis.com \
  apptopology.googleapis.com \
  cloudapiregistry.googleapis.com \
  cloudtrace.googleapis.com \
  compute.googleapis.com \
  dataform.googleapis.com \
  iam.googleapis.com \
  iamconnectors.googleapis.com \
  iap.googleapis.com \
  logging.googleapis.com \
  modelarmor.googleapis.com \
  monitoring.googleapis.com \
  networksecurity.googleapis.com \
  networkservices.googleapis.com \
  notebooks.googleapis.com \
  observability.googleapis.com
# enable google apis (agent platform bundle, part 2)
gcloud services enable \
  securitycenter.googleapis.com \
  saasservicemgmt.googleapis.com \
  storage.googleapis.com \
  telemetry.googleapis.com \
  texttospeech.googleapis.com \
  discoveryengine.googleapis.com

設定部分到此結束,接下來請前往「閘道」部分。

4. 閘道

強制執行存取控管前,請先部署 Agent Gateway,並在 DRY_RUN 模式中設定授權擴充功能。這樣一來,外送工具呼叫就能成功,同時記錄評估結果以供稽核。

這裡的 Agent Gateway 使用區域登錄檔,支援區域 Agent Runtime 資源。

建立閘道

# create agent gateway config file (regional registry)
cat > cfg/${AGW_NAME}.yaml << EOF
name: ${AGW_NAME}
protocols:
  - MCP
googleManaged:
  governedAccessPath: AGENT_TO_ANYWHERE
registries:
  - "//agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}"
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
  --source="cfg/${AGW_NAME}.yaml" \
  --location=${REGION}
# show agent gateway details (verify deployment state)
gcloud network-services agent-gateways describe ${AGW_NAME} \
  --location=${REGION}

閘道部分到此結束,接下來請參閱「授權」部分。

5. 授權

Identity-Aware Proxy (IAP) 的 Agent Gateway 授權擴充功能是一種服務擴充功能,用於將所有 Agent Platform 通訊的授權決策委派出去。

  1. Agent Gateway 委派流程:當代理嘗試叫用外部端點或 MCP 伺服器時,系統會將要求轉送至 Agent Gateway。閘道不會在本地評估存取權,而是使用授權擴充功能,將回呼傳送至 IAP 評估服務。IAP 會根據 Agent Registry 中目標資源的 IAM 政策,評估代理 (以 SPIFFE 為基礎) 身分。IAP 會將 ALLOWDENY 決策傳回閘道,閘道會轉送流量或以 HTTP 403 Forbidden 狀態碼封鎖流量。
  2. 強制執行模式:DRY_RUN 模式下,IAP 會評估要求並在 Cloud Logging 中記錄決策,但不會封鎖流量。在 ENFORCE 模式下,系統會立即封鎖來自未經授權代理程式的要求,或傳送至未註冊目標的要求。
  3. 繫結層:服務擴充功能會使用以 REQUEST_AUTHZ 設定檔設定的授權政策,連線至 Agent Gateway。

授權擴充功能

建立授權擴充功能

# create authz extension config file (dry run mode)
cat > cfg/${AGW_NAME}-svc-ext-authz-iap-dryrun.yaml << EOF
name: ${AGW_NAME}-svc-ext-authz-iap-dryrun
service: iap.googleapis.com
failOpen: true
timeout: 1s
metadata:
  iamEnforcementMode: "DRY_RUN"
  iapPolicyVersion: "V1"
EOF
# import authz extension file (create extension)
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-iap-dryrun \
  --source=cfg/${AGW_NAME}-svc-ext-authz-iap-dryrun.yaml \
  --location=${REGION}
# show authz extension details (verify extension state)
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-iap-dryrun \
  --location=${REGION}

授權政策

授權政策會將安全防護供應商 (IAP) 繫結至目標閘道資源,並指定攔截設定檔 (REQUEST_AUTHZ)。

建立授權政策

# create authz policy config file (attach dry-run authz extension)
cat > cfg/${AGW_NAME}-authz-policy-profile-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-profile-iap
target:
  resources:
    - "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
  authzExtension:
    resources:
      - "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap-dryrun"
EOF
# import authz policy config file (enable authz policy)
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-profile-iap \
  --source=cfg/${AGW_NAME}-authz-policy-profile-iap.yaml \
  --location=${REGION}
# show authz policy details (verify dry run mode)
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-profile-iap \
  --location=${REGION}

授權部分到此結束,接下來請前往「程式碼集」部分。

6. 程式碼集

本程式碼研究室使用的代理程式碼、BigQuery 資料集和註冊指令碼,都維護在遠端 Google Cloud GitHub 存放區中。下列步驟會在本機複製存放區、將必要檔案複製到目前的工作目錄結構,然後清除不需要的暫時檔案。

系統會為 Agent Runtime 建立儲存空間暫存 bucket,用於上傳、建構及部署封裝的代理程式應用程式程式碼及其依附元件構件。

擷取遠端構件

# clone remote repository to temp local dir
git clone https://github.com/GoogleCloudPlatform/cloud-networking-solutions.git ./temp_agw_cuj_arun_egress_gmcp
# copy agent runtime and endpoint definitions to working project dir
cp -r temp_agw_cuj_arun_egress_gmcp/codelabs/agw-cuj-arun-egress-gmcp/agent-dj ./agent-dj
cp -r temp_agw_cuj_arun_egress_gmcp/codelabs/agw-cuj-arun-egress-gmcp/endpoints ./endpoints
# remove temporary directory
rm -rf temp_agw_cuj_arun_egress_gmcp

建立 BigQuery 資料集

# create bq dataset schema and load data
bq --project_id=${PROJ_ID} query \
  --use_legacy_sql=false < agent-dj/setup.sql

建立暫存 bucket

# create storage bucket for agent deployment artifacts
gcloud storage buckets create gs://${STAGING_BUCKET} --location=${REGION}
# verify staging bucket url
gcloud storage buckets list --format="value(storage_url)"

程式碼集部分到此結束,接下來請前往「登錄」部分。

7. 註冊資料庫

Agent Registry 是 AI 生態系統中所有代理、MCP 伺服器和端點 (API) 的集中式清單。此外,這個目錄還可用於列出、搜尋及探索其他已註冊的工具和服務,供 AI 應用程式使用。Agent Gateway 輸出 (agent-to-anywhere) 模式會使用登錄 資料模型做為治理架構,強制執行輸出存取控管。系統會根據繫結至登錄資源的政策,檢查主體呼叫代理程式的 IAM 角色授權。

為了啟動環境並使用各種 Google API 和服務支援代理程式,系統會使用指令碼,透過 endpoints/googleapis.txt 的主機名稱和位置,快速註冊一組常見的 API 端點。

註冊端點

# run python script to register google api endpoints
python3 endpoints/register_endpoints.py \
  --multi-region=${MREGION} \
  --region=${REGION} \
  --mtls-endpoints=include

驗證端點

# list regional endpoints (verify registration)
gcloud agent-registry endpoints list --location=${REGION} \
  --format="table(displayName, name.basename():label=ENDPOINT_ID, interfaces[0].url:label=URL)"

登錄檔部分到此結束,接下來請前往「執行階段」部分。

8. 執行階段

部署至 Agent Runtime 的 agent-dj ADK 代理程式會在部署指令碼中設定下列設定,以便與 Agent Platform 整合:

  • "identity_type": types.IdentityType.AGENT_IDENTITY,為代理佈建專屬的 SPIFFE 主體身分
  • "agent_gateway_config": { "agent_to_anywhere_config": {"agent_gateway": } },將所有代理發起的輸出流量導向 Agent Gateway,以進行政策評估和強制執行

部署代理

# deploy agent runtime workload
uv --directory agent-dj run python3 deploy_agent.py \
  --project=${PROJ_ID} \
  --region=${REGION} \
  --src-dir=./agent \
  --staging-bucket=${STAGING_BUCKET} \
  --display-name="${RE_AGENT_NAME}" \
  --description="agent for dj contact info" \
  --enable-telemetry \
  --enable-agent-identity \
  --agent-gateway-egress=${AGW_URI} \
  --allow-token-sharing

擷取部署作業的健康指標

# fetch agent runtime resource (reasoning engine) id
export RE_ENGINE_ID=$(curl -s -X GET \
  "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" | \
  jq -r --arg name "${RE_AGENT_NAME}" \
  '.reasoningEngines[] | select(.displayName==$name) | .name | split("/") | last')
echo ${RE_ENGINE_ID}
# fetch agent runtime (reasoning engine) agent identity
export RE_AGENT_IDENTITY=$(gcloud agent-registry agents list \
  --location=${REGION} --filter="displayName=${RE_AGENT_NAME}" \
  --format="value(attributes.'agentregistry.googleapis.com/system/RuntimeIdentity'.principal)")
echo ${RE_AGENT_IDENTITY}
# fetch agent registry uid for agent
export AGENT_UID=$(gcloud agent-registry agents list \
  --location=${REGION} \
  --filter="displayName=${RE_AGENT_NAME}" \
  --format="value(uid)")
echo ${AGENT_UID}

驗證登錄檔項目

# show agent resource registry details
gcloud agent-registry agents describe ${AGENT_UID} --location=${REGION}
agentId: urn:agent:projects-${PROJ_NO}:projects:${PROJ_NO}:locations:${REGION}:aiplatform:reasoningEngines:${RE_ENGINE_ID}
attributes:
  agentregistry.googleapis.com/system/Framework:
    framework: google-adk
  agentregistry.googleapis.com/system/RuntimeIdentity:
    principal: principal://agents.global.org-${PROJ_NO}.system.id.goog/resources/aiplatform/projects/${PROJ_NO}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}
  agentregistry.googleapis.com/system/RuntimeReference:
    uri: //aiplatform.googleapis.com/projects/${PROJ_NO}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}
createTime: 'YYYY-MM-DDTHH:MM:SS.ssssssZ'
description: agent for dj contact info
displayName: agent-dj
name: projects/${PROJ_ID}/locations/${REGION}/agents/agentregistry-${RE_AGENT_ID}
protocols:
- interfaces:
  - protocolBinding: HTTP_JSON
    url: https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:query
  - protocolBinding: HTTP_JSON
    url: https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery
  type: CUSTOM
uid: agentregistry-00000000-0000-0000-1234-4567abcd1234
updateTime: 'YYYY-MM-DDTHH:MM:SS.ssssssZ'

驗證閘道設定

# verify agent gateway routing specification
curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  | jq '{displayName: .displayName, name: .name, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'

授予資源的代理程式 IAM 角色

資源的 IAM 角色授權可讓代理主體身分存取 BigQuery、MCP 工具 (適用於 Google API) 和其他必要的 AI 平台服務。這些政策會透過 IAM 在資源層級強制執行。

# grant bigquery query execution role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/bigquery.user"

# grant bigquery data viewer role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/bigquery.dataViewer"

# grant mcp tool execution role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/mcp.toolUser"
# grant ai platform user role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/aiplatform.user"

# grant agent default access role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/aiplatform.agentDefaultAccess"

# grant agent registry viewer role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/agentregistry.viewer"
# grant cloud logging writer role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/logging.logWriter"

# grant cloud monitoring writer role
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/monitoring.metricWriter"

# grant browser role for resource manager lookup
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/browser"

驗證資源的代理程式 IAM 角色

# verify active role bindings for agent identity
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:${RE_AGENT_IDENTITY}" \
  --format="value(bindings.role)"

執行階段部分到此結束,接下來請前往「政策」部分。

9. 政策

代理程式控管授權政策允許 AI 代理程式透過 Agent Gateway 將流量傳輸至目的地 (例如 BigQuery 的 Google Cloud MCP 伺服器端點)。流量抵達目的地後,系統會透過一般 IAM 權限授權資料存取權 (已在上一節中啟用)。

Agent Gateway 輸出內容的 IAM 角色授權可啟用存取政策,允許代理主體身分透過 Agent Gateway 存取已註冊的目的地資源。系統會在 Agent Gateway 層級強制執行政策,並使用 Identity-Aware Proxy (IAP) IAM 政策驗證政策。

授予代理程式 IAM 角色,以供代理程式閘道輸出使用

Agent Gateway 會檢查傳入的要求,驗證呼叫代理身分是否對目標資源具有 iap.webServiceVersions.egressViaIAP 權限 (由 roles/iap.egressor 角色授予)。

在所選目標資源上,將 roles/iap.egressor 授予代理程式身分或 Agent Runtime 主體組合,即可允許這項輸出流量。在本程式碼研究室中,角色會套用至主體 set,授予專案中所有 Agent Runtime 代理程式身分的權限。

IAM 政策會繫結至 Agent Registry 資料模型中定義的目的地資源。iap_web/agentRegistry 資源代表 IAM 階層中的「整個登錄檔」層級。其中 agentRegistryagentsmcpServersendpoints 各別子項資源的父項。在本程式碼研究室中,IAM 政策會繫結至登錄檔層級,並將權限套用至所有子項資源。

設定 IAP 區域登錄檔 IAM 政策

# show iap iam policy for regional registry
gcloud beta iap web get-iam-policy --resource-type=agent-registry --region=${REGION}
# retrieve active etag on policy for regional registry
export IAP_ETAG=$(gcloud beta iap web get-iam-policy --resource-type=agent-registry --region=${REGION} --format="value(etag)")
echo ${IAP_ETAG}
# create policy config file
cat > cfg/iap-policy-re-agent-set-to-registry-${REGION}.json << EOF
{
  "bindings": [
    {
      "role": "roles/iap.egressor",
      "members": [
        "${RE_AGENT_ID_SET}"
      ]
    }
  ],
  "etag": "${IAP_ETAG}"
}
EOF
# import policy file (bind iam policy)
gcloud beta iap web set-iam-policy cfg/iap-policy-re-agent-set-to-registry-${REGION}.json \
  --resource-type=agent-registry \
  --region=${REGION}
# verify iap iam policy for regional registry
gcloud beta iap web get-iam-policy --resource-type=agent-registry --region=${REGION}

政策部分到此結束,接下來請前往「稽核」一節。

10. 稽核

Agent Gateway 授權擴充功能目前處於 DRY_RUN 模式。系統會觀察及記錄傳出要求,但不會封鎖。

測試代理查詢

開啟瀏覽器視窗,前往 Google Cloud 控制台使用者介面,然後依序點選:

  • Agent Platform → Agents → Deployments → agent-dj
  • 選取「Playground」分頁標籤

或者,您也可以回應這個終端機指令,然後按一下連結,跳到代理程式遊樂場:

# playground
echo "https://console.cloud.google.com/agent-platform/runtimes/locations/${REGION}/agent-engines/${RE_ENGINE_ID}/playground?project=${PROJ_ID}"

提交一些測試查詢。

  • How many DJs do we have on file?
  • What is the phone number of DJ Cosmopup?

確認查詢會傳回有效的回覆 (例如「檔案中有 12 位 DJ」)。

分析稽核記錄

查看記錄並檢查模擬測試政策評估結果。

# query gateway logs for dry run
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND httpRequest.requestUrl:*" \
  --project=${PROJ_ID} \
  --limit=10 \
  --format="table(
    timestamp.date(tz=LOCAL):label=TIMESTAMP,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=IAP_AUTHZ,
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD,
    httpRequest.requestUrl:label=URL
  )"
TIMESTAMP            METHOD  STATUS  IAP_AUTHZ  MCP_METHOD  URL
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://telemetry.googleapis.com/v1/traces
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}:appendEvent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/publishers/google/models/gemini-2.5-flash:generateContent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}:appendEvent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED    tools/call  https://bigquery.googleapis.com/mcp
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}:appendEvent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/publishers/google/models/gemini-2.5-flash:generateContent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED    tools/call  https://bigquery.googleapis.com/mcp
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED                https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/publishers/google/models/gemini-2.5-flash:generateContent
YYYY-MM-DDTHH:MM:SS  POST    200     ALLOWED    tools/call  https://bigquery.googleapis.com/mcp

稽核部分到此結束,接下來請前往「強制執行」部分。

11. 強制執行

代理程式能夠透過閘道,以 DRY_RUN 模式提出要求並成功執行。更新授權政策,將 Agent Gateway IAP 授權擴充功能轉換為 ENFORCE 模式。

更新授權擴充功能

# create authz extension config file (enforced mode)
cat > cfg/${AGW_NAME}-svc-ext-authz-iap-enforced.yaml << EOF
name: ${AGW_NAME}-svc-ext-authz-iap-enforced
service: iap.googleapis.com
failOpen: false
timeout: 1s
metadata:
  iapPolicyVersion: "V1"
EOF
# import authz extension file (create extension)
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-iap-enforced \
  --source=cfg/${AGW_NAME}-svc-ext-authz-iap-enforced.yaml \
  --location=${REGION}
# list authz extensions (imported configs)
gcloud service-extensions authz-extensions list --location=${REGION}

更新授權政策

# re-write authz policy config file (pointing to enforced authz extension)
cat > cfg/${AGW_NAME}-authz-policy-profile-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-profile-iap
target:
  resources:
    - "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
  authzExtension:
    resources:
      - "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap-enforced"
EOF
# import authz policy config file (enable new authz policy)
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-profile-iap \
  --source=cfg/${AGW_NAME}-authz-policy-profile-iap.yaml \
  --location=${REGION}
# show authz policy details (verify enforced mode)
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-profile-iap \
  --location=${REGION}

驗證強制執行狀態

返回控制台 UI 中的代理程式「Playground」

提交其他測試查詢...

  • What DJ Fishfry's credit card number?

觀察傳遞至 Gemini 基礎模型 (${REGION}-aiplatform.googleapis.com/...) 和 MCP 伺服器端點 (bigquery.googleapis.com/mcp) 的代理程式要求,是否都附有 HTTP 200 OK 狀態碼。

# show gateway logs for http requests
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND httpRequest.requestUrl:*" \
  --project=${PROJ_ID} \
  --limit=10 \
  --format="table(
    timestamp.date(tz=LOCAL):label=TIMESTAMP,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=IAP_AUTHZ,
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD,
    httpRequest.requestUrl:label=URL)"

確認沒有任何要求遭到封鎖。在閘道稽核記錄中,找出任何遭拒的輸出嘗試,並查看 HTTP 403 Forbidden 狀態碼。

# show gateway logs for authz denies
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND (jsonPayload.authzPolicyInfo.result=\"DENIED\" OR httpRequest.status=403)" \
  --project=${PROJ_ID} \
  --limit=10 \
  --format="table(
    timestamp.date(tz=LOCAL):label=TIMESTAMP,
    httpRequest.requestMethod:label=METHOD,
    httpRequest.status:label=STATUS,
    jsonPayload.enforcedGatewaySecurityPolicy.serverNameIndication:label=SNI,
    jsonPayload.authzPolicyInfo.result:label=AUTHZ_RESULT,
    jsonPayload.authzPolicyInfo.policies[0].name.basename():label=DENYING_POLICY
  )"

「強制執行」部分到此結束,接下來請前往「清除」部分。

12. 清除

# delete agent
curl -s -X DELETE "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}?force=true" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)"

# next
# remove agent resource iam bindings
for ROLE in \
  "roles/bigquery.user" \
  "roles/bigquery.dataViewer" \
  "roles/mcp.toolUser" \
  "roles/aiplatform.user" \
  "roles/aiplatform.agentDefaultAccess" \
  "roles/agentregistry.viewer" \
  "roles/logging.logWriter" \
  "roles/monitoring.metricWriter" \
  "roles/browser"; do
  gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
    --member="${RE_AGENT_IDENTITY}" \
    --role="${ROLE}"
done

# next
# delete storage bucket
gcloud -q storage rm --recursive gs://${STAGING_BUCKET}

# delete bigquery dataset and contents
bq rm -r -f -d ${PROJ_ID}:dj_ds

# next
# reset/clear iap regional registry iam policy
export IAP_ETAG=$(gcloud beta iap web get-iam-policy --resource-type=agent-registry --region=${REGION} --format="value(etag)")
cat > cfg/iap-policy-empty.json << EOF
{
  "bindings": [],
  "etag": "${IAP_ETAG}"
}
EOF

gcloud beta iap web set-iam-policy cfg/iap-policy-empty.json \
  --resource-type=agent-registry \
  --region=${REGION}

# next
# delete gateway resources
gcloud -q beta network-security authz-policies delete ${AGW_NAME}-authz-policy-profile-iap --location=${REGION}

gcloud -q beta service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap-dryrun --location=${REGION}

gcloud -q network-services agent-gateways delete ${AGW_NAME} --location=${REGION}

# next
# clean up local working directories and generated configs
rm -rf cfg agent-dj endpoints

# end

清理作業到此結束,接下來請參閱結論

13. 結語

恭喜!您已成功部署及控管代理程式透過 Agent Gateway 存取工具時的外送通訊!

cosmopup

Cosmopup 認為程式碼研究室最棒!

後續步驟

歡迎使用這份意見回饋表單提供任何意見、問題或修正建議

感謝您!