Ingresso di Agent Gateway in Agent Runtime con Model Armor

1. Introduzione

Questo codelab esplora la governance dell'ingresso di Agent Gateway per gli agenti AI ospitati su Agent Runtime.

Agent Gateway in modalità in entrata (da client ad agente) supporta la gestione delle comunicazioni tra client (utenti finali umani, agenti desktop, IDE di codifica, agenti peer e così via) e agenti ospitati Agent Runtime. Questa modalità viene utilizzata per proteggere gli agenti da attacchi di prompt injection in entrata o da contenuti dannosi inviati dai client. Tutto il traffico in entrata viene elaborato utilizzando le estensioni di autorizzazione e Model Armor per proteggere il punto di ingresso della rete per tutte le interazioni con gli agenti.

Cosa crei

  • Agent Gateway in modalità in entrata (da client ad agente)
  • Estensione dell'autorizzazione Model Armor
  • Agente ADK di Agent Runtime con identità dell'agente
  • Dati dei file di Cloud Storage interrogati dall'agente utilizzando MCP
  • Template Model Armor per il controllo di prompt e risposte degli LLM
  • Modelli Sensitive Data Protection per l'anonimizzazione dei dati

figure1

Fig. 1 Architettura del codelab

Cosa imparerai

  • Come eseguire il deployment di Agent Gateway per filtrare il traffico in entrata verso un agente
  • Come configurare le estensioni di autorizzazione e la delega di Model Armor
  • Come creare ed eseguire il deployment di modelli Model Armor personalizzati
  • Come creare e implementare modelli Sensitive Data Protection personalizzati
  • Come testare e convalidare i criteri di screening LLM

Cosa serve

  • Un progetto cloud Google Cloud con la fatturazione abilitata
  • Autorizzazioni IAM per il provisioning di servizi di rete, set di dati BigQuery e risorse di Agent Platform
  • Una shell compatibile con POSIX (bash o zsh) con Google Cloud CLI (componente gcloud) installata
  • Strumenti a riga di comando: git, curl, jq (processore JSON), Python 3 e uv (gestore pacchetti Python)

2. Concetti

Direzione del traffico e ruoli del gateway

Agent Gateway funge da proxy di rete consapevole dell'agente, ma il suo ruolo operativo cambia a seconda della direzione del traffico:

  • Modalità da agente a ovunque (uscita):funziona come proxy in uscita. Quando un agente chiama strumenti di database esterni, server MCP di terze parti o API, il gateway di uscita gestisce l'individuazione dei servizi, il routing, TLS reciproco (mTLS), l'inserimento dinamico delle credenziali OAuth e il controllo dell'accesso agli endpoint.
  • Modalità da client ad agente (ingresso):funge da gateway di sicurezza frontend. Il suo obiettivo principale è proteggere l'accesso al runtime di esecuzione dell'agente intercettando e sanificando i prompt in linguaggio naturale in entrata prima che raggiungano il codice dell'agente o i modelli di AI.

Percorso in entrata ad Agent Runtime

Le richieste client che hanno come target un agente ospitato su Agent Runtime sono destinate all'endpoint API aiplatform.googleapis.com.

POST https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:query

Questo flusso di comunicazione in entrata all'endpoint API rappresenta il percorso di ingresso client-to-agent.

Per proteggere questo percorso di ingresso gestito da Google, Agent Gateway si integra direttamente con il Google Front End (GFE) a livello di infrastruttura di pubblicazione delle API. Quando viene eseguito il deployment di un agente gestito in Agent Runtime, Google associa in modo nativo la policy di autorizzazione del gateway in entrata alle richieste client in entrata all'edge di rete.

figure2

Fig. 2 Governance dell'ingresso con Agent Gateway in Agent Runtime

Poiché l'ispezione avviene a livello di frontend prima che le richieste entrino in Agent Runtime, questa architettura non introduce overhead di rete aggiuntivo o latenza di hop interna. Lo scaling viene gestito automaticamente dall'infrastruttura frontend, eliminando la necessità di gestire intervalli IP interni, bilanciatori del carico o route DNS personalizzate.

Sanitizzazione delle minacce in linea con Model Armor

La valutazione delle credenziali del chiamante e l'applicazione del controllo dell'accesso IAM (roles/aiplatform.user) vengono gestite in modo nativo dal livello di hosting API aiplatform. Il gateway in entrata stesso non esegue l'autorizzazione dell'identità, ma si concentra sulla sicurezza dei contenuti utilizzando le estensioni di autorizzazione configurate con un profilo CONTENT_AUTHZ. Il gateway funge da punto di applicazione delle norme inline, intercettando i prompt in linguaggio naturale in transito prima che raggiungano il ciclo di ragionamento dell'agente AI o l'LLM sottostante.

