Salida de Agent Gateway desde Agent Runtime a MCP externo

1. Introducción

En este codelab, se explora la administración de salida de Agent Gateway para los agentes de IA que acceden a servidores externos del Protocolo de contexto del modelo (MCP) alojados fuera de Google Cloud.

Las apps basadas en IA, desde chatbots independientes hasta sistemas autónomos con flujos de trabajo multiagente, pueden invocar herramientas externas de forma dinámica. Proporcionar a los agentes acceso controlado para consultar bases de datos, recuperar contenido web y ejecutar acciones es fundamental para que sean seguros y productivos. Sin embargo, en los entornos empresariales, proteger la ejecución de herramientas del agente es un desafío. Si un agente tiene acceso directo a la red, los ataques de inyección de instrucciones o las alucinaciones del modelo pueden hacer que el agente filtre datos sensibles o ejecute comandos destructivos.

Para administrar agentes autónomos a gran escala, Agent Gateway proporciona un punto de aplicación centralizado de confianza cero integrado directamente en la arquitectura de Agent Platform. En lugar de depender de implementaciones personalizadas exclusivas para cada aplicación o código de agente, Agent Gateway proporciona enrutamiento de red, administración de agentes y seguridad en el tiempo de ejecución que se aplican a nivel de la plataforma.

Cuando Agent Gateway opera en modo de salida (agent-to-anywhere), reenvía todas las solicitudes salientes de los agentes configurados para usar la puerta de enlace. Cada solicitud de carga de trabajo del agente se autentica con la identidad del agente única y se autoriza con las políticas de Identity-Aware Proxy (IAP). Las llamadas a la herramienta del MCP se decodifican y se inspeccionan de forma dinámica para aplicar las políticas. Los administradores de seguridad pueden aplicar de forma centralizada permisos detallados para garantizar que los agentes solo puedan invocar extremos y métodos aprobados.

Qué compilarás

  • Agent Gateway en modo de salida (del agente a cualquier lugar)
  • Extensión de autorización de Identity-Aware Proxy (IAP)
  • Agente de Agent Runtime ADK con identidad del agente
  • Agent Registry con extremos de la API de Google y de MCP
  • Conectividad de herramientas MCP externas a conjuntos de datos públicos de Data Commons
  • Políticas de autorización con control de acceso de IAM

figure1

Fig. 1: Arquitectura del codelab

Qué aprenderá

  • Cómo implementar Agent Gateway en una secuencia de configuración estructurada
  • Cómo realizar la transición de las políticas de autorización del modo de ejecución de prueba al modo de aplicación forzosa
  • Cómo registrar extremos de la API de Google y servidores MCP en Agent Registry
  • Cómo usar políticas de autorización condicionales basadas en atributos del protocolo de MCP
  • Cómo auditar los registros de Agent Gateway para validar la administración de la salida

Requisitos

  • Un proyecto de Google Cloud con la facturación habilitada.
  • Permisos de IAM para aprovisionar servicios de redes y recursos de Agent Platform
  • Un shell compatible con POSIX (bash o zsh) con Google Cloud CLI (componentes gcloud y bq) instalado
  • Herramientas de línea de comandos: git, curl, jq (procesador JSON), Python 3 y uv (administrador de paquetes de Python)
  • Una clave de API de Data Commons gratuita para acceder a conjuntos de datos de prueba de consultas

2. Conceptos

Secuencia de implementación

Este codelab sigue una secuencia de configuración estructurada para que los agentes tengan acceso a los recursos necesarios en la inicialización y se pueda confirmar la conectividad antes de aplicar las políticas de acceso forzado.

En este codelab, se usa la siguiente secuencia de implementación:

  1. Comienza en el modo DRY_RUN: Asegúrate de que las solicitudes del agente lleguen correctamente a la puerta de enlace y la atraviesen (modo solo de auditoría).
  2. Registra todos los servicios: Registra todos los componentes de agentes en el registro de agentes y confirma el acceso a las herramientas de los agentes.
  3. Crea políticas de autorización: Crea y aplica políticas de autorización para permitir el tráfico de salida de los agentes a los servidores y extremos de MCP.
  4. Cambia al modo ENFORCED: Actualiza la política de extensión de autorización para aplicar políticas y bloquear el tráfico de salida no autorizado.

figure2

Fig. 2: Secuencia de implementación

