1. Introduction
Cet atelier de programmation explore la gouvernance des entrées Agent Gateway pour les agents d'IA hébergés sur Agent Runtime.
Agent Gateway fonctionnant en mode entrée (client vers agent) permet de régir les communications entre les clients (utilisateurs finaux humains, agents de bureau, IDE de programmation, agents pairs, etc.) et les agents Agent Runtime hébergés. Ce mode permet de protéger les agents contre les attaques par injection de requêtes entrantes ou les contenus nuisibles envoyés par les clients. Tout le trafic entrant est traité à l'aide d'extensions d'autorisation et de Model Armor pour sécuriser le point d'entrée du réseau pour toutes les interactions avec l'agent.
Objectif de l'atelier
- Agent Gateway en mode entrée (client vers agent)
- Extension d'autorisation Model Armor
- Agent ADK Agent Runtime avec identité d'agent
- Données de fichier Cloud Storage interrogées par l'agent à l'aide de MCP
- Modèles Model Armor pour filtrer les requêtes et les réponses des LLM
- Modèles Sensitive Data Protection pour anonymiser les données
Fig. 1. Architecture de l'atelier de programmation
Objectifs
- Déployer Agent Gateway pour filtrer le trafic entrant vers un agent
- Configurer les extensions d'autorisation et la délégation Model Armor
- Créer et déployer des modèles Model Armor personnalisés
- Créer et déployer des modèles Sensitive Data Protection personnalisés
- Tester et valider les règles de filtrage des LLM
Ce dont vous avez besoin
- Un projet Google Cloud avec facturation activée
- Autorisations IAM pour provisionner des services réseau, des ensembles de données BigQuery et des ressources de la plate-forme d'agents
- Un shell compatible POSIX (
bashouzsh) avec Google Cloud CLI (composantgcloud) installé - Outils de ligne de commande :
git,curl,jq(processeur JSON), Python 3 etuv(gestionnaire de packages Python)
2. Concepts
Sens du trafic et rôles de passerelle
Agent Gateway fonctionne comme un proxy réseau compatible avec les agents, mais son rôle opérationnel change en fonction de la direction du trafic :
- Mode Agent-to-anywhere (sortie) : fonctionne comme un proxy sortant. Lorsqu'un agent appelle des outils de base de données externes, des serveurs MCP tiers ou des API, la passerelle de sortie gère la découverte de services, le routage, le TLS mutuel (
mTLS), l'injection dynamique d'identifiants OAuth et le contrôle des accès aux points de terminaison. - Mode client-agent (entrée) : fonctionne comme une passerelle de sécurité de l'interface utilisateur. Son objectif principal est de protéger l'entrée du runtime d'exécution de l'agent en interceptant et en assainissant les requêtes en langage naturel entrantes avant qu'elles n'atteignent le code agentique ou les modèles d'IA.
Chemin d'accès entrant à Agent Runtime
Les requêtes client ciblant un agent hébergé sur Agent Runtime sont destinées au point de terminaison de l'API aiplatform.googleapis.com.
POST https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:query
Ce flux de communication entrant vers le point de terminaison de l'API représente le chemin d'accès entrant client-agent.
Pour sécuriser ce chemin d'accès Ingress géré par Google, Agent Gateway s'intègre directement au Google Front End (GFE) au niveau de la couche d'infrastructure de diffusion d'API. Lorsque vous déployez un agent géré sur Agent Runtime, Google lie de manière native la règle d'autorisation de la passerelle d'entrée aux requêtes client entrantes en périphérie du réseau.
Fig. 2. Gouvernance des entrées avec Agent Gateway vers Agent Runtime
Comme l'inspection a lieu au niveau du frontend avant que les requêtes n'entrent dans Agent Runtime, cette architecture n'introduit aucune surcharge réseau ni latence de saut interne supplémentaires. La mise à l'échelle est gérée automatiquement par l'infrastructure de l'interface utilisateur, ce qui élimine la nécessité de gérer les plages d'adresses IP internes, les équilibreurs de charge ou les routes DNS personnalisées.
Nettoyage des menaces en ligne avec Model Armor
L'évaluation des identifiants de l'appelant et l'application du contrôle des accès IAM (roles/aiplatform.user) sont gérées de manière native par le niveau d'hébergement de l'API aiplatform. La passerelle d'entrée elle-même n'effectue pas d'autorisation d'identité, mais se concentre plutôt sur la sécurité du contenu à l'aide des extensions d'autorisation configurées avec un profil CONTENT_AUTHZ. La passerelle sert de point d'application des règles en ligne. Elle intercepte les requêtes en langage naturel en transit avant qu'elles n'atteignent la boucle de raisonnement de l'agent d'IA ou le LLM sous-jacent.
Lorsqu'une requête utilisateur entrante arrive au service d'interface, la passerelle lance un appel ext_proc (traitement externe) au service d'extension d'autorisation Model Armor régional, qui transmet l'appel au plan de données Model Armor. Model Armor agit comme un pare-feu en langage naturel. Il évalue le texte par rapport aux modèles actifs pour détecter les risques de sécurité :
- Injections de prompts indirectes et tentatives de jailbreaking
- URL malveillantes, langage toxique ou contenu dangereux
- Informations permettant d'identifier personnellement l'utilisateur (
PII) et fuite de données sensibles
Si le modèle inclut des filtres Sensitive Data Protection (SDP), Model Armor effectue un appel gRPC supplémentaire au service Cloud SDP. Cloud SDP inspecte la charge utile à l'aide du modèle spécifié, effectue toute anonymisation ou masquage demandé, puis renvoie le résultat nettoyé en amont pour qu'il soit transféré de manière sécurisée.
Si un cas de non-respect des règles ou une correspondance de données sensibles non masquées est détecté, la passerelle bloque ou masque la charge utile à la périphérie avant qu'elle n'entre dans l'environnement d'exécution. Par conséquent, l'application d'agent d'IA en cours d'exécution reste protégée et ne traite jamais de charges utiles malveillantes ou non masquées.
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 |
| Activer les services d'API Google Cloud |
Mise en réseau et passerelle |
| Provisionner une passerelle d'agent |
Extensions de service |
| Configurer les extensions de routage |
Sécurité du réseau |
| Déployer des règles d'autorisation |
Protection des données sensibles |
| Gérer les modèles d'inspection et d'anonymisation SDP |
Model Armor |
| Créer et gérer des modèles de sécurité |
Agent Platform |
| Déployer des charges de travail Agent Runtime |
Cloud Storage |
| Gérer les buckets de déploiement et de données client |
Administration IAM |
| Associer des autorisations au niveau du projet pour l'identité de l'agent |
Journaux et audit |
| 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 :
- Cloud Shell à l'adresse
shell.cloud.google.com, ou - Un terminal local avec
gcloudCLI installé
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"
echo ${SLUG}
echo ${REGION}
# 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)
export USER_IDENTITY=$(gcloud config get-value account)
echo ${PROJ_ID}
echo ${PROJ_NO}
echo ${ORG_ID}
echo ${USER_IDENTITY}
# create resource vars (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-cta"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export RE_AGENT_NAME="agent-crm"
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 DATA_BUCKET="customer-data-${PROJ_NO}"
export MCP_URL="https://storage.mtls.googleapis.com/storage/mcp"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${RE_AGENT_NAME}
echo ${RE_AGENT_ID_SET}
echo ${STAGING_BUCKET}
echo ${DATA_BUCKET}
echo ${MCP_URL}
# create local dir for config files
mkdir -p cfg
Mettre à jour gcloud cli (recommandé)
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
# enable google apis (all the rest)
gcloud services enable \
dlp.googleapis.com
La partie concernant la configuration est terminée. Passons à la section Passerelle.
4. Passerelle
Déployez une passerelle Agent Gateway gérée par Google fonctionnant en mode client-agent (CLIENT_TO_AGENT). Contrairement aux passerelles de sortie qui nécessitent des associations au registre d'agents pour acheminer les appels sortants, la passerelle d'entrée se lie directement au niveau du frontend pour servir de point d'application intégré pour les requêtes entrantes ciblant Agent Runtime.
Alors que les règles de sortie commencent souvent en mode DRY_RUN au niveau de la passerelle, la gouvernance du contenu d'entrée (CONTENT_AUTHZ) est déployée directement en mode appliqué. La journalisation ou le blocage actif et précis sont plutôt contrôlés en amont dans les modèles Model Armor individuels.
Créer une passerelle
# create agent gateway config file
cat > cfg/${AGW_NAME}.yaml <<EOF
name: ${AGW_NAME}
protocols:
- MCP
googleManaged:
governedAccessPath: CLIENT_TO_AGENT
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
--source="cfg/${AGW_NAME}.yaml" \
--location=${REGION}
Valider la passerelle
# list agent gateways (in region)
gcloud network-services agent-gateways list --location=${REGION}
# show agent gateway details (verify deployment state)
gcloud network-services agent-gateways describe ${AGW_NAME} --location=${REGION}
La partie sur la passerelle est terminée. Passons maintenant à la section Model Armor.
5. Model Armor
Modèles de Fiche
Créez un modèle d'inspection et d'anonymisation Sensitive Data Protection (SDP) à utiliser dans le modèle de réponse Model Armor. Cette configuration signale les numéros de sécurité sociale américains (SSN) à masquer.
Créer un modèle d'inspection
Le modèle d'inspection identifie les informations sensibles (US_SOCIAL_SECURITY_NUMBER) dans les données.
# create inspect template
curl -fsS -X POST "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" \
-d @- << EOF
{
"templateId": "agw-ssn-inspect-template",
"inspectTemplate": {
"displayName": "ssn inspect template",
"inspectConfig": {
"infoTypes": [
{ "name": "US_SOCIAL_SECURITY_NUMBER" }
],
"minLikelihood": "POSSIBLE"
}
}
}
EOF
Créer un modèle d'anonymisation
Le modèle d'anonymisation spécifie la transformation à appliquer aux numéros de sécurité sociale trouvés par le modèle d'inspection. Dans ce cas, la transformation consiste à remplacer le numéro de sécurité sociale par l'infoType.
# create de-identify template
curl -fsS -X POST "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" \
-d @- << EOF
{
"templateId": "agw-ssn-redaction-template",
"deidentifyTemplate": {
"displayName": "SSN Redaction Template",
"deidentifyConfig": {
"infoTypeTransformations": {
"transformations": [{
"primitiveTransformation": { "replaceWithInfoTypeConfig": {} }
}]
}
}
}
}
EOF
Valider les modèles SDP
# get (describe) inspect template
curl -fsS -X GET "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" | jq
# get (describe) de-identify template
curl -fsS -X GET "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" | jq
Modèles Model Armor
Le point de terminaison par défaut de l'API Model Armor est global (modelarmor.googleapis.com). Toutefois, les ressources Model Armor pour les modèles et les moteurs d'évaluation sont localisées dans des régions géographiques spécifiques. Le proxy de point de terminaison régional Google Cloud (REP), ou point de terminaison d'API régional, pour Model Armor est https://modelarmor.${LOCATION}.rep.googleapis.com/.
Par défaut, lorsque vous exécutez gcloud model-armor ..., l'interface CLI tente d'envoyer des requêtes API au point de terminaison mondial standard (https://modelarmor.googleapis.com/). Un remplacement du point de terminaison de l'API est utilisé pour rediriger toutes les requêtes HTTP du SDK/de l'interface CLI pour Model Armor directement vers le niveau d'API rep.googleapis.com régional où ces modèles liés à la localisation sont réellement créés, stockés et interrogés.
Définir un remplacement d'API
# set api endpoint override per location
gcloud config set api_endpoint_overrides/modelarmor "https://modelarmor.${REGION}.rep.googleapis.com/"
Vérifier le remplacement de l'API
# view api overrides on active gcloud config
gcloud config list api_endpoint_overrides/
Créer un modèle de filtre de requête
Créez un modèle de filtre de requête pour bloquer les contenus incitant à la haine, le harcèlement, les contenus à caractère sexuel explicite et les attaques par injection d'URI. La journalisation sera activée pour enregistrer des informations détaillées sur l'application des règles. Des codes et messages d'erreur personnalisés sont également configurés pour les requêtes bloquées.
# create model armor template (request)
gcloud beta model-armor templates create ${AGW_NAME}-modar-req-template \
--project=${PROJ_ID} \
--location=${REGION} \
--rai-settings-filters='[
{ "filterType": "HATE_SPEECH", "confidenceLevel": "MEDIUM_AND_ABOVE" },
{ "filterType": "HARASSMENT", "confidenceLevel": "MEDIUM_AND_ABOVE" },
{ "filterType": "SEXUALLY_EXPLICIT", "confidenceLevel": "MEDIUM_AND_ABOVE" }
]' \
--pi-and-jailbreak-filter-settings-enforcement=enabled \
--pi-and-jailbreak-filter-settings-confidence-level=medium-and-above \
--template-metadata-enforcement-type=INSPECT_AND_BLOCK \
--malicious-uri-filter-settings-enforcement=enabled \
--template-metadata-custom-llm-response-safety-error-code=798 \
--template-metadata-custom-llm-response-safety-error-message="ahoy! model response blocked by content filter :(" \
--template-metadata-custom-prompt-safety-error-code=799 \
--template-metadata-custom-prompt-safety-error-message="ahoy! the request was blocked by ye content filter... so rephrase the prompt and try again!" \
--template-metadata-ignore-partial-invocation-failures \
--template-metadata-log-operations \
--template-metadata-log-sanitize-operations
Créer un modèle de filtre de réponse
Créez un modèle de filtre de réponse pour bloquer le même contenu que le modèle de filtre de requête. La protection DLP est configurée sur la partie réponse pour désidentifier les numéros de sécurité sociale des messages renvoyés au client par l'agent.
# create model armor template (response)
gcloud beta model-armor templates create ${AGW_NAME}-modar-resp-template \
--project=${PROJ_ID} \
--location=${REGION} \
--rai-settings-filters='[
{ "filterType": "HATE_SPEECH", "confidenceLevel": "MEDIUM_AND_ABOVE" },
{ "filterType": "HARASSMENT", "confidenceLevel": "MEDIUM_AND_ABOVE" },
{ "filterType": "SEXUALLY_EXPLICIT", "confidenceLevel": "MEDIUM_AND_ABOVE" }
]' \
--malicious-uri-filter-settings-enforcement=enabled \
--advanced-config-inspect-template=projects/${PROJ_ID}/locations/${REGION}/inspectTemplates/agw-ssn-inspect-template \
--advanced-config-deidentify-template=projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates/agw-ssn-redaction-template \
--template-metadata-enforcement-type=INSPECT_AND_BLOCK \
--template-metadata-custom-llm-response-safety-error-code=798 \
--template-metadata-custom-llm-response-safety-error-message="ahoy! model response blocked by content filter :(" \
--template-metadata-custom-prompt-safety-error-code=799 \
--template-metadata-custom-prompt-safety-error-message="ahoy! the request was blocked by ye content filter... so rephrase the prompt and try again!" \
--template-metadata-ignore-partial-invocation-failures \
--template-metadata-log-operations \
--template-metadata-log-sanitize-operations
Vérifier les modèles Model Armor
# list model armor templates
gcloud model-armor templates list --location=${REGION}
# show request filter template details
gcloud model-armor templates describe ${AGW_NAME}-modar-req-template --location=${REGION}
# show response filter template details
gcloud model-armor templates describe ${AGW_NAME}-modar-resp-template --location=${REGION}
Autorisations IAM
Model Armor effectue des appels d'API pour invoquer le service Sensitive Data Protection (SDP). Accordez à l'identité de service Model Armor les autorisations IAM nécessaires pour utiliser les modèles d'inspection et d'anonymisation de la protection des données de service.
Associer une stratégie IAM pour la protection des données sensibles
# grant dlp (sdp) user role to the model armor service identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-modelarmor.iam.gserviceaccount.com" \
--role="roles/dlp.user"
Vérifier les autorisations IAM
# show iam policy for all dlp (sdp) roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.role:roles/dlp" \
--format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"
La partie sur Model Armor est terminée. Passons à la section Autorisation.
6. Autorisation
Autorisations IAM
Pour inspecter le trafic intégré à l'aide de Model Armor, l'agent de service des extensions de service (DEP) nécessite des liaisons IAM explicites (même pour les ressources d'un même projet) :
roles/modelarmor.calloutUseretroles/serviceusage.serviceUsageConsumer: accordées sur le projet de passerelle pour autoriser les encadrés d'inspection intégrée.roles/modelarmor.user: accordé sur le projet de modèle pour permettre l'accès aux modèles Model Armor et leur évaluation.
Associer une stratégie IAM pour Model Armor
# grant model armor callout user role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/modelarmor.calloutUser"
# grant service usage consumer role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/serviceusage.serviceUsageConsumer"
# grant model armor user role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/modelarmor.user"
Vérifier les autorisations IAM
# show iam policy on project for dep (service extension) service agent
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.members:serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--format="table(bindings.members:label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"
Extension d'autorisation
La configuration de l'extension d'autorisation pour Agent Gateway définit les paramètres d'intégration qui s'appliqueront au trafic de charge utile entrant et sortant. La configuration définit le service de traitement externe (service) qui fait référence à l'API Model Armor régionale et établit un lien vers les modèles de requête et de réponse spécifiques à l'aide du champ de métadonnées model_armor_settings.
Créer une extension d'autorisation
# create authz extension config file (enforced mode)
cat > cfg/${AGW_NAME}-svc-ext-authz-modar.yaml <<EOF
name: ${AGW_NAME}-svc-ext-authz-modar
service: modelarmor.${REGION}.rep.googleapis.com
metadata:
model_armor_settings: '[
{
"request_template_id": "projects/${PROJ_ID}/locations/${REGION}/templates/${AGW_NAME}-modar-req-template",
"response_template_id": "projects/${PROJ_ID}/locations/${REGION}/templates/${AGW_NAME}-modar-resp-template"
}
]'
failOpen: true
timeout: 5s
EOF
Importer une extension d'autorisation
# import authz extension file
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-modar \
--source=cfg/${AGW_NAME}-svc-ext-authz-modar.yaml \
--location=${REGION}
Valider l'extension d'autorisation
# list authz extensions
gcloud service-extensions authz-extensions list --location=${REGION}
# show authz extension details
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-modar \
--location=${REGION}
Règle d'autorisation
Les règles d'autorisation utilisent des profils de règles pour déterminer le type d'évaluation effectuée. Alors que les profils basés sur les requêtes (REQUEST_AUTHZ) évaluent les en-têtes HTTP, cette configuration utilise un profil d'autorisation basé sur le contenu (CONTENT_AUTHZ) pour lier l'extension Model Armor à la passerelle pour une inspection approfondie de la charge utile.
Créer une règle d'autorisation
# create authz policy config file (attach dry-run authz extension)
cat > cfg/${AGW_NAME}-authz-policy-modar.yaml <<EOF
name: ${AGW_NAME}-authz-policy-modar
target:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: CONTENT_AUTHZ
action: CUSTOM
customProvider:
authzExtension:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-modar"
EOF
Importer une règle d'autorisation
# import authz policy config file (enable authz policy)
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-modar \
--source=cfg/${AGW_NAME}-authz-policy-modar.yaml \
--location=${REGION}
Valider la règle d'autorisation
# list authz policies
gcloud beta network-security authz-policies list --location=${REGION}
# show authz policy details
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-modar \
--location=${REGION}
La partie concernant l'autorisation est terminée. Passons à la section Codebase.
7. Codebase
Le code de l'agent et les données de fichier 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.
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_ingress_modar
# copy agent runtime and endpoint definitions to working project dir
cp -r temp_agw_cuj_arun_ingress_modar/codelabs/agw-cuj-arun-ingress-modar/agent-crm ./agent-crm
# remove temporary directory
rm -rf temp_agw_cuj_arun_ingress_modar
Un bucket de stockage pour la préproduction est utilisé par Agent Runtime pour importer, compiler et déployer le code de l'application d'agent empaqueté et ses artefacts de dépendance.
Créer un bucket de stockage pour la préproduction
# create storage bucket
gcloud storage buckets create gs://${STAGING_BUCKET} --location=${REGION}
Vérifier le bucket de stockage
# list storage buckets
gcloud storage buckets list --format="value(storage_url)"
La partie concernant la base de code est terminée. Passons à la section Données client GCS.
Données client
Créez un bucket Cloud Storage pour stocker les données client. L'agent effectue une lecture directe à l'aide de la bibliothèque cliente Google Cloud standard, en appelant le point de terminaison MCP Cloud Storage.
Créer un bucket de stockage pour les données client
# create storage bucket
gcloud storage buckets create gs://${DATA_BUCKET} --location=${REGION}
Vérifier le bucket de stockage
# list storage buckets
gcloud storage buckets list --format="value(storage_url)"
Importer des données clients
# copy local data to bucket
gcloud storage cp -r ./agent-crm/data/* gs://${DATA_BUCKET}/
Valider les données client
# list bucket objects
gcloud storage ls gs://${DATA_BUCKET}/ --long
La partie sur les données client GCS est terminée. Passons à la section sur l'agent ADK.
8. Agent ADK
L'agent ADK agent-crm 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_IDENTITYpour provisionner une identité principale basée sur SPIFFE unique pour l'agent"client_to_agent_config": {"agent_gateway": "${AGW_URI}"}pour rediriger tout le trafic entrant de l'agent vers le chemin d'évaluation et d'application des règles de la passerelle d'agent
L'URL du serveur MCP mTLS pour le serveur MCP Cloud Storage et le nom du bucket de données sont également transmis à l'agent pour appeler l'outil MCP GCS via une connexion sécurisée.
Déployer l'agent
# deploy agent
uv --directory agent-crm 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 customer data" \
--mcp-server-url="${MCP_URL}" \
--data-bucket=${DATA_BUCKET} \
--enable-telemetry \
--enable-agent-identity \
--agent-gateway-ingress=${AGW_URI} \
--allow-token-sharing
Vérifier le déploiement
Récupérer les constantes vitales du déploiement
# fetch agent runtime (reasoning engine) resource 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 \
--project=${PROJ_ID} --location=${REGION} --filter="displayName=${RE_AGENT_NAME}" \
--format="value(attributes.'agentregistry.googleapis.com/system/RuntimeIdentity'.principal)")
echo ${RE_AGENT_IDENTITY}
Vérifier la configuration de la passerelle
# show agent runtime config details (gateway config)
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}'
Autorisations IAM
Associer des stratégies IAM à l'identité de l'agent
# grant mcp tool user role to agent set (all agent runtime agents in project)
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_ID_SET}" \
--role="roles/mcp.toolUser"
# grant storage object viewer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/storage.objectViewer"
# grant aiplatform user role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/aiplatform.user"
# grant cloudtrace agent role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/cloudtrace.agent"
# grant cloud monitoring metric writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/monitoring.metricWriter"
# grant cloud logging log writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/logging.logWriter"
# grant telemetry writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/telemetry.writer"
# grant service usage consumer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/serviceusage.serviceUsageConsumer"
# grant browser role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
--member="${RE_AGENT_IDENTITY}" \
--role="roles/browser"
Vérifier les autorisations IAM
# show agent identity roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.members:${RE_AGENT_IDENTITY}" \
--format="table(bindings.members.sub('^.*locations/', 'principal://agents.[...]/locations/'):label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"
# show agent set roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
--flatten="bindings[].members" \
--filter="bindings.members:${RE_AGENT_ID_SET}" \
--format="table(bindings.members.sub('^.*platformContainer/', 'principalSet://agents.[...]/'):label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"
La partie concernant l'agent ADK est terminée. Passons à la section Test.
9. Test
Envoyer des requêtes depuis la CLI
Tester un prompt sûr
# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
-d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
"input": {
"message": "what are the names of our west customers?",
"user_id": "test-user"
}
}
EOF
Vous devriez obtenir une réponse semblable à celle-ci : "Nos clients de l'Ouest sont Bob Johnson et Alice Brown."
Tester un déclencheur de masquage
# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
-d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
"input": {
"message": "what are ssn's for bob johnson and alice brown?",
"user_id": "test-user"
}
}
EOF
Tester un autre prompt sûr
# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
-d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
"input": {
"message": "what are bob johnson's and alice brown's email addresses?",
"user_id": "test-user"
}
}
EOF
Journaux d'audit
Afficher les journaux de trace
Lorsque la télémétrie est activée, Agent Runtime diffuse des événements structurés représentant les requêtes utilisateur, les paramètres d'outils, les flux d'exécution et les sorties de choix de modèle.
# show agent runtime (reasoning engine) telemetry and trace logs
gcloud logging read \
"logName:\"projects/${PROJ_ID}/logs/aiplatform.googleapis.com%2Freasoning_engine_stdout\" AND labels.managed-by=\"reasoning-engine\"" \
--project=${PROJ_ID} \
--limit=15 \
--format="table(
timestamp.date(format=\"%I:%M:%S %p\", tz=LOCAL):label=TIME,
trace.basename().sub('^(.{8}).*$', '\\1'):label=TRACE_ID,
labels.\"event.name\".scope(-1):label=EVENT,
jsonPayload.content.role:label=ROLE,
jsonPayload.content.parts[0].text:label=TEXT_CONTENT,
jsonPayload.content.parts[0].function_call.name:label=TOOL_CALL
)"
TRACE_ID regroupe la requête de l'utilisateur, les appels d'outils intermédiaires et les décisions du modèle dans une seule chronologie :
TIME TRACE_ID EVENT ROLE TEXT_CONTENT TOOL_CALL
HH:MM:SS PM 3070a1fd gen_ai.choice model Bob Johnson's SSN is 219-45-7895.
Alice Brown's SSN is 219-45-7896.
HH:MM:SS PM 3070a1fd gen_ai.user.message user
HH:MM:SS PM 3070a1fd gen_ai.user.message model read_customer_file
HH:MM:SS PM 3070a1fd gen_ai.user.message user
HH:MM:SS PM 3070a1fd gen_ai.user.message model read_customer_file
HH:MM:SS PM 3070a1fd gen_ai.user.message user
HH:MM:SS PM 3070a1fd gen_ai.user.message model list_customer_files
HH:MM:SS PM 3070a1fd gen_ai.user.message user what are ssn's for bob johnson and alice brown?
HH:MM:SS PM 3070a1fd gen_ai.system.message
HH:MM:SS PM 3070a1fd gen_ai.choice model read_customer_file
Afficher les journaux de nettoyage Model Armor
Ces journaux affichent les menaces et la désinfection en temps réel et bidirectionnelles effectuées par Model Armor lorsque le trafic transite par l'Agent Gateway.
# show model armor logs
gcloud logging read \
"logName:\"projects/${PROJ_ID}/logs/modelarmor.googleapis.com%2Fsanitize_operations\"" \
--project=${PROJ_ID} \
--limit=50 \
--format="table(
timestamp.date(format=\"%I:%M:%S %p\", tz=LOCAL):label=TIME,
jsonPayload.sanitizationResult.sanitizationVerdict:label=VERDICT,
jsonPayload.sanitizationInput.byteItem.byteData.decode(base64).decode(utf-8).sub('\n', ' \\\\\\\\n ').trailoff(123):label=INPUT_DATA
)"
Notez l'entrée de journal pour la requête nettoyée et bloquée.
TIME VERDICT INPUT_DATA
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW Bob Johnson's email address is bob.j@example.com. \n Alice Brown's email address is alice.b...
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW what are bob johnson's and alice brown's email addresses?
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_BLOCK 6��
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW what are ssn's for bob johnson and alice brown?
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW Our west customers are: Bob Johnson and Alice Brown.
HH:MM:SS PM MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW what are the names of our west customers?
La partie "Test" est terminée. Passons à la section Nettoyage.
10. Nettoyage
# remove agent iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/storage.objectViewer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/aiplatform.user"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/cloudtrace.agent"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/monitoring.metricWriter"
# next
# remove more agent and agent set iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/logging.logWriter"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/telemetry.writer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/serviceusage.serviceUsageConsumer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/browser"
# next
# remove rest of iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_ID_SET}" --role="roles/mcp.toolUser"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="serviceAccount:service-${PROJ_NO}@gcp-sa-modelarmor.iam.gserviceaccount.com" --role="roles/dlp.user"
# next
# delete agent runtime (reasoning engine) 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)" \
-H "Content-Type: application/json"
# next
# delete storage
gcloud -q storage rm --recursive gs://${STAGING_BUCKET}
gcloud -q storage rm --recursive gs://${DATA_BUCKET}
# next
# delete authz resources
gcloud -q beta network-security authz-policies delete ${AGW_NAME}-authz-policy-modar --location=${REGION}
gcloud -q beta service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-modar --location=${REGION} --async
# next
# remove dep (service extensions) service agent iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/modelarmor.calloutUser"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/serviceusage.serviceUsageConsumer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
--role="roles/modelarmor.user"
# next
# delete model armor templates
gcloud -q model-armor templates delete ${AGW_NAME}-modar-resp-template --location=${REGION}
gcloud -q model-armor templates delete ${AGW_NAME}-modar-req-template --location=${REGION}
# unset model armor api endpoint override
gcloud config unset api_endpoint_overrides/modelarmor
# next
# delete sdp (dlp) templates
curl -fsS -X DELETE "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates/agw-ssn-redaction-template" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "x-goog-user-project: ${PROJ_ID}"
curl -fsS -X DELETE "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates/agw-ssn-inspect-template" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "x-goog-user-project: ${PROJ_ID}"
# next
# delete agent gateway ingress
gcloud -q network-services agent-gateways delete ${AGW_NAME} --location=${REGION} --async
# end
La partie sur le nettoyage est terminée. Passons à la section Conclusion.
11. Conclusion
Félicitations ! Vous avez déployé Agent Gateway et contrôlé le trafic entrant vers un agent d'IA.

Cosmopup pense que les ateliers de programmation sont super !
Et ensuite ?
- Consultez la documentation Gemini Enterprise Agent Platform pour découvrir les fonctionnalités avancées et les tutoriels.
- Configurer les garde-fous Model Armor sur Agent Gateway pour renforcer la sécurité de l'IA
- Découvrez les Règles de gouvernance sémantique pour appliquer les règles commerciales et la conformité aux requêtes en langage naturel.
N'hésitez pas à nous faire part de vos commentaires, questions ou corrections en utilisant ce formulaire.
Merci !