Sortie de la passerelle d'agent d'Agent Runtime vers un MCP externe

1. Introduction

Cet atelier de programmation explore la gouvernance de sortie de la passerelle d'agent pour les agents d'IA qui accèdent à des serveurs MCP (Model Context Protocol) externes hébergés en dehors de Google Cloud.

Les applications d'IA, qu'il s'agisse de chatbots autonomes ou de systèmes autonomes avec des workflows multi-agents, peuvent appeler des outils externes de manière dynamique. Il est essentiel de fournir aux agents un accès contrôlé pour interroger des bases de données, récupérer du contenu Web et exécuter des actions afin de garantir leur sécurité et leur productivité. Toutefois, dans les environnements d'entreprise, la sécurisation de l'exécution des outils d'agent est un défi. Si un agent dispose d'un accès direct au réseau, les attaques par injection de prompt ou les hallucinations du modèle peuvent l'amener à exfiltrer des données sensibles ou à exécuter des commandes destructrices.

Pour gérer les agents autonomes à grande échelle, Agent Gateway fournit un point d'application centralisé et zéro confiance directement intégré à l'architecture Agent Platform. Au lieu de s'appuyer sur des implémentations personnalisées propres à chaque application ou code d'agent, Agent Gateway fournit un routage réseau, une gouvernance des agents et une sécurité d'exécution appliqués au niveau de la plate-forme.

Lorsque l'Agent Gateway fonctionne en mode sortie (agent-to-anywhere), elle sert de proxy pour toutes les requêtes sortantes des agents configurés pour utiliser la passerelle. Chaque requête de charge de travail de l'agent est authentifiée à l'aide de l'identité de l'agent unique et autorisée à l'aide des règles Identity-Aware Proxy (IAP). Les appels d'outil MCP sont décodés et inspectés de manière dynamique pour faire respecter les règles. Les administrateurs de sécurité peuvent appliquer de manière centralisée des autorisations précises pour s'assurer que les agents ne peuvent appeler que les points de terminaison et les méthodes approuvés.

Objectif de l'atelier

  • Agent Gateway en mode sortie (agent-to-anywhere)
  • Extension d'autorisation Identity-Aware Proxy (IAP)
  • Agent ADK Agent Runtime avec identité d'agent
  • Agent Registry avec les points de terminaison de l'API Google et du MCP
  • Connectivité des outils MCP externes aux ensembles de données publics Data Commons
  • Stratégies d'autorisation avec contrôle des accès IAM

figure1

Fig. 1. Architecture de l'atelier de programmation

Objectifs

  • Déployer la passerelle d'agent dans une séquence de configuration structurée
  • Passer des règles d'autorisation du mode dry run au mode appliqué
  • Enregistrer des points de terminaison d'API Google et des serveurs MCP dans Agent Registry
  • Utiliser des règles d'autorisation conditionnelles basées sur les attributs du protocole MCP
  • Auditer les journaux Agent Gateway pour valider la gouvernance de sortie

Ce dont vous avez besoin

  • Un projet Google Cloud avec facturation activée
  • Autorisations IAM pour provisionner les services réseau et les ressources Agent Platform
  • Un shell compatible POSIX (bash ou zsh) avec Google Cloud CLI (composants gcloud et bq) installé
  • Outils de ligne de commande : git, curl, jq (processeur JSON), Python 3 et uv (gestionnaire de packages Python)
  • Une clé API Data Commons sans frais pour accéder aux ensembles de données de test des requêtes

2. Concepts

Séquence de déploiement

Cet atelier de programmation suit une séquence de configuration structurée afin que les agents aient accès aux ressources nécessaires lors de l'initialisation et que la connectivité puisse être confirmée avant l'application des règles d'accès appliquées.