Topología de enrutamiento de salida

La salida de Agent Gateway (agente a cualquier lugar) actúa como un proxy saliente centralizado de confianza cero para las cargas de trabajo de agentes. Cuando un agente realiza una solicitud a una herramienta o API externa, Agent Gateway intercepta la solicitud saliente y la evalúa en función de las políticas de gobernanza antes de enrutarla a su destino. En una arquitectura de Agent Platform de Google Cloud, Agent Gateway proporciona conectividad del plano de datos a lo siguiente:

  • Redes privadas (VPC): Tráfico saliente dirigido a APIs internas de la empresa, microservicios, bases de datos alojadas en VPC privadas y redes locales o entre nubes a las que se puede acceder a través de conectividad híbrida.
  • Redes externas (Internet): Tráfico saliente que se dirige a servicios web de terceros, APIs de SaaS o extremos públicos.
  • Servicios de IA y Agent Platform: Tráfico saliente que segmenta las APIs de Cloud administradas de Google, los modelos de base, los extremos de MCP de Google (como BigQuery) y los servicios de administración de la plataforma (políticas de Agent Registry y de IAP).

figure3

Fig. 3: Topología de enrutamiento de salida de Agent Gateway

El objetivo de este codelab es el tráfico saliente de un agente personalizado en Agent Runtime que apunta a un extremo de servidor de MCP externo de terceros al que se puede acceder a través de Internet.

Inspección del protocolo MCP

La salida de Agent Gateway (agent-to-anywhere) puede analizar el contenido de las solicitudes de MCP y evaluar las políticas de acceso según atributos de protocolo detallados. Las políticas de salida del servidor de MCP al agente pueden incluir condiciones, expresadas en Common Expression Language (CEL), que se aplican en el tiempo de ejecución en cada solicitud.

Por lo general, las llamadas a MCP usan el formato de protocolo de transferencia JSON-RPC y el transporte HTTP. Los detalles del método de MCP que se invoca (p. ej., tools/call), el nombre de la herramienta de destino y los argumentos se incluyen en la carga útil de JSON del cuerpo HTTP.

Agent Gateway extrae el atributo iap.googleapis.com/mcp.toolName analizando el cuerpo JSON para encontrar el identificador de la herramienta especificado en la solicitud.

Por lo general, los atributos como iap.googleapis.com/mcp.tool.isReadOnly y mcp.tool.isDestructive no se envían en cada cuerpo de la solicitud. En cambio, son anotaciones (metadatos) asociadas a la herramienta. Por lo tanto, cuando Agent Gateway extrae el toolName del cuerpo, busca la definición de la herramienta y las propiedades asociadas en Agent Registry, donde se registró el contenido de toolspec.json.

figure4

Fig. 4: Inspección del MCP de Agent Gateway

Las expresiones de CEL que se usan en las condiciones de IAM de IAP usan el formato estándar api.getAttribute('iap.googleapis.com/ATTRIBUTE_NAME', 'DEFAULT_VALUE')== 'DESIRED_VALUE'.

En esta tabla, se describen los atributos de administración de salida de Agent Gateway que se pueden aplicar a las solicitudes del servidor de MCP:

Atributo

Método o ubicación del MCP

Descripción

mcp.toolName

tools/call (cuerpo)

Es el identificador de la herramienta de destino solicitada en la carga útil de RPC (p. ej., "delete_instance").

mcp.tool.isReadOnly

Agent Registry (toolspec.json)

Indica si la herramienta es de solo lectura (no modifica su entorno).

mcp.tool.isDestructive

Agent Registry (toolspec.json)

Indica si llamar a la herramienta podría provocar modificaciones irreversibles o pérdida de datos.

mcp.tool.isIdempotent

Agent Registry (toolspec.json)

Indica si la ejecución repetida de la herramienta con argumentos idénticos produce exactamente el mismo estado.

mcp.tool.isOpenWorld

Agent Registry (toolspec.json)

Indica si la herramienta va más allá de los sistemas internos delimitados y llega a la Internet pública no delimitada.

Aquí concluye la sección de conceptos. A continuación, se encuentra la sección de Configuración.

3. Configuración

Roles de IAM obligatorios

Se requieren los siguientes roles para crear los recursos en este codelab:

Categoría

Rol de IAM requerido (ID)

Descripción

Administración de API