Quando un prompt utente in entrata arriva al servizio di frontend, il gateway avvia un callout ext_proc (elaborazione esterna) al servizio di estensione dell'autorizzazione Model Armor regionale, che trasmette in streaming la chiamata al dataplane Model Armor. Model Armor funge da firewall in linguaggio naturale, valutando il testo in base a modelli attivi per rilevare rischi per la sicurezza e la protezione:

  • Prompt injection indiretti e tentativi di jailbreaking
  • URL dannosi, linguaggio tossico o contenuti non sicuri
  • Informazioni che consentono l'identificazione personale (PII) e fuga di dati sensibili

Se il modello include filtri Sensitive Data Protection (SDP), Model Armor effettua una chiamata gRPC aggiuntiva al servizio Cloud SDP. Cloud SDP ispeziona il payload utilizzando il modello specificato, esegue l'anonimizzazione o l'oscuramento richiesti e restituisce il risultato sanitizzato alla catena per essere inoltrato in modo sicuro.

Se viene rilevata una violazione delle norme o una corrispondenza di dati sensibili non modificati, il gateway blocca o modifica il payload all'edge prima di entrare nel runtime. Di conseguenza, l'applicazione dell'agente AI in esecuzione rimane protetta e non elabora mai payload dannosi o non modificati.

Con questo si conclude la parte sui concetti. Passiamo ora alla sezione Configurazione.

3. Configurazione

Ruoli IAM richiesti

Per creare le risorse in questo Codelab sono necessari i seguenti ruoli:

Categoria

Ruolo IAM richiesto (ID)

Descrizione

Gestione delle API

roles/serviceusage.serviceUsageAdmin

Abilita i servizi API Google Cloud

Networking e gateway

roles/networkservices.admin

Provisioning di Agent Gateway

Service Extensions

roles/serviceextensions.admin

Configurare le estensioni di routing

Sicurezza di rete

roles/networksecurity.admin

Deployment dei criteri di autorizzazione

Sensitive Data Protection

roles/dlp.admin

Gestire i modelli di ispezione e anonimizzazione SDP

Model Armor

roles/modelarmor.admin

Creare e gestire modelli di sicurezza

Agent Platform

roles/aiplatform.admin

Esegui il deployment dei carichi di lavoro di Agent Runtime

Cloud Storage

roles/storage.admin

Gestire i bucket di deployment e dei dati dei clienti

Amministrazione IAM

roles/resourcemanager.projectIamAdmin

Associa le autorizzazioni a livello di progetto per l'identità dell'agente

Log e revisione

roles/logging.viewer

Esaminare le tracce e i log di controllo

In alternativa, utilizza un ruolo di base generico come roles/admin o un ruolo legacy come roles/owner.

Accedere al progetto

Questo codelab utilizza un singolo progetto cloud di Google. I passaggi di configurazione utilizzano i comandi della shell Linux e dell'interfaccia a riga di comando gcloud.

Inizia accedendo alla riga di comando del tuo progetto Google Cloud:

Imposta l'ID progetto

gcloud config set project SET_YOUR_PROJECT_ID_HERE

Autentica sessione

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

Imposta le variabili di ambiente della 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

Se esegui un'installazione autogestita di Google Cloud SDK (ovvero al di fuori di Cloud Shell), aggiorna i componenti all'ultima versione.

# update gcloud cli
gcloud components update

Abilitare i servizi 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

Con questo si conclude la parte di configurazione… passiamo ora alla sezione Gateway.

4. Gateway

Esegui il deployment di un Agent Gateway gestito da Google che opera in modalità client-to-agent (CLIENT_TO_AGENT). A differenza dei gateway in uscita che richiedono associazioni al registro degli agenti per instradare le chiamate in uscita, il gateway in entrata si lega direttamente al livello frontend per fungere da punto di applicazione incorporato per i prompt in entrata che hanno come target Agent Runtime.

Mentre le policy di uscita spesso iniziano in modalità DRY_RUN a livello di gateway, la governance dei contenuti in entrata (CONTENT_AUTHZ) viene implementata direttamente in modalità applicata. Il logging granulare di solo controllo o il blocco attivo viene invece controllato a monte nei singoli modelli Model Armor.

Crea gateway

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

Verifica gateway

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

Con questo si conclude la parte relativa al gateway. Passiamo ora alla sezione Model Armor.

5. Model Armor

Modelli SDP