Cet atelier de programmation utilise la séquence de déploiement suivante :

  1. Démarrer en mode DRY_RUN : assurez-vous que les requêtes de l'agent arrivent bien à la passerelle et qu'elles la traversent (mode audit uniquement).
  2. Enregistrez tous les services : enregistrez tous les composants agentiques dans le registre d'agents et confirmez l'accès aux outils de l'agent.
  3. Créez des règles d'autorisation : créez et appliquez des règles d'autorisation pour autoriser le trafic sortant des agents vers les serveurs et points de terminaison MCP.
  4. Passez au mode ENFORCED : mettez à jour la règle d'extension d'autorisation pour appliquer les règles et bloquer le trafic de sortie non autorisé.

figure2

Fig. 2. Séquence de déploiement

Topologie de routage de sortie

La sortie Agent Gateway (agent-to-anywhere) sert de proxy sortant centralisé et zéro confiance pour les charges de travail agentiques. Lorsqu'un agent envoie une requête à un outil ou une API externes, la requête sortante est interceptée par Agent Gateway et évaluée par rapport aux règles de gouvernance avant d'être acheminée vers sa destination. Dans une architecture Google Cloud Agent Platform, Agent Gateway fournit une connectivité au plan de données pour :

  • Réseaux privés (VPC) : trafic sortant ciblant les API, les microservices et les bases de données d'entreprise internes hébergés dans des VPC privés, ainsi que les réseaux sur site ou multicloud accessibles via une connectivité hybride.
  • Réseaux externes (Internet) : trafic sortant ciblant des services Web tiers, des API SaaS ou des points de terminaison publics.
  • Services d'IA et Agent Platform : trafic sortant ciblant les API Google Cloud gérées, les modèles de base, les points de terminaison Google MCP (tels que BigQuery) et les services de gouvernance de plate-forme (Agent Registry et les règles IAP).

figure3

Fig. 3. Topologie de routage de sortie Agent Gateway

Cet atelier de programmation se concentre sur le trafic sortant d'un agent personnalisé sur Agent Runtime ciblant un point de terminaison de serveur MCP tiers externe accessible sur Internet.

Inspection du protocole MCP

La sortie Agent Gateway (agent-to-anywhere) est capable d'analyser le contenu des requêtes MCP et d'évaluer les règles d'accès en fonction d'attributs de protocole précis. Les règles de sortie du serveur de l'agent vers le MCP peuvent inclure des conditions, exprimées en Common Expression Language (CEL), qui sont appliquées au moment de l'exécution pour chaque requête.

Les appels MCP utilisent généralement le format de protocole filaire JSON-RPC et le transport HTTP. Les détails de la méthode MCP appelée (par exemple, tools/call), le nom de l'outil cible et les arguments sont contenus dans la charge utile JSON du corps HTTP.

L'attribut iap.googleapis.com/mcp.toolName est extrait par Agent Gateway en analysant le corps JSON pour trouver l'identifiant d'outil spécifié dans la requête.

Les attributs tels que iap.googleapis.com/mcp.tool.isReadOnly et mcp.tool.isDestructive ne sont généralement pas envoyés dans chaque corps de requête. Il s'agit plutôt d'annotations (métadonnées) associées à l'outil. Ainsi, lorsque la passerelle d'agent extrait le toolName du corps, elle recherche la définition de l'outil et les propriétés associées dans Agent Registry, où le contenu toolspec.json a été enregistré.

figure4

Fig. 4. Inspection MCP Agent Gateway

Les expressions CEL utilisées dans les conditions IAM IAP utilisent le format standard api.getAttribute('iap.googleapis.com/ATTRIBUTE_NAME', 'DEFAULT_VALUE')== 'DESIRED_VALUE'.

Ce tableau décrit les attributs de gouvernance de sortie de la passerelle d'agent qui peuvent être appliqués aux requêtes du serveur MCP :

Attribut

Méthode / Emplacement MCP

Description

mcp.toolName

tools/call (corps)

Identifiant de l'outil cible demandé dans la charge utile RPC (par exemple, "delete_instance")

mcp.tool.isReadOnly

Agent Registry (toolspec.json)

Indique si l'outil est en lecture seule (ne modifie pas son environnement)

mcp.tool.isDestructive

Agent Registry (toolspec.json)