roles/serviceusage.serviceUsageAdmin

Habilita los servicios de la API de Google Cloud

Redes y puerta de enlace

roles/networkservices.admin

Aprovisiona Agent Gateway

Service Extensions

roles/serviceextensions.admin

Configura las extensiones de enrutamiento

Seguridad de red

roles/networksecurity.admin

Implementa políticas de autorización

Agent Registry

roles/agentregistry.admin

Hosts permitidos del catálogo

Vertex AI y agentes

roles/aiplatform.admin

Implementa cargas de trabajo de Agent Runtime

Políticas de salida

roles/iap.admin

Aplica políticas de roles/iap.egressor

Cloud Storage

roles/storage.admin

Administra buckets de etapa de pruebas de implementación

Registros y auditoría

roles/logging.viewer

Cómo inspeccionar registros y registros de auditoría

Como alternativa, usa un rol básico amplio, como roles/admin, o un rol heredado, como roles/owner.

Accede a tu proyecto

En este codelab, se usa un solo proyecto de Google Cloud. En los pasos de configuración, se usan la CLI de gcloud y los comandos de shell de Linux.

Para comenzar, accede a la línea de comandos de tu proyecto de Google Cloud:

Establece tu ID del proyecto

gcloud config set project SET_YOUR_PROJECT_ID_HERE

Autentica la sesión

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

Establece variables de entorno de shell

# 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-datacommons"
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}"
export MCP_DISPLAY_NAME="api.datacommons.org"
export MCP_RESOURCE_NAME="${REGION}-datacommons-mcp"
export MCP_URL="https://api.datacommons.org/mcp"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${RE_AGENT_NAME}
echo ${RE_AGENT_ID_SET}
echo ${STAGING_BUCKET}
echo ${MCP_DISPLAY_NAME}
echo ${MCP_RESOURCE_NAME}
echo ${MCP_URL}
# create local dir for config files
mkdir -p cfg

Si ejecutas una instalación autoadministrada del SDK de Google Cloud (es decir, fuera de Cloud Shell), actualiza los componentes a la versión más reciente.

# update gcloud cli
gcloud components update

Habilita los servicios de la 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

Aquí concluye la parte de configuración… a continuación, se abordará la sección Puerta de enlace.

4. Puerta de enlace

Antes de aplicar los controles de acceso, implementa Agent Gateway y configura su extensión de autorización en el modo DRY_RUN. Esto permite que las llamadas a herramientas salientes se realicen correctamente y, al mismo tiempo, se registren los resultados de la evaluación para fines de auditoría.

Aquí, Agent Gateway usa un registro regional para admitir recursos de Agent Runtime regionales.

Crear puerta de enlace

# 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}

Aquí concluye la parte de la puerta de enlace… a continuación, veremos la sección de Autorización.

5. Autorización

La extensión de autorización de Agent Gateway para Identity-Aware Proxy (IAP) es un tipo de extensión de servicio que se usa para delegar decisiones de autorización para todas las comunicaciones de Agent Platform.

  1. Flujo de delegación: Cuando un agente intenta invocar un extremo externo o un servidor de MCP, enruta la solicitud a Agent Gateway. En lugar de evaluar el acceso de forma local, la puerta de enlace usa la extensión de autorización para enviar una llamada al servicio de evaluación de IAP. IAP evalúa la identidad del agente (basada en SPIFFE) en función de la política de IAM del recurso de destino en Agent Registry. IAP devuelve una decisión ALLOW o DENY a la puerta de enlace, que reenvía el tráfico o lo bloquea con un código de estado HTTP 403 Forbidden.
  2. Modos de aplicación: En el modo DRY_RUN, IAP evalúa las solicitudes y registra las decisiones en Cloud Logging sin bloquear el tráfico. En el modo ENFORCE, se bloquea de inmediato cualquier solicitud de un agente no autorizado o a un destino no registrado.
  3. Capa de vinculación: La extensión de servicio se conecta a Agent Gateway a través de una política de autorización configurada con el perfil REQUEST_AUTHZ.

Extensión de autorización

Crea una extensión de autorización

# 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}

Política de autorización

Una política de autorización vincula el proveedor de seguridad (IAP) al recurso de puerta de enlace de destino y especifica el perfil de intercepción (REQUEST_AUTHZ).

Crea una política de autorización

# 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}