Crea un modello di ispezione e anonimizzazione di Sensitive Data Protection (SDP) da utilizzare nel modello di risposta di Model Armor. Questa configurazione contrassegna i numeri di previdenza sociale statunitensi (SSN) per la redazione.

Crea modello di ispezione

Il modello di ispezione identifica le informazioni sensibili (US_SOCIAL_SECURITY_NUMBER) nei dati.

# 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

Crea template di anonimizzazione

Il modello di anonimizzazione specifica la trasformazione da applicare ai numeri di previdenza sociale trovati dal modello di ispezione. In questo caso, la trasformazione consiste nel sostituire l'SSN con il tipo di informazioni.

# 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

Verifica dei modelli 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

Modelli Model Armor

L'endpoint predefinito per l'API Model Armor è globale (modelarmor.googleapis.com). Tuttavia, le risorse Model Armor per i modelli e i motori di valutazione sono localizzate in regioni geografiche specifiche. Il proxy endpoint regionale Google Cloud (REP) o l'endpoint API regionale per Model Armor è https://modelarmor.${LOCATION}.rep.googleapis.com/.

Per impostazione predefinita, quando esegui gcloud model-armor ..., la CLI tenta di inviare richieste API all'endpoint globale standard (https://modelarmor.googleapis.com/). Un override dell'endpoint API viene utilizzato per reindirizzare tutte le richieste HTTP SDK/CLI per Model Armor direttamente al livello API rep.googleapis.com regionale in cui questi modelli vincolati alla località vengono effettivamente creati, archiviati e interrogati.

Imposta l'override dell'API

# set api endpoint override per location
gcloud config set api_endpoint_overrides/modelarmor "https://modelarmor.${REGION}.rep.googleapis.com/"

Verifica l'override dell'API

# view api overrides on active gcloud config
gcloud config list api_endpoint_overrides/

Crea un modello di filtro delle richieste

Crea un modello di filtro delle richieste per bloccare incitamento all'odio, molestie, contenuti sessualmente espliciti e attacchi di iniezione di URI. Il logging verrà attivato per acquisire informazioni dettagliate sugli eventi relativi all'applicazione dei criteri. Sono configurati anche codici e messaggi di errore personalizzati per quando una richiesta viene bloccata.

# 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

Crea un modello di filtro delle risposte

Crea un modello di filtro delle risposte per bloccare gli stessi contenuti del modello di filtro delle richieste. La prevenzione della perdita di dati è configurata nella parte della risposta per rimuovere l'identificazione dei numeri di previdenza sociale per i messaggi restituiti al client dall'agente.

# 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

Verifica i modelli 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}

Autorizzazioni IAM

Model Armor effettua chiamate API per richiamare il servizio Sensitive Data Protection (SDP). Concedi all'identità di servizio Model Armor le autorizzazioni IAM per utilizzare i modelli di ispezione e anonimizzazione SDP.

Associa il criterio IAM per Sensitive Data Protection

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

Verifica le autorizzazioni 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)"

Con questo si conclude la parte relativa a Model Armor. Passiamo ora alla sezione Autorizzazione.

6. Autorizzazione

Autorizzazioni IAM

Per ispezionare il traffico inline utilizzando Model Armor, il service agent Service Extensions (DEP) richiede binding IAM espliciti (anche tra risorse all'interno dello stesso progetto):

  • roles/modelarmor.calloutUser e roles/serviceusage.serviceUsageConsumer: concessi nel progetto gateway per consentire i callout di ispezione in linea.
  • roles/modelarmor.user: concesso al progetto modello per consentire l'accesso e la valutazione dei modelli Model Armor.

Associa il criterio IAM per 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"

Verifica le autorizzazioni 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)"

Estensione autorizzazione

La configurazione dell'estensione di autorizzazione per Agent Gateway definisce le impostazioni di integrazione che verranno applicate al traffico di payload in entrata e in uscita. La configurazione definisce il servizio di elaborazione esterno (service) che fa riferimento all'API Model Armor regionale e ai modelli di richiesta e risposta specifici utilizzando il campo dei metadati model_armor_settings.

Crea un'estensione di autorizzazione

# 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

Importa estensione di autorizzazione

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

Verifica l'estensione di autorizzazione

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

Norme relative alle autorizzazioni

I criteri di autorizzazione utilizzano i profili dei criteri per determinare il tipo di valutazione eseguita. Mentre i profili basati sulle richieste (REQUEST_AUTHZ) valutano le intestazioni HTTP, questa configurazione utilizza un profilo di autorizzazione basato sui contenuti (CONTENT_AUTHZ) per associare l'estensione Model Armor al gateway per l'ispezione approfondita del payload.

Crea policy di autorizzazione

# 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

Importa policy di autorizzazione

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