Indique si l'appel de l'outil peut entraîner des modifications non réversibles ou une perte de données.

mcp.tool.isIdempotent

Agent Registry (toolspec.json)

Indique si l'exécution répétée de l'outil avec des arguments identiques produit exactement le même état.

mcp.tool.isOpenWorld

Agent Registry (toolspec.json)

Indique si l'outil dépasse les limites des systèmes internes pour atteindre l'Internet public illimité.

La partie sur les concepts est terminée. Passons à la section Configuration.

3. Configuration

Rôles IAM requis

Les rôles suivants sont requis pour créer les ressources dans cet atelier de programmation :

Catégorie

Rôle IAM requis (ID)

Description

Gestion des API

roles/serviceusage.serviceUsageAdmin

Activer les services d'API Google Cloud

Mise en réseau et passerelle

roles/networkservices.admin

Provisionner la passerelle d'agent

Extensions de service

roles/serviceextensions.admin

Configurer les extensions de routage

Sécurité du réseau

roles/networksecurity.admin

Déployer des règles d'autorisation

Agent Registry

roles/agentregistry.admin

Hôtes autorisés du catalogue

Vertex AI et les agents

roles/aiplatform.admin

Déployer des charges de travail Agent Runtime

Règles de sortie

roles/iap.admin

Appliquer les règles roles/iap.egressor

Cloud Storage

roles/storage.admin

Gérer les buckets de préproduction des déploiements

Journaux et audit

roles/logging.viewer

Inspecter les traces et les journaux d'audit

Vous pouvez également utiliser un rôle de base étendu, comme roles/admin, ou un rôle hérité, comme roles/owner.

Accéder à votre projet

Cet atelier de programmation utilise un seul projet Google Cloud. Les étapes de configuration utilisent la CLI gcloud et les commandes du shell Linux.

Commencez par accéder à la ligne de commande de votre projet Google Cloud :

Définir votre ID de projet

gcloud config set project SET_YOUR_PROJECT_ID_HERE

Authentifier la session

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

Définir des variables d'environnement 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 vous exécutez une installation autogérée du SDK Google Cloud (c'est-à-dire en dehors de Cloud Shell), mettez à jour les composants vers la dernière version.

# update gcloud cli
gcloud components update

Activer les services d'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

La partie concernant la configuration est terminée. Passons à la section Passerelle.

4. Passerelle

Avant d'appliquer des contrôles d'accès, déployez Agent Gateway et configurez son extension d'autorisation en mode DRY_RUN. Cela permet aux appels d'outils sortants de réussir tout en enregistrant les résultats de l'évaluation à des fins d'audit.

Ici, Agent Gateway utilise un registre régional pour prendre en charge les ressources Agent Runtime régionales.

Créer une passerelle

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

La partie concernant la passerelle est terminée. Passons à la section Autorisation.

5. Autorisation

L'extension d'autorisation Agent Gateway pour Identity-Aware Proxy (IAP) est un type d'extension de service utilisé pour déléguer les décisions d'autorisation pour toutes les communications de la plate-forme d'agent.

  1. Flux de délégation : lorsqu'un agent tente d'appeler un point de terminaison externe ou un serveur MCP, il achemine la requête vers Agent Gateway. Au lieu d'évaluer l'accès localement, la passerelle utilise l'extension d'autorisation pour envoyer un callout au service d'évaluation IAP. IAP évalue l'identité de l'agent (basée sur SPIFFE) par rapport à la stratégie IAM de la ressource cible dans le registre des agents. IAP renvoie une décision ALLOW ou DENY à la passerelle, qui transfère le trafic ou le bloque avec un code d'état HTTP 403 Forbidden.
  2. Modes d'application : en mode DRY_RUN, IAP évalue les requêtes et consigne les décisions dans Cloud Logging sans bloquer le trafic. En mode ENFORCE, toute requête provenant d'un agent non autorisé ou adressée à une cible non enregistrée est immédiatement bloquée.
  3. Couche de liaison : l'extension de service est connectée à Agent Gateway à l'aide d'une règle d'autorisation configurée avec le profil REQUEST_AUTHZ.