Con esto, concluye la parte de autorización… a continuación, veremos la sección Codebase.

6. Base de código

El código del agente y la secuencia de comandos de registro del extremo que se usan para este codelab se mantienen en un repositorio remoto de GitHub de Google Cloud. En los siguientes pasos, se clonará el repositorio de forma local, se copiarán los archivos necesarios en la estructura del directorio de trabajo actual y, luego, se borrarán los archivos temporales.

Se crea un bucket de almacenamiento provisional para que Agent Runtime suba, compile y, luego, implemente el código de la aplicación del agente empaquetado y sus artefactos de dependencia.

Recupera artefactos remotos

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

Crea un bucket de etapa de pruebas

# 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)"

Aquí concluye la parte de la base de código. A continuación, se abordará la sección Registro.

7. Registro

Agent Registry es un inventario centralizado de todos los agentes, servidores MCP y extremos (APIs) en el ecosistema de IA. También es un catálogo que se puede usar para enumerar, buscar y descubrir otras herramientas y servicios registrados para su uso en aplicaciones de IA. El modo de salida de Agent Gateway (agent-to-anywhere) usa el modelo de datos del registro como marco de trabajo de administración para aplicar el control de acceso de salida. Los permisos de rol de IAM para los agentes de llamada de la principal se verifican en función de la política vinculada al recurso del registro.

Para iniciar el entorno y brindar asistencia a los agentes con varias APIs y servicios de Google, se usa una secuencia de comandos para registrar rápidamente un conjunto común de extremos de API con nombres de host y ubicaciones de endpoints/googleapis.txt.

Registra extremos

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

Verifica los extremos

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

Con esto, concluye la sección del registro. A continuación, veremos la sección de Data Commons.

8. Data Commons

Data Commons es una iniciativa de Google para organizar conjuntos de datos públicos y hacerlos disponibles y accesibles para cualquier persona. Es un servicio gratuito al que se puede acceder con una clave de API después de crear una cuenta.

Crear clave de API

Después de crear una cuenta, sigue estos pasos para obtener una clave de API:

  • Accede al portal de la API de Data Commons.
  • Haz clic en el botón "Mis aplicaciones" en la esquina superior derecha.
  • Haz clic en el botón "+ NUEVA APP" en la esquina superior derecha, debajo de tu nombre de usuario.
  • Asigna un nombre a tu app (p. ej., "Codelab Agent MCP").
  • Haz clic en el botón "HABILITAR" de la API de Data Commons. api.datacommons.org
  • Haz clic en el botón “SAVE” en la esquina inferior derecha.

Esto crea una clave de API y un secreto. Haz clic en el ícono de “copiar” junto al valor de la clave para “Copiar la clave de API”. Pega el valor en el comando de la terminal para establecer la variable de entorno DC_API_KEY.

# set api key env var
 export DC_API_KEY="YOUR_API_KEY_HERE"

Crear servidor de MCP toolspec

Cuando registras un servidor de MCP de forma manual, se debe incluir un archivo de especificación de la herramienta durante el registro. Cuando subes un archivo toolspec.json, se enumeran todas las herramientas que pone a disposición el endpoint y se permite que otros usuarios las descubran.

La secuencia de comandos test_mcp.py, incluida en la base de código agent-datacommons/, genera un archivo toolspec.json conectándose al servidor de MCP de destino (a través de SSE o HTTP) y llama a list_tools() para recuperar todas las herramientas disponibles expuestas por el servidor.

# generate toolspec for registry ingestion
uv --directory agent-datacommons run python3 test_mcp.py --toolspec=include --token="${DC_API_KEY}"

Un vistazo al resultado de toolspec generado muestra los atributos de MCP que Agent Gateway puede usar para la evaluación y la aplicación de la política de salida.

# show toolspec mcp attributes
jq '.tools[] | {name, isReadOnly, isDestructive, isIdempotent, isOpenWorld}' agent-datacommons/toolspec.json

Registra el servidor de MCP

# register mcp server
gcloud agent-registry services create ${MCP_RESOURCE_NAME} \
  --location=${REGION} \
  --display-name="${MCP_DISPLAY_NAME}" \
  --description="mcp server for data commons" \
  --mcp-server-spec-type=tool-spec \
  --mcp-server-spec-content=agent-datacommons/toolspec.json \
  --interfaces=url=${MCP_URL},protocolBinding=JSONRPC