Verifica la policy di autorizzazione

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

Con questo si conclude la parte relativa all'autorizzazione. Passiamo ora alla sezione Codebase.

7. Codebase

Il codice dell'agente e i dati dei file utilizzati per questo codelab vengono gestiti in un repository GitHub di Google Cloud remoto. I seguenti passaggi cloneranno il repository localmente, copieranno i file necessari nella struttura della directory di lavoro corrente e poi puliranno i file temporanei.

Recuperare artefatti remoti

# 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 di archiviazione per lo staging viene utilizzato da Agent Runtime per caricare, compilare e implementare il codice dell'applicazione agente pacchettizzata e i relativi artefatti di dipendenza.

Crea un bucket di archiviazione per lo staging

# create storage bucket
gcloud storage buckets create gs://${STAGING_BUCKET} --location=${REGION}

Verifica il bucket di archiviazione

# list storage buckets
gcloud storage buckets list --format="value(storage_url)"

Con questo si conclude la parte relativa al codebase. Passiamo ora alla sezione Dati dei clienti GCS.

Dati cliente

Crea un bucket Cloud Storage per archiviare i dati dei clienti. L'agente leggerà direttamente utilizzando la libreria client standard di Google Cloud che chiama l'endpoint MCP di Cloud Storage.

Crea un bucket di archiviazione per i dati dei clienti

# create storage bucket
gcloud storage buckets create gs://${DATA_BUCKET} --location=${REGION}

Verifica il bucket di archiviazione

# list storage buckets
gcloud storage buckets list --format="value(storage_url)"

Carica dati clienti

# copy local data to bucket
gcloud storage cp -r ./agent-crm/data/* gs://${DATA_BUCKET}/

Verificare i dati dei clienti

# list bucket objects
gcloud storage ls gs://${DATA_BUCKET}/ --long

Con questo si conclude la sezione relativa ai dati dei clienti di GCS. Passiamo ora alla sezione Agente ADK.

8. Agente ADK

L'agente agent-crm ADK di cui è stato eseguito il deployment in Agent Runtime è configurato con le seguenti impostazioni nello script di deployment per l'integrazione con Agent Platform:

  • "identity_type": types.IdentityType.AGENT_IDENTITY per eseguire il provisioning di un'identità principale basata su SPIFFE univoca per l'agente
  • "client_to_agent_config": {"agent_gateway": "${AGW_URI}"} per indirizzare tutto il traffico in entrata per l'agente al percorso di valutazione e applicazione delle norme dell'Agent Gateway

All'agente viene passato anche l'URL del server MCP mTLS per il server MCP Cloud Storage e il nome del bucket di dati per richiamare lo strumento MCP GCS tramite una connessione sicura.

Esegui il deployment dell'agente

# 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

Verifica il deployment

Recupera i parametri vitali del deployment

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

Verifica la configurazione del gateway

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

Autorizzazioni IAM

Associa le policy IAM per l'identità dell'agente

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

Verifica le autorizzazioni 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)"

Con questo si conclude la parte relativa all'agente ADK. Passiamo ora alla sezione Test.

9. Test

Invia query dall'interfaccia a riga di comando

Testare un prompt sicuro

# 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

Dovresti visualizzare una risposta simile a questa… "I nostri clienti dell'ovest sono: Bob Johnson e Alice Brown".

Testare un trigger di oscuramento

# 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

Testare un altro prompt sicuro

# 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

Audit log

Visualizza i log di traccia

Quando la telemetria è abilitata, Agent Runtime trasmette eventi strutturati che rappresentano query utente, parametri degli strumenti, flussi di esecuzione e output di scelta del modello.

# 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 raggruppa la query dell'utente, le chiamate intermedie agli strumenti e le decisioni del modello in un'unica cronologia:

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

Visualizzare i log di sanitizzazione di Model Armor

Questi log mostrano la minaccia e la sanificazione inline bidirezionale in tempo reale eseguite da Model Armor mentre il traffico scorre attraverso 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
  )"

Nota la voce di log per la richiesta sanificata e bloccata.

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?

Con questo si conclude la parte relativa al test. Passiamo ora alla sezione Pulizia.

10. Esegui la pulizia

# 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

Con questo si conclude la parte di pulizia. Passiamo ora alla sezione Conclusione.

11. Conclusione

Complimenti! Hai eseguito correttamente il deployment di Agent Gateway e regolato il traffico in entrata verso un agente AI.

cosmopup

Cosmopup pensa che i codelab siano fantastici.

Quali sono i passaggi successivi?

Non esitare a inviare commenti, domande o correzioni utilizzando questo modulo di feedback.

Grazie.