Extension d'autorisation

Créer une extension d'autorisation

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

Règle d'autorisation

Une règle d'autorisation lie le fournisseur de sécurité (IAP) à la ressource de passerelle cible et spécifie le profil d'interception (REQUEST_AUTHZ).

Créer une règle d'autorisation

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

La partie concernant l'autorisation est terminée. Passons à la section Codebase.

6. Codebase

Le code de l'agent et le script d'enregistrement du point de terminaison utilisés pour cet atelier de programmation sont conservés dans un dépôt GitHub Google Cloud distant. Les étapes suivantes cloneront le dépôt en local, copieront les fichiers nécessaires dans la structure du répertoire de travail actuel, puis supprimeront les fichiers temporaires.

Un bucket de préproduction de stockage est créé pour qu'Agent Runtime puisse importer, compiler et déployer le code d'application de l'agent empaqueté et ses artefacts de dépendance.

Récupérer des artefacts distants

# 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

Créer un bucket de préproduction

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

La partie concernant le codebase est terminée. Passons à la section Registre.

7. Registre

Agent Registry est un inventaire centralisé de tous les agents, serveurs MCP et points de terminaison (API) de l'écosystème d'IA. Il s'agit également d'un catalogue qui peut être utilisé pour lister, rechercher et découvrir d'autres outils et services enregistrés à utiliser par les applications d'IA. Le mode de sortie Agent Gateway (agent-to-anywhere) utilise le modèle de données du registre comme framework de gouvernance pour appliquer le contrôle des accès de sortie. Les attributions de rôle IAM pour les agents appelants principaux sont vérifiées par rapport à la stratégie liée à la ressource de registre.

Afin d'amorcer l'environnement et d'aider les agents à utiliser divers services et API Google, un script est utilisé pour enregistrer rapidement un ensemble commun de points de terminaison d'API à l'aide des noms d'hôte et des emplacements de endpoints/googleapis.txt.

Enregistrer des points de terminaison

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

Valider les points de terminaison

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

La partie sur le registre est terminée. Passons maintenant à la section Data Commons.

8. Data Commons

Data Commons est une initiative de Google visant à organiser des ensembles de données publics et à les rendre disponibles et accessibles à tous. Il s'agit d'un service sans frais accessible à l'aide d'une clé API après la création d'un compte.

Créer une clé API

Une fois votre compte créé, suivez ces étapes pour obtenir une clé API :

  • Connectez-vous au portail de l'API Data Commons.
  • Cliquez sur le bouton My Apps (Mes applications) en haut à droite.
  • Cliquez sur le bouton + NOUVELLE APPLICATION en haut à droite, sous votre nom d'utilisateur.
  • Donnez un nom à votre application (par exemple, "Codelab Agent MCP").
  • Cliquez sur le bouton ACTIVER pour l'API Data Commons. api.datacommons.org
  • Cliquez sur le bouton ENREGISTRER en bas à droite.

Une clé API et un code secret sont alors créés. Cliquez sur l'icône de copie à côté de la valeur de la clé pour copier la clé API. Collez la valeur dans la commande de terminal pour définir la variable d'environnement DC_API_KEY.

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

Créer un serveur MCP toolspec

Lors de l'enregistrement manuel d'un serveur MCP, un fichier de spécification d'outil doit être inclus. L'importation d'un fichier toolspec.json liste tous les outils mis à disposition par le point de terminaison et permet aux autres utilisateurs de les découvrir.

Le script test_mcp.py, inclus dans la base de code agent-datacommons/, génère un fichier toolspec.json en se connectant au serveur MCP cible (via SSE ou HTTP) et appelle list_tools() pour récupérer tous les outils disponibles exposés par le serveur.

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

Un examen de la sortie toolspec générée montre les attributs MCP que l'Agent Gateway peut utiliser pour l'évaluation et l'application des règles de sortie.

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