# list registry regional mcp servers
gcloud agent-registry mcp-servers list --location=${REGION} --format="table(displayName, interfaces.url)"
# show mcp server registry details
gcloud agent-registry services describe ${MCP_RESOURCE_NAME} --location=${REGION}
# fetch mcp server registry id
export MCP_REGISTRY_ID=$(gcloud agent-registry services describe ${MCP_RESOURCE_NAME} \
  --location=${REGION} \
  --format="value(registryResource.basename())")
echo ${MCP_REGISTRY_ID}

Aquí concluye la sección de Data Commons… a continuación, la sección Tiempo de ejecución.

9. Entorno de ejecución

El agente del ADK de agent-datacommons implementado en Agent Runtime se configura con los siguientes parámetros en la secuencia de comandos de implementación para integrarse con Agent Platform:

  • "identity_type": types.IdentityType.AGENT_IDENTITY para aprovisionar una identidad principal única basada en SPIFFE para el agente
  • "agent_gateway_config": { "agent_to_anywhere_config": {"agent_gateway": } } para dirigir todo el tráfico saliente iniciado por el agente a Agent Gateway para la evaluación y aplicación de políticas

Implementa el agente

# deploy agent runtime workload
uv --directory agent-datacommons 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 data commons stats" \
  --enable-telemetry \
  --enable-agent-identity \
  --agent-gateway-egress=${AGW_URI} \
  --env-var="DC_API_KEY=${DC_API_KEY}"

Recupera los signos vitales de la implementación

# 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 RE_AGENT_REGISTRY_ID=$(gcloud agent-registry agents list \
  --location=${REGION} \
  --filter="displayName=${RE_AGENT_NAME}" \
  --format="value(uid)")
echo ${RE_AGENT_REGISTRY_ID}

Verifica la entrada del registro

# show agent resource registry details
gcloud agent-registry agents describe ${RE_AGENT_REGISTRY_ID} --location=${REGION}

10. Políticas

Las políticas de autorización de gobernanza de agentes permiten el tráfico de un agente de IA a través de Agent Gateway y hacia el destino (p. ej., un extremo del servidor de MCP externo para una aplicación de SaaS). Una vez que el tráfico llega al destino, los permisos normales a nivel de servicio o de aplicación autorizan el acceso a los datos.

Los otorgamientos de roles de IAM para la salida de Agent Gateway habilitan políticas de acceso que permiten que la identidad principal del agente acceda a los recursos de destino registrados a través de Agent Gateway. Las políticas se aplican a nivel de Agent Gateway y se validan con las políticas de IAM de Identity-Aware Proxy (IAP).

Otorga roles de IAM de agente para la salida de Agent Gateway

Agent Gateway verifica las solicitudes entrantes para validar que la identidad del agente que llama tenga el permiso iap.webServiceVersions.egressViaIAP (otorgado por el rol roles/iap.egressor) en el recurso de destino.

Otorgar roles/iap.egressor a la identidad del agente o al conjunto de principales de Agent Runtime en el recurso de destino seleccionado permite este tráfico de salida. En este codelab, el rol se aplica a la principal agente, que otorga permiso a la identidad específica del agente de Agent Runtime.

Las políticas de IAM están vinculadas a los recursos de destino según se definen en el modelo de datos del Registro de agentes. El recurso iap_web/agentRegistry representa un nivel "en todo el registro" en la jerarquía de IAM. Aquí, agentRegistry actúa como el elemento superior de los recursos secundarios individuales de agents, mcpServers y endpoints. En este codelab, la política de IAM se vincula a los niveles mcpServer y endpoint, lo que aplica el permiso a los recursos secundarios específicos.

Acerca del filtrado condicional de MCP

El servidor de MCP de Data Commons tiene dos herramientas:

  • search_indicators: Para consultas sobre el descubrimiento de los datos disponibles, la búsqueda de variables o la comprensión de la cobertura de datos
  • get_observations: Para las consultas que recuperan puntos de datos o series temporales específicos

Hay algunas operaciones estándar de MCP que debes tener en cuenta cuando configures políticas de administración condicionales en servidores de MCP. Antes de que un cliente de MCP pueda realizar una tools/call para search_indicators o get_observations, primero debe enviar solicitudes de descubrimiento y de protocolo de enlace:

  • initialize
  • notifications/initialized
  • tools/list

Para demostrar el filtrado de políticas condicionales, la política se configurará para estas condiciones:

Tabla. Evaluación de políticas para solicitudes de MCP

Solicitud / método

Valor de mcp.toolName

Evaluación de CEL

Resultado

initialize

""

"" in ['search_indicators', '']

✅ PERMITIDO (200)

tools/list

""

"" in ['search_indicators', '']

✅ PERMITIDO (200)

search_indicators

"search_indicators"

"search_indicators" in [...]

✅ PERMITIDO (200)

get_observations

"get_observations"

"get_observations" in [...]

❌ RECHAZADO (403)

Para permitir las negociaciones de protocolo y la llamada a la herramienta search_indicators, la regla de política condicional incluye un permiso para "search_indicators" o "" (cadena vacía).

Configura la política de IAM del servidor de MCP de IAP del registro

# show iap iam policy for mcp server
gcloud beta iap web get-iam-policy \
  --region=${REGION} \
  --resource-type=agent-registry \
  --mcp-server=${MCP_REGISTRY_ID}

NOTA: etag: debería devolver el valor predeterminado ACAB, ya que aún no se definieron políticas.

# fetch active etag on policy for mcp server
export IAP_ETAG=$(gcloud beta iap web get-iam-policy \
  --resource-type=agent-registry --region=${REGION} \
  --mcp-server=${MCP_REGISTRY_ID} --format="value(etag)")
echo ${IAP_ETAG}
# create policy config file
cat > cfg/iap-policy-dc-agent-to-dc-mcp-tool-1.json << EOF
{
  "bindings": [
    {
      "role": "roles/iap.egressor",
      "members": [
        "${RE_AGENT_IDENTITY}"
      ],
      "condition": {
        "title": "allow ${RE_AGENT_NAME} to use search_indicators tool for ${MCP_DISPLAY_NAME}",
        "expression": "api.getAttribute('iap.googleapis.com/mcp.toolName', '') in ['search_indicators', '']"
      }
    }
  ],
  "etag": "${IAP_ETAG}",
  "version": 3
}
EOF
# import policy file (bind iam policy)
gcloud beta iap web set-iam-policy cfg/iap-policy-dc-agent-to-dc-mcp-tool-1.json \
  --resource-type=agent-registry \
  --mcp-server=${MCP_REGISTRY_ID} \
  --region=${REGION}
# verify iap iam policy for mcp server
gcloud beta iap web get-iam-policy \
  --region=${REGION} \
  --resource-type=agent-registry \
  --mcp-server=${MCP_REGISTRY_ID}

Aquí concluye la sección de políticas. A continuación, se abordará la sección de Auditoría.

11. Auditoría

La extensión de autorización de Agent Gateway funciona en modo DRY_RUN. Se observan y registran las solicitudes salientes, pero no se bloquean.

Prueba las preguntas del agente

Abre una ventana del navegador en la IU de la consola de Google Cloud y navega a la siguiente ubicación:

  • Agent Platform → Agents → Deployments → agent-datacommons
  • Selecciona la pestaña Playground.

O bien, haz eco de este comando de terminal y haz clic en el vínculo para ir al Playground del agente:

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

Envía algunas búsquedas de prueba…

  • What data do you have on water quality in Zimbabwe?
  • Compare the life expectancy, economic inequality, and GDP growth for BRICS nations

Verifica que las búsquedas devuelvan respuestas válidas.

Analiza los registros de auditoría

Consulta los registros y, luego, inspecciona las evaluaciones de las políticas de prueba de validación.

# list unique urls with http status and iap authorization result
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND httpRequest.requestUrl:*" \
  --project=${PROJ_ID} \
  --limit=200 \
  --format="value(httpRequest.status, jsonPayload.authzPolicyInfo.result, httpRequest.requestUrl)" | sort -u
200     ALLOWED https://api.datacommons.org/mcp
200     ALLOWED https://cloudresourcemanager.googleapis.com:443/google.cloud.resourcemanager.v3.Projects/GetProject
200     ALLOWED https://telemetry.googleapis.com/v1/traces
200     ALLOWED https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/publishers/google/models/gemini-2.5-flash:generateContent
200     ALLOWED https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}
200     ALLOWED https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}:appendEvent
200     ALLOWED https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}/sessions/${RE_SESSION_ID}/events
202     ALLOWED https://api.datacommons.org/mcp