Enregistrer un serveur 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}

La partie concernant Data Commons est terminée. Passons à la section Exécution.

9. Environnement d'exécution

L'agent ADK agent-datacommons déployé sur Agent Runtime est configuré avec les paramètres suivants dans le script de déploiement pour s'intégrer à Agent Platform :

  • "identity_type": types.IdentityType.AGENT_IDENTITY pour provisionner une identité principale unique basée sur SPIFFE pour l'agent
  • "agent_gateway_config": { "agent_to_anywhere_config": {"agent_gateway": } } pour rediriger tout le trafic sortant initié par l'agent vers Agent Gateway afin d'évaluer et d'appliquer les règles

Déployer l'agent

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

Récupérer les constantes vitales du déploiement

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

Vérifier l'entrée de registre

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

10. Règles

Les règles d'autorisation de gouvernance des agents permettent le trafic d'un agent d'IA via Agent Gateway et vers la destination (par exemple, un point de terminaison de serveur MCP tiers pour une application SaaS). Une fois le trafic arrivé à destination, les autorisations standards au niveau du service ou de l'application autorisent l'accès aux données.

Les autorisations de rôle IAM pour la sortie de la passerelle d'agent permettent d'accéder aux stratégies d'accès qui autorisent l'identité principale de l'agent à accéder aux ressources de destination enregistrées via la passerelle d'agent. Les stratégies sont appliquées au niveau de l'Agent Gateway et validées à l'aide des stratégies IAM Identity-Aware Proxy (IAP).

Attribuer des rôles IAM d'agent pour la sortie Agent Gateway

Agent Gateway vérifie les requêtes entrantes pour s'assurer que l'identité de l'agent appelant dispose de l'autorisation iap.webServiceVersions.egressViaIAP (accordée par le rôle roles/iap.egressor) sur la ressource cible.

L'attribution de roles/iap.egressor à l'identité de l'agent ou à l'ensemble de comptes principaux Agent Runtime sur la ressource de destination sélectionnée autorise ce trafic de sortie. Dans cet atelier de programmation, le rôle est appliqué au compte principal agent, ce qui accorde l'autorisation à l'identité d'agent Agent Runtime spécifique.

Les stratégies IAM sont liées aux ressources de destination, comme défini dans le modèle de données du registre d'agents. La ressource iap_web/agentRegistry représente un niveau "à l'échelle du registre" dans la hiérarchie IAM. Où agentRegistry sert de parent aux ressources enfants individuelles pour agents, mcpServers et endpoints. Dans cet atelier de programmation, la stratégie IAM est liée aux niveaux mcpServer et endpoint, ce qui applique l'autorisation aux ressources enfants spécifiques.

À propos du filtrage conditionnel des outils MCP

Le serveur MCP Data Commons comporte deux outils :

  • search_indicators : pour les questions sur la découverte des données disponibles, la recherche de variables ou la compréhension de la couverture des données
  • get_observations : pour les requêtes permettant de récupérer des points de données ou des séries temporelles spécifiques

Il existe des opérations MCP standards à connaître lorsque vous configurez des règles de gouvernance conditionnelles sur des serveurs MCP. Avant qu'un client MCP puisse effectuer un tools/call pour search_indicators ou get_observations, il doit d'abord envoyer des demandes de découverte et d'établissement de protocole :

  • initialize
  • notifications/initialized
  • tools/list

Pour illustrer le filtrage conditionnel des règles, la règle sera configurée pour les conditions suivantes :

Table. Évaluation des demandes MCP

Requête / Méthode

Valeur mcp.toolName

Évaluation CEL

Résultat

initialize

""

"" in ['search_indicators', '']

✅ AUTORISÉ (200)

tools/list

""

"" in ['search_indicators', '']

✅ AUTORISÉ (200)

search_indicators

"search_indicators"

"search_indicators" in [...]

✅ AUTORISÉ (200)

get_observations

"get_observations"

"get_observations" in [...]

❌ REFUSÉ (403)