Actualiza la política de IAM de los extremos de IAP del registro

Otorga permisos de salida del agente para el extremo de telemetría

# set var for endpoint display name
export ENDPOINT_1_DISPLAY_NAME="telemetry.googleapis.com"
echo ${ENDPOINT_1_DISPLAY_NAME}
# fetch endpoint registry id
export ENDPOINT_1_REGISTRY_ID=$(gcloud agent-registry services list \
  --location=${REGION} \
  --filter="displayName=${ENDPOINT_1_DISPLAY_NAME}" \
  --format="value(registryResource.basename())")
echo ${ENDPOINT_1_REGISTRY_ID}
# create policy config file
cat > cfg/iap-policy-re-agent-to-ep-1.json << EOF
{
  "bindings": [
    {
      "role": "roles/iap.egressor",
      "members": [
        "${RE_AGENT_IDENTITY}"
      ]
    }
  ]
}
EOF
# import policy file (bind iam policy)
gcloud -q beta iap web set-iam-policy cfg/iap-policy-re-agent-to-ep-1.json \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_1_REGISTRY_ID} \
  --region=${REGION}
# verify iap iam policy for telemetry endpoint
gcloud beta iap web get-iam-policy \
  --region=${REGION} \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_1_REGISTRY_ID}

Otorga permisos de salida del agente para el endpoint de aiplatform

# set var for endpoint display name
export ENDPOINT_2_DISPLAY_NAME="${REGION}-aiplatform.googleapis.com"
echo ${ENDPOINT_2_DISPLAY_NAME}
# fetch endpoint registry id
export ENDPOINT_2_REGISTRY_ID=$(gcloud agent-registry services list \
  --location=${REGION} \
  --filter="displayName=${ENDPOINT_2_DISPLAY_NAME}" \
  --format="value(registryResource.basename())")
echo ${ENDPOINT_2_REGISTRY_ID}
# create policy config file
cat > cfg/iap-policy-re-agent-to-ep-2.json << EOF
{
  "bindings": [
    {
      "role": "roles/iap.egressor",
      "members": [
        "${RE_AGENT_IDENTITY}"
      ]
    }
  ]
}
EOF
# import policy file (bind iam policy)
gcloud -q beta iap web set-iam-policy cfg/iap-policy-re-agent-to-ep-2.json \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_2_REGISTRY_ID} \
  --region=${REGION}
# verify iap iam policy for aiplatform endpoint
gcloud beta iap web get-iam-policy \
  --region=${REGION} \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_2_REGISTRY_ID}

Otorga permisos de salida del agente para el extremo de Cloud Resource Manager

# set var for endpoint display name
export ENDPOINT_3_DISPLAY_NAME="cloudresourcemanager.googleapis.com"
echo ${ENDPOINT_3_DISPLAY_NAME}
# fetch endpoint registry id
export ENDPOINT_3_REGISTRY_ID=$(gcloud agent-registry services list \
  --location=${REGION} \
  --filter="displayName=${ENDPOINT_3_DISPLAY_NAME}" \
  --format="value(registryResource.basename())")
echo ${ENDPOINT_3_REGISTRY_ID}
# create policy config file
cat > cfg/iap-policy-re-agent-to-ep-3.json << EOF
{
  "bindings": [
    {
      "role": "roles/iap.egressor",
      "members": [
        "${RE_AGENT_IDENTITY}"
      ]
    }
  ]
}
EOF
# import policy file (bind iam policy)
gcloud -q beta iap web set-iam-policy cfg/iap-policy-re-agent-to-ep-3.json \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_3_REGISTRY_ID} \
  --region=${REGION}
# verify iap iam policy for cloudresourcemanager endpoint
gcloud beta iap web get-iam-policy \
  --region=${REGION} \
  --resource-type=agent-registry \
  --endpoint=${ENDPOINT_3_REGISTRY_ID}

Aquí concluye la parte de la auditoría. A continuación, se abordará la sección Aplicar.

12. Aplicar

El agente pudo realizar solicitudes exitosas a través de la puerta de enlace en modo DRY_RUN. Actualiza la política de autorización para realizar la transición de la extensión de autorización del IAP de Agent Gateway al modo ENFORCE.

Actualiza la extensión de autorización

# 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}

Actualiza la política de autorización

# 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}

Verifica el permiso condicional

Regresa al Playground del agente en la IU de la consola.

Envía una consulta de prueba adicional (intenta invocar la herramienta permitidasearch_indicators)…

  • What data topics do you have for Peru?

Observa que las solicitudes del agente al modelo fundamental de Gemini (${REGION}-aiplatform.googleapis.com/...), a la API de telemetría (telemetry.googleapis.com/...) y al extremo del servidor de MCP de Data Commons (api.datacommons.org/mcp) se pasan con códigos de estado 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)"

Comprueba que no se bloquee ninguna solicitud. Busca cualquier intento de salida rechazado con códigos de estado HTTP 403 Forbidden en los registros de auditoría de la puerta de enlace.

# 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
  )"
# show gateway logs for mcp requests with method and tool name
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND jsonPayload.agentGatewayInfo.mcpInfo.method:*" \
  --project=${PROJ_ID} \
  --limit=10 \
  --format="table(
    timestamp.date(tz=LOCAL):label=TIMESTAMP,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=IAP_AUTHZ,
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD,
    jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL_NAME,
    httpRequest.requestUrl:label=URL
  )"

Verifica el rechazo condicional

Envía una consulta de prueba adicional (intenta invocar la herramienta rechazadaget_observations)…

  • What are the diabetes levels in Peru compared to Slovakia?

El agente primero mirará search_indicators y, luego, intentará usar get_observations, pero fallará y la respuesta del agente quedará incompleta.

# show gateway logs for mcp requests with method and tool name
gcloud logging read \
  "resource.type=\"networkservices.googleapis.com/Gateway\" \
  AND jsonPayload.agentGatewayInfo.mcpInfo.method:*" \
  --project=${PROJ_ID} \
  --limit=10 \
  --format="table(
    timestamp.date(tz=LOCAL):label=TIMESTAMP,
    httpRequest.status:label=STATUS,
    jsonPayload.authzPolicyInfo.result:label=IAP_AUTHZ,
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD,
    jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL_NAME,
    httpRequest.requestUrl:label=URL
  )"
TIMESTAMP            STATUS  IAP_AUTHZ  MCP_METHOD                 TOOL_NAME          URL
YYYY-MM-DDTHH:MM:SS  403     DENIED     tools/call                 get_observations   https://api.datacommons.org/mcp
YYYY-MM-DDTHH:MM:SS          ALLOWED    tools/call                 get_observations   https://api.datacommons.org/mcp
YYYY-MM-DDTHH:MM:SS  403     DENIED     tools/call                 get_observations   https://api.datacommons.org/mcp
YYYY-MM-DDTHH:MM:SS  200     ALLOWED    tools/call                 search_indicators  https://api.datacommons.org/mcp
YYYY-MM-DDTHH:MM:SS  200     ALLOWED    tools/list                                    https://api.datacommons.org/mcp
YYYY-MM-DDTHH:MM:SS  202     ALLOWED    notifications/initialized                     https://api.datacommons.org/mcp

Esto valida que la política de administración funcione según lo previsto.

Ten en cuenta que la segunda fila que indica un estado en blanco y ALLOWED es un evento de registro de cierre de conexión secundario que emite Agent Gateway cuando cierra el socket después de enviar la respuesta 403 (porque los eventos de cierre de conexión no tienen códigos de estado de respuesta, httpRequest.status está en blanco).

Aquí concluye la parte de aplicación… a continuación, veremos la sección Limpieza.

13. Limpieza

# 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
# delete storage bucket
gcloud -q storage rm --recursive gs://${STAGING_BUCKET}

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

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

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

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

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

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

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

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

# next
# remove manual registry entry
gcloud -q agent-registry services delete ${MCP_RESOURCE_NAME} --location=${REGION}
# 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 beta service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap-enforced --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-datacommons endpoints

# end

Aquí concluye la sección de limpieza. A continuación, veremos la Conclusión.

14. Conclusión

¡Felicitaciones! Implementaste y controlaste correctamente las comunicaciones salientes de un agente que accede a herramientas con Agent Gateway.

cosmopup

Cosmopup cree que los codelabs son lo mejor de lo mejor.

¿Qué sigue?

Si tienes comentarios, preguntas o correcciones, usa este formulario de comentarios.

¡Gracias!