Pour autoriser les négociations de protocole et l'appel d'outil search_indicators, la règle de stratégie conditionnelle inclut une autorisation pour "search_indicators" ou "" (chaîne vide).

Configurer la stratégie IAM du serveur MCP IAP du registre

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

REMARQUE  : etag: doit renvoyer la valeur par défaut ACAB, car aucune règle n'a encore été définie.

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

La partie sur les règles est terminée. Passons à la section Audit.

11. Audit

L'extension d'autorisation de l'Agent Gateway fonctionne en mode DRY_RUN. Les requêtes sortantes sont observées et consignées, mais pas bloquées.

Tester les requêtes de l'agent

Ouvrez une fenêtre de navigateur dans l'interface utilisateur de la console Google Cloud et accédez à :

  • Agent Platform → Agents → Déploiements → agent-datacommons
  • Sélectionnez l'onglet Terrain de jeu.

Vous pouvez également exécuter cette commande de terminal et cliquer sur le lien pour accéder à l'atelier de l'agent :

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

Envoyez quelques requêtes de test…

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

Vérifiez que les requêtes renvoient des réponses valides.

Analyser les journaux d'audit

Affichez les journaux et inspectez les évaluations des règles de dry run.

# 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

Mettre à jour la stratégie IAM des points de terminaison IAP du registre

Accorder des autorisations de sortie à l'agent pour le point de terminaison de télémétrie

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

Accorder des autorisations de sortie de l'agent pour le point de terminaison 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}

Accorder des autorisations de sortie de l'agent pour le point de terminaison cloudresourcemanager

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

La partie concernant l'audit est terminée. Passons à la section Appliquer.

12. Appliquer

L'agent a pu effectuer des requêtes avec succès via la passerelle en mode DRY_RUN. Faites passer l'extension d'autorisation IAP de l'Agent Gateway en mode ENFORCE en mettant à jour la règle d'autorisation.

Mettre à jour l'extension d'autorisation

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

Mettre à jour une règle d'autorisation

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

Vérifier l'autorisation conditionnelle

Revenez à l'atelier de l'agent dans l'interface utilisateur de la console.

Envoyez une requête de test supplémentaire (tentez d'appeler l'outil allowedsearch_indicators).

  • What data topics do you have for Peru?

Notez que les requêtes de l'agent envoyées au modèle de fondation Gemini (${REGION}-aiplatform.googleapis.com/...), à l'API de télémétrie (telemetry.googleapis.com/...) et au point de terminaison du serveur MCP Data Commons (api.datacommons.org/mcp) sont transmises avec des codes d'état 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)"

Vérifiez qu'aucune requête n'est bloquée. Recherchez les tentatives de sortie refusées avec des codes d'état HTTP 403 Forbidden dans les journaux d'audit de la passerelle.

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

Vérifier le refus conditionnel

Envoyez une requête de test supplémentaire (tentez d'appeler l'outil Refuséget_observations).

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

L'agent examinera d'abord search_indicators, puis tentera d'utiliser get_observations, mais échouera et la réponse de l'agent restera incomplète.

# 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

Cela confirme que la règle de gouvernance fonctionne comme prévu.

Notez que la deuxième ligne indiquant un état vide et ALLOWED est un événement de journal de fermeture de connexion secondaire émis par Agent Gateway lors de la fermeture du socket après l'envoi de la réponse 403 (car les événements de fermeture de connexion n'ont pas de codes d'état de réponse, httpRequest.status est vide).

La partie sur l'application des règles est terminée. Passons à la section Nettoyage.

13. Nettoyage

# 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

La partie nettoyage est terminée. Passons à la conclusion !

14. Conclusion

Félicitations ! Vous avez réussi à déployer et à gérer les communications sortantes pour un agent accédant à des outils à l'aide d'Agent Gateway.

cosmopup

Cosmopup pense que les ateliers de programmation sont le nec plus ultra !

Et ensuite ?

N'hésitez pas à nous faire part de vos commentaires, questions ou corrections en utilisant ce formulaire de commentaires.

Merci !