Gemini Enterprise con uscita di Agent Gateway al server MCP personalizzato privato utilizzando Agent Registry

1. Introduzione

Questo codelab esplora la connettività di uscita privata e controllata per Gemini Enterprise utilizzando Agent Gateway in modalità da agente a ovunque (uscita). Configurerai un'app Gemini Enterprise per richiamare in modo sicuro un server Model Context Protocol (MCP) personalizzato ospitato su Cloud Run instradando il traffico tramite Agent Gateway utilizzando le interfacce Private Service Connect (PSC) per connettersi a un endpoint PSC per le API di Google in una rete VPC.

Negli ambienti aziendali, la concessione dell'accesso diretto alla rete agli agenti autonomi comporta il rischio di esfiltrazione dei dati e di esecuzione di strumenti non verificati. Agent Gateway fornisce un punto di applicazione zero-trust centralizzato a livello di piattaforma che ispeziona dinamicamente i payload degli strumenti MCP HTTP trasmissibili in streaming. Le richieste in uscita vengono autenticate con un'identità dell'agente verificabile a livello crittografico e autorizzate tramite Identity-Aware Proxy (IAP) utilizzando le Unified Access Policies (UAP) di IAM con regole Common Expression Language (CEL). Ciò consente un controllo dell'accesso granulare su metodi e strumenti MCP specifici senza esporre i workload di backend alla rete internet pubblica.

Cosa crei

  • Agent Gateway in modalità di uscita (da agente a ovunque) con verifica dell'endpoint di Agent Registry
  • Servizio Cloud Run che ospita un server MCP HTTP privato in streaming (--ingress=internal) registrato con le specifiche dello strumento in Agent Registry
  • Estensione dell'autorizzazione Identity-Aware Proxy (IAP) per Agent Gateway
  • Policy di accesso unificate (UAP) IAM con condizioni CEL per l'autorizzazione dello strumento MCP
  • App Gemini Enterprise associata ad Agent Gateway e connessa a un datastore del server MCP personalizzato importato da Agent Registry
  • Risorse di rete VPC, zona DNS di Cloud DNS ed endpoint PSC per le API di Google
  • Collegamento di rete PSC per l'uscita VPC privata di Agent Gateway
  • Regole dei criteri Cloud Next Generation Firewall (NGFW) per proteggere il traffico VPC

figure1

Fig. 1 Architettura del codelab

Cosa imparerai

  • Come eseguire il deployment di un server MCP HTTP privato trasmissibile dall'origine su Cloud Run e registrare il relativo endpoint e lo schema dello strumento in Agent Registry
  • Come configurare Agent Gateway con voci di registro conformi e instradare le chiamate agli strumenti dell'app Gemini Enterprise tramite il gateway
  • Come stabilire l'uscita VPC privata utilizzando interfacce e collegamenti di rete PSC
  • Come delegare l'autorizzazione di Agent Gateway a Identity-Aware Proxy (IAP)
  • Come creare e associare policy di accesso unificato (UAP) IAM utilizzando gli attributi CEL destination.agent_registry.* e destination.is_registered per limitare l'esecuzione dello strumento MCP
  • Come convalidare l'applicazione dei criteri e il traffico in uscita di rete utilizzando Cloud Logging

Cosa serve

  • Un progetto cloud Google Cloud con la fatturazione abilitata
  • Una licenza Gemini Enterprise attiva o una prova di 30 giorni
  • Autorizzazioni IAM per il provisioning di servizi di rete, Gemini Enterprise e risorse Agent Platform
  • Una shell compatibile con POSIX (bash o zsh) con Google Cloud CLI (gcloud), curl e jq installati

Con questo si conclude la parte introduttiva. Passiamo ora alla sezione Concetti.

2. Concetti

Sequenza di deployment

Questo codelab esegue prima il deployment dell'infrastruttura in modo che i percorsi di rete privati e i controlli di governance siano operativi prima di registrare e connettere gli strumenti MCP con Gemini Enterprise:

  1. Infrastruttura di rete:esegui il provisioning di subnet VPC, un endpoint PSC, un collegamento di rete PSC, regole di policy Cloud NGFW e zone Cloud DNS private.
  2. Agent Gateway:esegui il deployment di Agent Gateway in modalità di uscita con l'integrazione di Agent Registry (registries) e l'uscita VPC privata (networkAttachment).
  3. Policy di autorizzazione:configura l'estensione di autorizzazione IAP, la policy di autorizzazione gateway e la policy di accesso unificato (UAP) IAM utilizzando le condizioni destination.is_registered e destination.agent_registry.* CEL.
  4. Esegui il deployment e registra il server MCP: esegui il deployment del server MCP math dall'origine a Cloud Run (--ingress=internal) e registra le specifiche del servizio e dello strumento (add e subtract) in Agent Registry.
  5. App Gemini Enterprise:crea l'app Gemini Enterprise (Engine), configura le impostazioni di identità e osservabilità e associa l'uscita in uscita ad Agent Gateway (agentGatewaySetting).
  6. Importa connettore dati MCP personalizzato:crea e attiva il connettore dati REGISTRY_MCP (:setUpDataConnector) per collegare il datastore di backend del server MCP registrato all'app Gemini Enterprise.
  7. Convalida:testa le esecuzioni degli strumenti consentite e negate nella chat e verifica l'applicazione delle norme nei log di Agent Gateway, DNS, firewall e Cloud Run.

Egress di Gemini Enterprise

Gemini Enterprise indirizza le richieste di strumenti del server MCP personalizzato ad Agent Gateway quando sono configurati sia agentGatewaySetting su Engine sia use_agent_gateway_egress: true su DataConnector.

figure2

Fig. 2 Architettura di uscita di Gemini Enterprise

L'app Gemini Enterprise organizza il routing degli strumenti in quattro aree chiave:

  1. Widget (default_search_widget_config):
    • Fornisce l'interfaccia del client web. Il widget riceve i prompt dall'utente e avvia le sessioni di chat con il motore sottostante.
  2. Assistente di base (assistants/default_assistant/agents/default/core_assistant):
    • L'agente di ragionamento conversazionale principale all'interno del motore. Quando valuta una query utente, l'assistente principale determina se è necessario un calcolo aritmetico, esamina gli strumenti disponibili e delega l'esecuzione al sottoagente Agent Gateway sintetizzato.
  3. Data Store e Connettore dati:
    • DataStore: eseguito il provisioning all'interno di un Collection dedicato quando viene eseguito :setUpDataConnector, collega (dataStoreIds) gli schemi dello strumento Registro degli agenti importati (add, subtract), i tipi di argomenti e le istruzioni dell'agente a Gemini Enterprise Engine.
    • DataConnector: gestisce la connessione dell'azione REGISTRY_MCP (createBapConnection: true) al server MCP remoto (instance_uri), risolve la risorsa del server MCP di Agent Registry (registry_mcp_server_name) e abilita l'uscita di Agent Gateway (use_agent_gateway_egress: true).
  4. Agent Identity, Agent Registry e Agent Gateway:
    • Quando il connettore dati invia la chiamata allo strumento in uscita, indirizza il traffico al gateway specificato in agentGatewaySetting. Il Centro Assistente conia un token di identità SPIFFE che ne attesta l'identità: principal://agents.global.org-.../agents/default/core_assistant.
    • Agent Gateway si integra con Agent Registry utilizzando il campo registries per risolvere dinamicamente gli endpoint di destinazione e gli schemi degli strumenti registrati. Compila gli attributi destination.is_registered e destination.agent_registry.* e li trasmette a IAP v2 per la valutazione in base alle regole CEL di IAM Unified Access Policy (UAP) prima di consentire il transito nella rete VPC.

Connettività VPC gateway

Agent Gateway consente la connettività di rete VPC privata utilizzando due campi YAML:

  • networkConfig.egress.networkAttachment: indirizza il traffico IP privato in modo che venga instradato attraverso il collegamento di rete PSC nella rete VPC.
  • dnsPeeringConfig.domains: esegue il peering della risoluzione DNS con la zona DNS di Cloud DNS della rete VPC in modo che i nomi host di destinazione (*.run.app) vengano risolti nell'indirizzo IP dell'endpoint PSC privato definito nella rete VPC.

Limitazioni e requisiti

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

3. Configurazione

Ruoli IAM richiesti

Per completare il codelab sono necessari i seguenti ruoli:

Dominio

Ruoli IAM richiesti

Progetto e IAM

roles/orgpolicy.policyAdmin
roles/resourcemanager.projectIamAdmin
roles/iam.accessPolicyAdmin
roles/serviceusage.serviceUsageAdmin
roles/iam.serviceAccountUser

Networking e gateway

roles/networkservices.admin
roles/networksecurity.admin
roles/serviceextensions.admin
roles/compute.networkAdmin
roles/dns.admin

Gemini Enterprise e Registry

roles/discoveryengine.admin
roles/agentregistry.admin (o roles/apphub.admin)

Carichi di lavoro e build

roles/run.admin
roles/cloudbuild.builds.editor
roles/artifactregistry.writer
roles/storage.admin

Osservabilità

roles/logging.viewer
roles/logging.logWriter

In alternativa, utilizza un ruolo di base generico come roles/owner combinato con roles/orgpolicy.policyAdmin (dato che roles/owner da solo non può modificare i criteri dell'organizzazione).

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

Autenticare la 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 for agent platform (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-ata"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export UAP_POLICY_NAME="uap-policy-${SLUG}"
export UAP_BINDING_NAME="uap-binding-${SLUG}"
export MCP_NAME="math-wizard"
export MCP_URL="https://${MCP_NAME}-${PROJ_NO}.${REGION}.run.app/mcp"

echo ${AGW_NAME}
echo ${AGW_URI}
echo ${UAP_POLICY_NAME}
echo ${UAP_BINDING_NAME}
echo ${MCP_NAME}
echo ${MCP_URL}
# create resource vars for gemini enterprise (automatic)
export GE_APP_DISPLAY_NAME="Codelab app"
export GE_APP_ORG_NAME="${SLUG}, Inc."
export GE_LOCATION="global"
export GE_APP_NAME="app-${SLUG}-${GE_LOCATION}"
export GE_APP_INIT="${GE_APP_NAME}_$(date +%s)"

echo ${GE_APP_DISPLAY_NAME}
echo ${GE_APP_ORG_NAME}
echo ${GE_LOCATION}
echo ${GE_APP_NAME}
echo ${GE_APP_INIT}

Impostare i domini di attendibilità dell'identità dell'agente

L'istruzione if-then-else verifica se il progetto appartiene a un'organizzazione per impostare il dominio attendibile corretto per le identità dell'agente principale.

# set var for trust domain
if [[ -n "${ORG_ID}" ]]; then
  export TRUST_DOMAIN="agents.global.org-${ORG_ID}.system.id.goog"
else
  export TRUST_DOMAIN="agents.global.proj-${PROJ_NO}.system.id.goog"
fi

echo "trust domain: ${TRUST_DOMAIN}"

Imposta il progetto di fatturazione e quota

# set cli quota project
gcloud config set billing/quota_project ${PROJ_ID}
# set api quota project
gcloud auth application-default set-quota-project ${PROJ_ID}

Crea la directory locale per i file di configurazione

# create config folder
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 (part 1)
gcloud services enable \
  agentregistry.googleapis.com \
  agentidentity.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 \
  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 (part 2)
gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  discoveryengine.googleapis.com \
  dns.googleapis.com \
  orgpolicy.googleapis.com \
  run.googleapis.com \
  saasservicemgmt.googleapis.com \
  securitycenter.googleapis.com \
  storage.googleapis.com \
  telemetry.googleapis.com \
  texttospeech.googleapis.com

Criteri dell'organizzazione

I vincoli dei criteri dell'organizzazione gestiti di Google Cloud predefiniti limitano le funzionalità utilizzate in questo codelab:

Ignora eventuali limitazioni delle policy dell'organizzazione ereditate a livello di progetto impostando esplicitamente enforce: false.

Disattiva vincolo MCP personalizzato

# disable data connector constraint (allow custom mcp servers)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.disableCustomMcpServerConnector
spec:
  rules:
  - enforce: false
EOF
# verify org policy constraint on project
gcloud org-policies describe discoveryengine.managed.disableCustomMcpServerConnector \
  --project=${PROJ_ID} --effective

Disattiva il vincolo della policy di accesso

# disable iam v3 constraint (allow v3 access policies)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/iam.managed.disableAccessPolicyBinding
spec:
  rules:
  - enforce: false
EOF
# verify org policy constraint on project
gcloud org-policies describe iam.managed.disableAccessPolicyBinding \
  --project=${PROJ_ID} --effective

Controllare e disattivare i vincoli del connettore di dati condizionali

Per impostazione predefinita, discoveryengine.managed.allowedEgressFqdns e discoveryengine.managed.allowedDataSources bloccano la creazione del connettore solo se il progetto si trova all'interno di un perimetro dei Controlli di servizio VPC (VPC SC) o se un amministratore dell'organizzazione ha aggiunto il progetto a enforcedProjects.

Innanzitutto, esamina le norme effettive del tuo progetto:

# check effective egress fqdn constraint on project
gcloud org-policies describe discoveryengine.managed.allowedEgressFqdns \
  --project=${PROJ_ID} --effective
# check effective data source constraint on project
gcloud org-policies describe discoveryengine.managed.allowedDataSources \
  --project=${PROJ_ID} --effective

~~IF~~ questi vincoli vengono applicati, per assicurarti che non blocchino la configurazione del connettore custom_mcp in un'organizzazione con VPC SC o con limitazioni dei criteri, imposta enforce: false su entrambi i criteri per il tuo progetto:

# disable egress fqdn constraint on project
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.allowedEgressFqdns
spec:
  rules:
  - enforce: false
EOF
# disable allowed data sources constraint on project
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/discoveryengine.managed.allowedDataSources
spec:
  rules:
  - enforce: false
EOF
# verify both constraints are disabled on project
gcloud org-policies describe discoveryengine.managed.allowedEgressFqdns \
  --project=${PROJ_ID} --effective

gcloud org-policies describe discoveryengine.managed.allowedDataSources \
  --project=${PROJ_ID} --effective

Autorizzazioni IAM

Concedi i ruoli IAM richiesti al tuo account utente e al service account predefinito di Compute Engine utilizzato da Cloud Build:

  • Account utente (${USER_IDENTITY}):
    • Richiede le autorizzazioni per eseguire il deployment e richiamare i servizi Cloud Run (roles/run.admin, roles/run.invoker, roles/iam.serviceAccountUser), creare immagini container (roles/cloudbuild.builds.editor), gestire Gemini Enterprise (roles/discoveryengine.admin) e creare Unified Access Policies (roles/iam.accessPolicyAdmin).
  • Service account predefinito Compute Engine(${PROJ_NO}-compute@developer.gserviceaccount.com):
    • Utilizzato da Cloud Build per organizzare il codice sorgente in Cloud Storage (roles/storage.admin), eseguire il push delle immagini su Artifact Registry (roles/artifactregistry.writer) e scrivere i log di build (roles/logging.logWriter).

Esegui questi comandi per assegnare i binding dei ruoli:

# grant roles to user account
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/run.admin"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/iam.serviceAccountUser"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/run.invoker"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/discoveryengine.admin"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/iam.accessPolicyAdmin"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="user:${USER_IDENTITY}" \
  --role="roles/cloudbuild.builds.editor"
# grant roles to default compute (cloud build) service account
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
  --role="roles/storage.admin"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
  --role="roles/artifactregistry.writer"

gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:${PROJ_NO}-compute@developer.gserviceaccount.com" \
  --role="roles/logging.logWriter"

Verifica le autorizzazioni IAM

Controlla i sei (6) binding dei ruoli nell'account utente.

# show iam policy on project for user account
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:${USER_IDENTITY}" \
  --format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"

Controlla i tre (3) binding dei ruoli nel service account Compute predefinito.

# show iam policy on project for default compute service account
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:${PROJ_NO}-compute@developer.gserviceaccount.com" \
  --format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"

Verifica delle associazioni dell'agente di servizio (misura precauzionale)

In un nuovo progetto, Google Cloud esegue automaticamente il provisioning dell'agente di servizio Agent Gateway e gli concede roles/agentgateway.serviceAgent quando networkservices.googleapis.com viene abilitato per la prima volta. Se riutilizzi un progetto esistente in cui la pulizia precedente potrebbe aver rimosso le associazioni del service agent predefinite, esegui i seguenti comandi come fail-safe per assicurarti che l'identità e l'associazione del ruolo siano intatte:

# ensure network services service account has been created
gcloud beta services identity create \
  --service=networkservices.googleapis.com \
  --project="${PROJ_ID}"

# ensure network services service account has service agent roles applied
gcloud projects add-iam-policy-binding "${PROJ_ID}" \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-agentgateway.iam.gserviceaccount.com" \
  --role="roles/agentgateway.serviceAgent"

Con questo si conclude la parte di configurazione. Passiamo ora alla sezione Rete.

4. Rete

In questa sezione, eseguirai il deployment di una rete VPC utilizzando la modalità personalizzata con una subnet /28 dedicata (192.168.10.0/28) che supporta il collegamento di rete PSC per l'uscita della rete Agent Gateway nella rete VPC.

L'endpoint PSC per le API di Google viene implementato utilizzando un singolo /32indirizzo IPv4 interno globale (172.16.20.20) per supportare l'accesso interno privato alle API e ai servizi Google. In questo codelab, Agent Gateway ha come target Cloud Run utilizzando l'endpoint PSC risolvendo il dominio run.app. tramite il peering Cloud DNS.

Crea reti

Crea una rete VPC globale.

# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom

Crea subnet per il collegamento di rete PSC di Agent Gateway:

# create subnet for agent gateway psc na
gcloud compute networks subnets create subnet-${REGION}-agw \
  --network=vnet-${SLUG} \
  --range=192.168.10.0/28 \
  --region=${REGION} \
  --enable-private-ip-google-access

Crea regole firewall

Crea una policy del firewall per consentire tutto il traffico in uscita con il logging abilitato. Verrà utilizzato per monitorare il traffico in uscita da Agent Gateway alla rete VPC. Cloud NGFW supporta i livelli Essentials e Standard per la sicurezza di rete e il monitoraggio del traffico.

# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG} --global
# create fw policy rule
gcloud compute network-firewall-policies rules create 1001 \
  --description="allow all out and log" \
  --firewall-policy=fw-policy-${SLUG} \
  --global-firewall-policy \
  --action=allow \
  --direction=EGRESS \
  --layer4-configs=all \
  --dest-ip-ranges=0.0.0.0/0 \
  --enable-logging
# bind fw policy to network
gcloud compute network-firewall-policies associations create \
  --name=fw-policy-bind-${SLUG} \
  --firewall-policy=fw-policy-${SLUG} \
  --network=vnet-${SLUG} \
  --global-firewall-policy

Crea collegamento di rete PSC

Crea un collegamento di rete Private Service Connect (PSC) configurato per accettare automaticamente le connessioni da Agent Gateway. Il collegamento di rete stabilisce il lato della connessione della rete VPC consumer per il collegamento sicuro con il lato producer di Agent Gateway per il traffico in uscita. Per ulteriori informazioni sui requisiti delle subnet e sulle specifiche dell'intervallo IP, consulta Configurare la connettività VPC.

# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
  --region=${REGION} \
  --subnets=subnet-${REGION}-agw \
  --connection-preference=ACCEPT_AUTOMATIC

Verifica il collegamento di rete PSC

# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}

Recupera l'URI della risorsa del collegamento di rete PSC e memorizzalo nella variabile di ambiente PSC_NA_URI. Questo URI verrà utilizzato nella configurazione di Agent Gateway (networkConfig.egress.networkAttachment) per eseguire il provisioning dell'interfaccia PSC per l'uscita di rete nella rete VPC:

# fetch psc network attachment uri
export PSC_NA_URI=$(gcloud compute network-attachments describe psc-na-${REGION}-agw \
  --region=${REGION} \
  --format="value(selfLink.scope(v1))")
echo ${PSC_NA_URI}

Crea endpoint PSC

Un endpoint Private Service Connect (PSC) per le API di Google viene utilizzato da Agent Gateway per stabilire la connettività privata al server MCP di Cloud Run tramite un percorso di rete interno senza esporre il traffico a internet pubblico. Le chiamate agli strumenti in uscita da Agent Gateway nella rete VPC risolveranno l'URL del servizio Cloud Run di destinazione (*.run.app) in questo indirizzo IP dell'endpoint privato.

Prenota un indirizzo IPv4 interno globale per l'endpoint PSC. L'indirizzo IP scelto deve essere un indirizzo /32 che non si sovrapponga a subnet esistenti nella tua rete VPC:

# set env var for psc ep ip address
export PSC_EP_IP="172.16.20.20"
echo ${PSC_EP_IP}
# reserve internal global ipv4 address
gcloud compute addresses create ip-psc2gapis \
  --global \
  --purpose=PRIVATE_SERVICE_CONNECT \
  --addresses=${PSC_EP_IP} \
  --network=vnet-${SLUG}

Crea un endpoint PSC per le API di Google utilizzando il bundle all-apis, che include Cloud Run (run.app).

# create psc endpoint for google apis
gcloud compute forwarding-rules create psc2gapis \
  --global \
  --network=vnet-${SLUG} \
  --address=ip-psc2gapis \
  --target-google-apis-bundle=all-apis

Verifica l'endpoint PSC

# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global

Crea zona DNS e record

Cloud DNS viene utilizzato per consentire ad Agent Gateway di comunicare privatamente con il server MCP ospitato su Cloud Run. Quando Agent Gateway valuta le richieste di strumenti in uscita che hanno come target Cloud Run, utilizza il peering DNS (dnsPeeringConfig.domains) per risolvere le query DNS per *.run.app utilizzando la zona DNS privato di Cloud associata alla tua rete VPC. Il record DNS privato restituisce la query con l'indirizzo IP dell'endpoint PSC interno (172.16.20.20), consentendo l'instradamento delle richieste dello strumento MCP tramite un percorso di rete privato.

Crea una zona gestita privata di Cloud DNS per il dominio run.app.:

# create private dns zone
gcloud dns managed-zones create priv-zone-run \
  --description="private zone for run.app" \
  --dns-name="run.app." \
  --visibility=private \
  --networks=vnet-${SLUG}

Crea un record DNS jolly A per *.run.app. che punta all'indirizzo IP dell'endpoint PSC:

# create dns record
gcloud dns record-sets create "*.run.app." \
  --zone=priv-zone-run \
  --type=A \
  --ttl=300 \
  --rrdatas=${PSC_EP_IP}

Crea una policy Cloud DNS per attivare il logging delle query DNS. Il logging DNS acquisisce le richieste di risoluzione del dominio provenienti da Agent Gateway all'interno della rete VPC, fornendo auditabilità e consentendoti di verificare che le richieste dello strumento *.run.app vengano risolte correttamente nell'endpoint PSC interno:

# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
  --description="dns logging for vnet-${SLUG}" \
  --networks=vnet-${SLUG} \
  --enable-logging

Con questo si conclude la parte relativa alla rete. Passiamo ora alla sezione Agent Gateway.

5. Agent Gateway

Agent Gateway specifica registries per le istanze di Agent Registry insieme ai campi networkConfig che configurano il collegamento di rete PSC e le impostazioni di peering DNS per la connettività VPC privata:

  • registries: associa il gateway a un massimo di due istanze di Agent Registry: una regionale (../locations/${REGION}) e una globale (../locations/global). In questo modo, Agent Gateway viene integrato con Agent Registry per risolvere sia i deployment regionali (come i server MCP Cloud Run in ${REGION}) sia le risorse globali (come gli agenti Gemini Enterprise e gli endpoint globali) per l'applicazione delle norme IAP v2 granulari. Le voci regionali hanno la precedenza su quelle globali durante la risoluzione degli URL di destinazione.
  • networkAttachment: punta al collegamento di rete PSC (psc-na-${REGION}-agw), collegando Agent Gateway alla tua rete VPC per l'uscita privata.
  • dnsPeeringConfig.domains: configura run.app. in modo che le query DNS provenienti da Agent Gateway per i servizi Cloud Run utilizzino il peering DNS per risolvere i nomi host nell'indirizzo IP dell'endpoint PSC delle API private di Google (172.16.20.20) configurato nella zona privata Cloud DNS.

Esegui il deployment di Agent Gateway

Crea e importa il file di configurazione di Agent Gateway.

# create agent gateway config file
cat > cfg/${AGW_NAME}-networkConfig.yaml << EOF
name: ${AGW_NAME}
protocols:
  - MCP
googleManaged:
  governedAccessPath: AGENT_TO_ANYWHERE
registries:
  - "//agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}"
networkConfig:
  egress:
    networkAttachment: ${PSC_NA_URI}
  dnsPeeringConfig:
    domains:
      - run.app.
    targetProject: ${PROJ_ID}
    targetNetwork: projects/${PROJ_ID}/global/networks/vnet-${SLUG}
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
  --source="cfg/${AGW_NAME}-networkConfig.yaml" \
  --location=${REGION}

Verifica il deployment di Agent Gateway

Conferma la configurazione di Agent Registry e della rete:

# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
  --location=${REGION} \
  --format="yaml(registries,networkConfig)"

Output previsto:

networkConfig:
  dnsPeeringConfig:
    domains:
    - run.app.
    targetNetwork: projects/${PROJ_ID}/global/networks/vnet-${SLUG}
    targetProject: ${PROJ_ID}
  egress:
    networkAttachment: projects/${PROJ_ID}/regions/${REGION}/networkAttachments/psc-na-${REGION}-agw
registries:
- //agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}

Verifica che l'output mostri i dettagli di configurazione richiesti:

  • registries: elenca l'URI del registro degli agenti regionale (${REGION}) associato al gateway.
  • egress.networkAttachment: specifica l'URI del collegamento di rete PSC per l'uscita VPC.
  • dnsPeeringConfig.domains: contiene run.app. che punta a targetNetwork per la risoluzione del dominio privato.

Ispeziona il collegamento di rete PSC per confermare la connessione del gateway:

# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
  --region=${REGION} \
  --format="yaml(connectionEndpoints)"

Controlla che esista un endpoint di connessione accettato:

connectionEndpoints:
- ipAddress: 192.168.10.2
  projectIdOrNum: '<AGW_TENANT_PROJ_NO>'
  status: ACCEPTED
  subnetwork: https://www.googleapis.com/compute/v1/projects/${PROJ_ID}/regions/${REGION}/subnetworks/subnet-${REGION}-agw

Delegare l'autorizzazione

Agent Gateway protegge e gestisce il traffico degli strumenti in uscita utilizzando le policy di autorizzazione (networksecurity.authzPolicies) integrate con le Unified Access Policies (UAP) di Identity-Aware Proxy (IAP).

Anche se Agent Gateway supporta le regole di ALLOW e DENY di base in linea, gli ambienti aziendali richiedono una governance centralizzata e incentrata sull'identità. Con le Unified Access Policies IAM (o criteri di accesso), gestisci le regole di accesso in uscita utilizzando i criteri di accesso IAM v3 standard.

figure3

Fig. 3. Architettura di autorizzazione

Il flusso di autorizzazione collega tre componenti:

  1. Norme di autorizzazione del gateway (authzPolicy):
    • Una risorsa di regione che ha come target Agent Gateway.
    • Configurato con policyProfile: REQUEST_AUTHZ e action: CUSTOM per indirizzare tutti i controlli di autorizzazione in uscita all'estensione di autorizzazione IAP.
  2. Estensione del servizio IAP (authzExtension):
    • Una risorsa di regione che delega l'autorizzazione delle richieste a Identity-Aware Proxy (iap.googleapis.com).
    • Valuta le policy in modalità ENFORCE utilizzando la versione V2 della policy.
  3. Policy e binding di accesso unificato IAM (accessPolicy e policyBinding):
    • Risorse IAM globali v3 contenenti regole di accesso granulari.
    • Autentica l'identità principale SPIFFE dell'agente chiamante, verifica l'autorizzazione universale iap.googleapis.com/resources.egressViaIAP e valuta le condizioni del linguaggio Common Expression Language (CEL) in base agli attributi di destinazione.

Implementare l'estensione autorizzazione

Crea una configurazione dell'estensione di autorizzazione service-extensions che delega le decisioni di autorizzazione al servizio IAP:

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

Verifica l'estensione dell'autorizzazione

Controlla che l'estensione di autorizzazione sia attiva:

# list authz extensions
gcloud service-extensions authz-extensions list \
  --location=${REGION} \
  --format="table(
    name.basename():label=NAME,
    createTime.date(tz=LOCAL):label=CREATED,
    updateTime.date(tz=LOCAL):label=MODIFIED,
    service:label=SERVICE,
    metadata:label=METADATA,
    timeout:label=TIMEOUT
  )"

Policy di autorizzazione del deployment

Crea una configurazione dei criteri di autorizzazione network-security che ha come target Agent Gateway e delega la verifica delle richieste all'estensione di autorizzazione per IAP:

# create authz policy config file
cat > cfg/${AGW_NAME}-authz-policy-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-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"
EOF
# import authz policy config file (create authz policy)
gcloud network-security authz-policies import ${AGW_NAME}-authz-policy-iap \
  --source=cfg/${AGW_NAME}-authz-policy-iap.yaml \
  --location=${REGION}

Verifica della policy di autorizzazione

Verifica che il criterio di autorizzazione sia attivo:

# list authz policies
gcloud network-security authz-policies list \
  --location=${REGION} \
  --format="table(
    name.basename():label=NAME,
    action:label=ACTION,
    customProvider.list().sub('\W.*', ''):label=CUSTOM_PROVIDER_TYPE,
    policyProfile:label=POLICY_PROFILE,
    customProvider.authzExtension.resources[0].basename():label=CUSTOM_PROVIDER_RESOURCE
  )"

Crea policy di accesso IAM

Agent Gateway ora delega i controlli di autorizzazione a IAP e risolve i metadati di destinazione da Agent Registry. Successivamente, definisci una regola di policy Unified Access Policies IAM per gestire l'esecuzione dello strumento in uscita.

IAP valuta le espressioni degli attributi CEL in base ai seguenti attributi di destinazione di Agent Registry:

  • Stato di registrazione (destination.is_registered):
    • Valore booleano (true/false) che indica se la destinazione è catalogata in Agent Registry.
  • Nome server MCP (destination.agent_registry.mcp_server.name):
    • Nome canonico della risorsa del server MCP registrata in Agent Registry.
  • Metodo MCP (destination.agent_registry.mcp_server.method):
    • Il metodo MCP richiamato (ad es. tools/call, tools/list, initialize).
  • Nome strumento (destination.agent_registry.mcp_server.tool.name):
    • Il nome dello strumento specifico richiamato (ad es. subtract o add), che consente un'autorizzazione granulare a livello di strumento sui server MCP registrati.

Definisci la regola del criterio di accesso IAM

Il manifest della regola di policy IAM specifica:

  • Soggetti:l'identità del soggetto SPIFFE che rappresenta l'agente assistente principale di Gemini Enterprise.
  • Autorizzazioni:l'autorizzazione universale iap.googleapis.com/resources.egressViaIAP richiesta per tutto il traffico in uscita regolato da IAP.
  • Condizioni:un'espressione CEL (destination.is_registered == true) che garantisce che l'agente possa richiamare solo gli endpoint catalogati in Agent Registry.

Crea il file manifest della regola del criterio:

# create access policy rule file
cat > cfg/${UAP_POLICY_NAME}-rules.json << EOF
[
  {
    "description": "allow ge assistant to any registered service",
    "effect": "ALLOW",
    "principals": [
      "principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_INIT}/assistants/default_assistant/agents/default/core_assistant"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true"
      }
    }
  }
]
EOF

Esegui il deployment della policy di accesso IAM

Crea la policy di accesso IAM globale utilizzando le regole definite nel file manifest:

# create iam access policy
gcloud iam access-policies create ${UAP_POLICY_NAME} \
  --details-rules=cfg/${UAP_POLICY_NAME}-rules.json \
  --project=${PROJ_ID} \
  --location=global

Verifica la policy di accesso IAM

Controlla che la policy di accesso IAM sia stata creata correttamente ed esamina i dettagli della regola:

# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
  --project=${PROJ_ID} \
  --location=global

Output previsto:

details:
  rules:
  - conditions:
      iap.googleapis.com:
        expression: destination.is_registered == true
    description: allow ge assistant to any registered service
    effect: ALLOW
    operation:
      permissions:
      - iap.googleapis.com/resources.egressViaIAP
    principals:
    - principal://agents.global.org-${ORG_ID}.system.id.goog/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_INIT}/assistants/default_assistant/agents/default/core_assistant
name: projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}

Associa la policy di accesso IAM al progetto

Per attivare l'applicazione in tutti i gateway agenti del tuo progetto, crea un binding della policy che colleghi la policy di accesso IAM alla risorsa progetto:

# bind iam access policy to project resource
gcloud iam policy-bindings create ${UAP_BINDING_NAME} \
  --policy="projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}" \
  --target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJ_ID}" \
  --project=${PROJ_ID} \
  --location=global

Verifica l'associazione della policy di accesso IAM

Controlla che i punti di associazione delle norme attive rimandino alle norme e al target corretti:

# show policy binding details
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
  --project=${PROJ_ID} \
  --location=global

Output previsto:

name: projects/${PROJ_ID}/locations/global/policyBindings/${UAP_BINDING_NAME}
policy: projects/${PROJ_ID}/locations/global/accessPolicies/${UAP_POLICY_NAME}
policyKind: ACCESS
target:
  resource: //cloudresourcemanager.googleapis.com/projects/${PROJ_ID}

Con questo si conclude la sezione di Agent Gateway. Passiamo ora alla sezione del server MCP.

6. Server MCP

In questa sezione creerai un server FastMCP personalizzato che espone gli strumenti add e subtract e lo eseguirai il deployment su Cloud Run direttamente dall'origine. Durante il deployment dell'origine (--source), Cloud Build creerà un pacchetto dell'immagine container utilizzando Dockerfile e uv inclusi (che installa le dipendenze definite in pyproject.toml e avvia server.py).

Una volta eseguito il deployment del servizio Cloud Run, registra il server MCP in Agent Registry insieme alla relativa specifica dello strumento (toolspec.json) in modo che Gemini Enterprise possa rilevare e richiamare i relativi strumenti.

Crea l'applicazione server MCP

Crea una directory di progetto math-wizard per il codice dell'applicazione:

# create directory for code
mkdir -p math-wizard

Scrivi il file manifest del progetto Python:

# create python project manifest file
cat > math-wizard/pyproject.toml << 'EOF'
[project]
name = "math-wizard"
version = "0.1.0"
description = "math wizard mcp server"
requires-python = ">=3.12"
dependencies = [
    "fastmcp==2.13.1",
]
EOF

Nel codice sono incluse alcune funzioni di strumentazione aggiuntive per acquisire le intestazioni HTTP in entrata (mcp-session-id, x-forwarded-for, user-agent e x-cloud-trace-context) per la convalida di Cloud Logging e Cloud Trace.

Scrivi il file di codice dell'applicazione:

# create mcp server application code
cat > math-wizard/server.py << 'EOF'
import asyncio
import json
import logging
import os
from fastmcp import FastMCP
from fastmcp.server.dependencies import get_http_headers
from mcp.types import ToolAnnotations

logger = logging.getLogger(__name__)
logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)

mcp = FastMCP("math wizard mcp server")

def log_network_context(tool_name: str, a: int, b: int) -> None:
    headers = get_http_headers()
    print(json.dumps({
        "severity": "INFO",
        "message": f">>> 🛠️ Tool: '{tool_name}' called with numbers '{a}' and '{b}'",
        "tool": tool_name,
        "mcp_session_id": headers.get("mcp-session-id"),
        "x_forwarded_for": headers.get("x-forwarded-for"),
        "user_agent": headers.get("user-agent"),
        "trace_header": headers.get("x-cloud-trace-context"),
    }), flush=True)

@mcp.tool(
    annotations=ToolAnnotations(
        readOnlyHint=True,
    )
)
def add(a: int, b: int) -> int:
    """Use this to add two numbers together.

    Args:
        a: The first number.
        b: The second number.

    Returns:
        The sum of the two numbers.
    """
    logger.info(f">>> 🛠️ Tool: 'add' called with numbers '{a}' and '{b}'")
    log_network_context("add", a, b)
    return a + b

@mcp.tool(
    annotations=ToolAnnotations(
        readOnlyHint=True,
    )
)
def subtract(a: int, b: int) -> int:
    """Use this to subtract two numbers.

    Args:
        a: The first number.
        b: The second number.

    Returns:
        The difference of the two numbers.
    """
    logger.info(f">>> 🛠️ Tool: 'subtract' called with numbers '{a}' and '{b}'")
    log_network_context("subtract", a, b)
    return a - b

if __name__ == "__main__":
    logger.info(f"🚀 MCP server started on port {os.getenv('PORT', 8080)}")
    asyncio.run(
        mcp.run_async(
            transport="streamable-http",
            host="0.0.0.0",
            port=int(os.getenv("PORT", 8080)),
        )
    )
EOF

Scrivi il Dockerfile per definire le istruzioni di build dell'immagine container e i comandi di avvio:

# create dockerfile
cat > math-wizard/Dockerfile << 'EOF'
# use official python 3.12 image
FROM python:3.12-slim

# install uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# install the project into /app
COPY . /app
WORKDIR /app

# allow statements and log messages to immediately appear in the logs
ENV PYTHONUNBUFFERED=1

# install dependencies
RUN uv sync

EXPOSE 8080

# run the mcp server
CMD ["uv", "run", "server.py"]
EOF

Esegui il deployment del servizio in Cloud Run

Esegui il deployment del server MCP dall'origine utilizzando Cloud Build (che utilizza il service account di computing predefinito del progetto ${PROJ_NO}-compute@developer.gserviceaccount.com):

# deploy cloud run service
gcloud run deploy ${MCP_NAME} \
  --source math-wizard \
  --region=${REGION} \
  --no-invoker-iam-check \
  --ingress=internal \
  --quiet

Verifica il deployment di Cloud Run

Controlla i dettagli del servizio Cloud Run per verificarne la configurazione attiva:

# show cloud run service details
gcloud run services describe ${MCP_NAME} --region=${REGION}

Output previsto:

<snip>
✔ Service math-wizard in region ${REGION}

URL:     https://math-wizard-${PROJ_NO}.${REGION}.run.app
Ingress: internal
Traffic:
  100% LATEST (currently math-wizard-00001-<id>)
</snip>

Registrare il server MCP in Agent Registry

Per consentire a Gemini Enterprise di scoprire gli strumenti esatti disponibili sul server MCP, durante la registrazione ad Agent Registry deve essere fornito un file di specifiche degli strumenti (toolspec.json).

Crea la specifica dello strumento MCP

# create tool spec file
cat > cfg/toolspec.json << 'EOF'
{
  "tools": [
    {
      "name": "add",
      "description": "Use this to add two numbers together.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": { "type": "integer", "description": "The first number." },
          "b": { "type": "integer", "description": "The second number." }
        },
        "required": ["a", "b"]
      },
      "isReadOnly": true,
      "isDestructive": false,
      "isIdempotent": true,
      "isOpenWorld": false
    },
    {
      "name": "subtract",
      "description": "Use this to subtract two numbers.",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": { "type": "integer", "description": "The first number." },
          "b": { "type": "integer", "description": "The second number." }
        },
        "required": ["a", "b"]
      },
      "isReadOnly": true,
      "isDestructive": false,
      "isIdempotent": true,
      "isOpenWorld": false
    }
  ]
}
EOF

Registrare il server MCP in Agent Registry

# register mcp server in agent registry
gcloud agent-registry services create ${MCP_NAME} \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --display-name="${MCP_NAME}-${PROJ_NO}.${REGION}.run.app" \
  --description="MANDATORY MATH & ARITHMETIC AGENT: You MUST ALWAYS invoke \
this tool for ANY mathematical calculation, addition (+), subtraction (-), \
sum, difference, or arithmetic question (including simple questions like \
'what is 67 + 345?'). NEVER compute arithmetic yourself and NEVER transfer \
math queries to file_and_coding_agent / code interpreter. Always delegate \
every math question to this tool." \
  --mcp-server-spec-type=tool-spec \
  --mcp-server-spec-content=cfg/toolspec.json \
  --interfaces=protocolBinding=JSONRPC,url="${MCP_URL}"

Verificare il server MCP in Agent Registry

Verifica che il servizio Cloud Run di cui è stato eseguito il deployment sia elencato come server MCP registrato nella regione insieme al relativo URL endpoint e agli strumenti disponibili:

# list registered mcp servers in agent registry
gcloud agent-registry mcp-servers list \
  --location=${REGION} \
  --project=${PROJ_ID} \
  --format="table(
    name.basename():label=REGISTRY_ID,
    displayName:label=DISPLAY_NAME,
    interfaces[0].url:label=ENDPOINT_URL,
    tools[].name.list():label=TOOLS
  )"

Output previsto:

REGISTRY_ID                                         DISPLAY_NAME                                  ENDPOINT_URL                                              TOOLS
agentregistry-00000000-0000-0000-0012-3456789abcde  math-wizard-${PROJ_NO}.${REGION}.run.app      https://math-wizard-${PROJ_NO}.${REGION}.run.app/mcp      add,subtract

Visualizza la specifica di configurazione del servizio per verificare che registri le definizioni esatte degli strumenti, gli schemi di input e le annotazioni di comportamento per ogni strumento:

# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
  --location=${REGION} \
  --project=${PROJ_ID} \
  --format="yaml(mcpServerSpec.content.tools)"

Con questo si conclude la parte relativa al server MCP. Passiamo ora alla sezione Gemini Enterprise.

7. Gemini Enterprise

In questa sezione creerai e configurerai un'app Gemini Enterprise e una risorsa datastore del server MCP personalizzato collegata.

Modello di risorse Discovery Engine

Un'app Gemini Enterprise (rappresentata come risorsa Engine nell'API Discovery Engine) è il livello di orchestrazione centrale e l'interfaccia conversazionale per gli utenti finali. Gestisce le sessioni di chat degli utenti, basa i modelli generativi sui dati aziendali e coordina l'esecuzione dinamica degli strumenti.

Le app Gemini Enterprise interagiscono con dati e sistemi tramite i datastore:

  • Datastore di conoscenza:acquisisce e indicizza contenuti statici (ad es. Cloud Storage, Google Drive, BigQuery) per la Retrieval-Augmented Generation (RAG).
  • Connettori di dati (provider di azioni): connettiti ad API dinamiche di terze parti o personalizzate. Un datastore del server MCP personalizzato espone gli strumenti definiti dal Model Context Protocol (MCP), consentendo al modello di chiamare dinamicamente funzioni esterne durante una conversazione.

Routing in uscita tramite Agent Gateway

Per impostazione predefinita, Gemini Enterprise instrada il traffico di esecuzione di connettori e strumenti sulle reti pubbliche. Tuttavia, per i carichi di lavoro VPC privati e la governance zero-trust, il motore può essere configurato per instradare l'uscita tramite Agent Gateway:

  • Quando crei il datastore del server MCP personalizzato più avanti in questo lab, attivi l'opzione Instrada l'uscita tramite Agent Gateway nelle impostazioni del datastore.
  • In questo modo, le chiamate agli strumenti in uscita del motore vengono associate al gateway dell'agente regionale, garantendo che tutte le richieste MCP includano il Agent Identity dell'app, vengano sottoposte all'autorizzazione di runtime utilizzando IAP e le Unified Access Policies (UAP) IAM e attraversino il collegamento di rete PSC nel tuo VPC privato.

Crea l'app Gemini Enterprise

Il seguente metodo utilizza l'API discoveryengine.googleapis.com per creare le risorse e la configurazione dell'app Gemini Enterprise. Per la configurazione tramite la UI della console Google Cloud, consulta Creare un'app per istruzioni.

# create engine (ge app)
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines?engineId=${GE_APP_INIT}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "displayName": "${GE_APP_DISPLAY_NAME}",
  "dataStoreIds": [],
  "solutionType": "SOLUTION_TYPE_SEARCH",
  "industryVertical": "GENERIC",
  "appType": "APP_TYPE_INTRANET",
  "searchEngineConfig": {
    "searchTier": "SEARCH_TIER_ENTERPRISE",
    "searchAddOns": [
      "SEARCH_ADD_ON_LLM"
    ]
  },
  "commonConfig": {
    "companyName": "${GE_APP_ORG_NAME}"
  }
}
EOF

Verificare la creazione dell'app

# fetch engine (ge app) id
export GE_APP_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq -r --arg name "${GE_APP_DISPLAY_NAME}" '.engines[] | select(.displayName==$name) | .name | split("/") | last')

echo "engine (ge app) id: ${GE_APP_ID}"

Visualizza i dettagli del motore per vedere la configurazione creata:

# get engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

Prendi nota delle seguenti proprietà compilate dal server nella risposta JSON:

  • name: percorso della risorsa canonica (projects/${PROJ_NO}/locations/global/collections/default_collection/engines/${GE_APP_ID}).
  • sessionConfig.sessionManagementPolicy: il valore predefinito è "VERTEX_AI_MANAGED", che rende persistente lo stato della chat a più turni e della chiamata di strumenti in Agent Platform (in precedenza nota come Vertex AI).
  • observabilityConfig.observabilityEnabled: il valore predefinito è true per le metriche di base (la registrazione dettagliata del prompt e del payload dello strumento viene attivata in un passaggio successivo).

Abilita il provider di identità

Abilita Google Identity come provider di identità per l'autenticazione degli utenti finali nella tua app Gemini Enterprise.

Il seguente metodo utilizza l'API discoveryengine.googleapis.com per configurare il provider di identità dell'app Gemini Enterprise. Per configurare l'utilizzo dell'interfaccia utente della console Google Cloud, consulta Configurare il provider di identità per istruzioni.

# set identity provider
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "idpConfig": {
    "idpType": "GSUITE"
  }
}
EOF

Verificare il provider di identità

# show identity provider
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

L'output "idpType": "GSUITE" corrisponde al provider Google Identity.

(Facoltativo) Abilita la licenza di prova di Gemini Enterprise

Se utilizzi un progetto a cui sono assegnate licenze Gemini Enterprise, puoi saltare questo passaggio. Se utilizzi un nuovo progetto senza licenza, continua e segui questi passaggi.

Crea una risorsa di configurazione della licenza per assegnare i posti utente Gemini Enterprise per 30 giorni. In questo modo, la licenza predefinita verrà impostata sulla nuova prova, quindi a ogni utente che accede verrà automaticamente concesso un posto:

# configure free trial subscription
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs?licenseConfigId=free_trial_gemini" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "subscriptionTier": "SUBSCRIPTION_TIER_SEARCH_AND_ASSISTANT",
  "freeTrial": true
}
EOF

Verificare che la licenza sia stata applicata

# show license config
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs/free_trial_gemini" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

Controlla la presenza di "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" e "freeTrial": true.

# verify auto-registration enabled on default user store
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/userStores/default_user_store" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

Controlla la presenza di ../free_trial_gemini" e "enableLicenseAutoRegister": true.

Attivare le impostazioni di osservabilità

L'attivazione dell'osservabilità a livello di app (motore) Gemini Enterprise ti consente di visualizzare le interazioni dell'assistente principale con i dati delle metriche in Esplora metriche e di correlare le tracce end-to-end in Cloud Trace.

# set observability on engine (ge app)
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}?updateMask=observabilityConfig" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "observabilityConfig": {
    "observabilityEnabled": true,
    "sensitiveLoggingEnabled": true
  }
}
EOF

Verifica le impostazioni di osservabilità

# verify observability is enabled on engine (ge app)
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq '{observabilityConfig: .observabilityConfig}'

Controlla la presenza di "sensitiveLoggingEnabled": true.

Associazione ad Agent Gateway

L'instradamento del traffico in uscita da Gemini Enterprise tramite Agent Gateway stabilisce un limite di governance e applicazione della sicurezza Zero Trust centralizzato per tutte le chiamate agli strumenti degli agenti AI:

  • Applicazione centralizzata delle policy:Agent Gateway funge da proxy inline che valuta le richieste di strumenti in uscita in base alle policy di autorizzazione e ai controlli di governance prima che il traffico esca dall'ambiente dell'agente.
  • Traffico in uscita dalla rete privata:il binding di Gemini Enterprise ad Agent Gateway garantisce che le chiamate di strumenti che hanno come target server MCP privati su Cloud Run vengano instradate in modo sicuro tramite Private Service Connect (PSC), bypassando internet pubblico.
  • Auditabilità unificata:fornisce la registrazione centralizzata delle richieste, la telemetria e le tracce di controllo su tutti i server MCP connessi e gli strumenti esterni.

Se configuri agentGatewaySetting nell'app Gemini Enterprise, le chiamate in uscita a strumenti e agenti avviate da query degli utenti finali (ad esempio chiamate a server MCP personalizzati importati da Agent Registry e agenti A2A) vengono automaticamente indirizzate tramite Agent Gateway.

Applica una patch al motore agentGatewaySetting per abilitare:

# bind engine (ge app) to agent gateway
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}?updateMask=agentGatewaySetting.defaultEgressAgentGateway.name" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "agentGatewaySetting": {
    "defaultEgressAgentGateway": {
      "name": "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
    }
  }
}
EOF

Verificare il binding di Agent Gateway

Recupera la configurazione dell'app per confermare l'associazione agentGatewaySetting:

# verify engine (ge app) agent gateway configuration
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq '{name: .name, displayName: .displayName, agentGatewaySetting: .agentGatewaySetting}'

Output previsto:

{
  "name": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}",
  "displayName": "${GE_APP_DISPLAY_NAME}",
  "agentGatewaySetting": {
    "defaultEgressAgentGateway": {
      "name": "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
    }
  }
}

Crea un datastore del server MCP personalizzato

In questa sezione connetterai il server MCP a Gemini Enterprise creando un datastore MCP personalizzato.

Utilizzando l'API Discovery Engine, si tratta di una procedura in due passaggi:

  1. Crea (:setUpDataConnector): crea una risorsa Collection dedicata (${MCP_NAME}-%timestamp-collection), collega DataConnector (custom_mcp) e ne esegue il provisioning del DataStore di backup (..._mcp_data).
  2. Attiva (PATCH .../dataConnector?updateMask=actionConfig): attiva il runtime dell'azione del connettore (actionState: "ACTIVE") utilizzando la specifica dello strumento Agent Registry e associa DataStore (dataStoreIds) al tuo Gemini Enterprise Engine.
# fetch mcp server agent registry resource name
export MCP_REGISTRY_URI=$(gcloud agent-registry mcp-servers list \
  --location=${REGION} \
  --project=${PROJ_ID} \
  --filter="displayName:${MCP_NAME}" \
  --format="value(name)")

echo "mcp registry name: ${MCP_REGISTRY_URI}"
echo "mcp url: ${MCP_URL}"

Crea connettore dati

# create custom mcp data connector from agent registry and link to engine
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}:setUpDataConnector" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "collectionId": "${MCP_NAME}-$(date +%s)-collection",
  "collectionDisplayName": "${MCP_NAME}-collection",
  "dataConnector": {
    "dataSource": "custom_mcp",
    "dataSourceVersion": 1,
    "params": {
      "oauth_access_token": "unused"
    },
    "refreshInterval": "86400s",
    "entities": [
      {
        "entityName": "mcp_data"
      }
    ],
    "connectorModes": [
      "FEDERATED"
    ],
    "actionConfig": {
      "isActionConfigured": true,
      "createBapConnection": true,
      "actionParams": {
        "auth_type": "NO_AUTH",
        "instance_uri": "${MCP_URL}",
        "mcp_server_source": "REGISTRY_MCP",
        "registry_mcp_server_name": "${MCP_REGISTRY_URI}",
        "mcp_agent_instructions": "MANDATORY MATH & ARITHMETIC AGENT: Always invoke this tool for any mathematical calculation, addition (+), subtraction (-), sum, or difference.",
        "use_agent_gateway_egress": true,
        "agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
      }
    }
  }
}
EOF

Verificare la creazione del connettore dati

# fetch collection id
export GE_COLLECTION_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq -r --arg dname "${MCP_NAME}-collection" '.collections[] | select(.displayName == $dname) | .name | split("/") | last' | head -n 1)

echo "ge collection id: ${GE_COLLECTION_ID}"

Controlla che il campo "registry_mcp_server_name" venga compilato con l'UUID di Agent Registry per il server MCP:

# show data connector details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/dataConnector" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq '{name, state, actionState, connectorModes, bapConfig, registry_mcp_server_name: .actionConfig.actionParams.registry_mcp_server_name}'

Visualizza la voce del registro del server MCP nella UI della console Google Cloud:

echo "mcp server registry page url: https://console.cloud.google.com/agent-platform/agent-registry/mcp-servers/${REGION}/${MCP_REGISTRY_URI##*/}/overview?project=${PROJ_ID}"

Attivare il connettore dati

# activate and bind data connector
curl -s -X PATCH "https://discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector?updateMask=actionConfig" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "name": "projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector",
  "actionConfig": {
    "isActionConfigured": true,
    "createBapConnection": true,
    "actionParams": {
      "auth_type": "NO_AUTH",
      "instance_uri": "${MCP_URL}",
      "mcp_server_source": "REGISTRY_MCP",
      "registry_mcp_server_name": "${MCP_REGISTRY_URI}",
      "mcp_agent_instructions": "MANDATORY MATH & ARITHMETIC AGENT: Always invoke this tool for any mathematical calculation, addition (+), subtraction (-), sum, or difference.",
      "use_agent_gateway_egress": true,
      "agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
    }
  }
}
EOF

Verifica i collegamenti del server MCP personalizzato

# show engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq '{name: .name, dataStoreIds: .dataStoreIds, agentGatewaySetting: .agentGatewaySetting}'

Controlla il datastore collegato "dataStoreIds": "collection-math-wizard-_mcp_data".

# show collection details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  | jq --arg app "${GE_APP_ID}" '.collections[] | select(.dataConnector.actionConfig.actionParams.agent_gateway_engine // "" | endswith($app)) | .dataConnector | {name: .name, state: .state, actionState: .actionState, connectorModes: .connectorModes, actionParams: .actionConfig.actionParams}'

Controlla la presenza di "state": "ACTIVE" con tutti i parametri compilati.

Azioni dello strumento

Quando esamini il datastore math-wizard-collection nella dashboard di Gemini Enterprise, noterai che la scheda Azioni non viene utilizzata e il pulsante ↻ Ricarica azioni personalizzate è disattivato. Questo è un comportamento previsto.

Visualizza la pagina dei dettagli del datastore nell'interfaccia utente della console Google Cloud:

echo "data store details page url: https://console.cloud.google.com/gemini-enterprise/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/connector/details?project=${PROJ_ID}"

A seconda di come connetti un server MCP personalizzato a Gemini Enterprise, il rilevamento e la governance degli strumenti vengono gestiti in uno dei due modi seguenti:

  • Workflow MCP personalizzato diretto (BYO_MCP): quando configuri un server MCP personalizzato direttamente in Gemini Enterprise senza Agent Registry, l'archivio dati stesso gestisce il catalogo degli strumenti (connectorModes: ["FEDERATED", "ACTIONS"]). Devi aprire la scheda Azioni, fare clic su ↻ Ricarica azioni personalizzate per recuperare lo schema tools/list e attivare o disattivare manualmente i singoli strumenti (add e subtract) nell'interfaccia utente.
  • Importazione di Agent Registry (REGISTRY_MCP flusso di lavoro utilizzato in questo codelab): quando importi un server MCP da Agent Registry, Agent Registry funge da fonte autorevole di verità per l'endpoint MCP, i relativi metadati dell'interfaccia e il catalogo degli strumenti (connectorModes: ["FEDERATED"]). Gemini Enterprise attiva automaticamente gli strumenti MCP registrati in fase di runtime tramite Agent Gateway del motore senza richiedere il ricaricamento o l'attivazione/disattivazione manuale delle azioni nell'interfaccia utente dell'archivio dati.

Con questo si conclude la parte relativa all'app Gemini Enterprise. Passiamo ora alla sezione Convalida.

8. Convalida

In questa sezione attiverai chiamate live dello strumento MCP dall'app web Gemini Enterprise e traccerai il flusso delle richieste nei log di Agent Gateway, Cloud DNS, firewall VPC e Cloud Run. A questo punto, rafforzerai il criterio di accesso unificato IAM per consentire subtract bloccando add, verificando l'applicazione di Zero Trust al gateway.

Accesso utente

Crea l'URL per l'app web Gemini Enterprise:

# fetch app user url
export GE_WIDGET_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/widgetConfigs/default_search_widget_config" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  | jq -r '.configId')

export GE_APP_USER_URL="https://vertexaisearch.cloud.google.com/home/cid/${GE_WIDGET_ID}"

echo "app user url: ${GE_APP_USER_URL}"

Segui il link per aprire l'interfaccia di chat dell'app web Gemini Enterprise nel browser e fai clic su Inizia.

Testare le query dell'agente nella chat

Nell'interfaccia utente della chat, verifica che il connettore dati math-wizard-collection sia attivato facendo clic sull'icona a forma di puzzle per Connettori nella parte inferiore della casella di chat. Dovresti vedere un pulsante di attivazione/disattivazione colorato.

Prova le seguenti query di test:

what is 2342345 - 98234798324?
what is 72347234 + 234234?

Verifica che l'assistente restituisca le risposte corrette e mostri un badge di citazione dell'azione interattivo (come Math Calculation (8s) 🤖 Agentgateway Agent) sotto ogni risposta, a conferma dell'esecuzione dello strumento.

Controllare i log in Cloud Logging

Verifica che Gemini Enterprise abbia indirizzato le chiamate agli strumenti tramite Agent Gateway e la rete VPC privata esaminando i log in Cloud Logging.

1. Verifica l'autorizzazione di Agent Gateway e IAP

Verifica che Agent Gateway abbia intercettato la richiesta, risolto la destinazione in Agent Registry, delegato l'autorizzazione a IAP e consentito la chiamata allo strumento:

# show agent gateway logs
gcloud logging read 'resource.type="networkservices.googleapis.com/Gateway"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="table( \
    timestamp.date(tz=LOCAL):label=TIMESTAMP, \
    httpRequest.status:label=STATUS, \
    httpRequest.serverIp:label=SERVER_IP, \
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD, \
    jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL, \
    jsonPayload.authzPolicyInfo.result:label=AUTHZ, \
    jsonPayload.agentGatewayInfo.agentRegistryResource.basename():label=REGISTRY_MCP
  )"

Verifica che l'output contenga:

  • STATUS: 200 (esecuzione riuscita) e 202 (handshake notifications/initialized).
  • SERVER_IP: IP dell'endpoint PSC delle API di Google (172.16.20.20:443).
  • MCP_METHOD e TOOL: la sequenza del protocollo MCP (notifications/initialized, tools/list e tools/call con add o subtract).
  • AUTHZ: ALLOWED (uscita autorizzata da IAP).
  • REGISTRY_MCP: ID risorsa dell'Agent Registry risolto (agentregistry-...).

2. Verifica il transito di DNS e firewall

Verifica che Cloud DNS abbia risolto il nome host nell'endpoint PSC e che il firewall abbia consentito il traffico dall'interfaccia Agent Gateway:

# show dns logs
gcloud logging read 'resource.type="dns_query"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="table( \
    timestamp.date(tz=LOCAL):label=TIMESTAMP, \
    jsonPayload.queryName:label=QUERY_NAME, \
    jsonPayload.queryType:label=TYPE, \
    jsonPayload.responseCode:label=RCODE, \
    jsonPayload.rdata:label=RDATA
  )"
# show firewall logs
gcloud logging read 'logName:"compute.googleapis.com%2Ffirewall"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="table( \
    timestamp.date(tz=LOCAL):label=TIMESTAMP, \
    jsonPayload.connection.src_ip:label=SRC_IP, \
    jsonPayload.connection.dest_ip:label=DEST_IP, \
    jsonPayload.connection.dest_port:label=PORT, \
    jsonPayload.rule_details.reference.basename():label=RULE, \
    jsonPayload.disposition:label=DISPOSITION
  )"

Verifica i seguenti valori:

  • DNS QUERY_NAME e RDATA: risolve math-wizard-...run.app. (record A, NOERROR) in 172.16.20.20.
  • Firewall SRC_IP e DEST_IP: 192.168.10.2 (IP dell'interfaccia PSC dell'Agent Gateway) a 172.16.20.20:443.
  • Firewall RULE e DISPOSITION: corrispondenza di firewallPolicy:fw-policy-... con ALLOWED.

3. Verifica l'esecuzione dello strumento Cloud Run

Verifica che il container Cloud Run abbia ricevuto ed elaborato la chiamata allo strumento:

# show cloud run logs
gcloud logging read 'resource.type="cloud_run_revision"
  AND textPayload:"Tool:"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="value(timestamp.date(tz=LOCAL), textPayload)"

Verifica che textPayload mostri le voci di esecuzione dello strumento (ad es. >>> 🛠️ Tool: 'subtract' called with numbers '[x]' and '[y]').

Testare l'applicazione del criterio del privilegio minimo

Nella policy di accesso IAM iniziale, qualsiasi metodo o strumento era consentito purché la destinazione fosse registrata (destination.is_registered == true). In questo passaggio, aggiorna la policy per applicare il principio del privilegio minimo consentendo solo lo strumento subtract e bloccando add.

Aggiorna policy di accesso IAM

Quando limiti l'esecuzione dello strumento MCP, utilizza un pattern a due regole:

  1. Regola 1 (individuazione e handshake MCP): consente i metodi del ciclo di vita MCP non di chiamata di strumenti (destination.is_registered == true e destination.agent_registry.mcp_server.method != 'tools/call'). Poiché Gemini Enterprise negozia la configurazione e l'individuazione dello stream (initialize, notifications/initialized, tools/list) prima di richiamare uno strumento e destination.agent_registry.mcp_server.tool.name viene compilato solo durante tools/call, la regola 1 è necessaria per mantenere il funzionamento dell'inizializzazione della sessione e dell'individuazione del catalogo.
  2. Regola 2 (limitazione a livello di strumento): limita l'esecuzione di tools/call in modo che sia consentito solo lo strumento subtract (destination.is_registered == true, destination.agent_registry.mcp_server.method == 'tools/call' e destination.agent_registry.mcp_server.tool.name == 'subtract').

Aggiorna il file manifest della regola della policy di accesso con entrambe le regole:

# create access policy rule file (update: allow subtract only)
cat > cfg/${UAP_POLICY_NAME}-rule-update.json << EOF
[
  {
    "description": "allow ge assistant to any registered endpoint to perform mcp discovery and handshake",
    "effect": "ALLOW",
    "principals": [
      "principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_ID}/assistants/default_assistant/agents/default/core_assistant"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true && \
         destination.agent_registry.mcp_server.method != 'tools/call'"
      }
    }
  },
  {
    "description": "allow ge assistant to any registered mcp server with tool call subtract",
    "effect": "ALLOW",
    "principals": [
      "principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_ID}/assistants/default_assistant/agents/default/core_assistant"
    ],
    "operation": {
      "permissions": [
        "iap.googleapis.com/resources.egressViaIAP"
      ]
    },
    "conditions": {
      "iap.googleapis.com": {
        "expression": \
        "destination.is_registered == true && \
         destination.agent_registry.mcp_server.method == 'tools/call' && \
         destination.agent_registry.mcp_server.tool.name == 'subtract'"
      }
    }
  }
]
EOF

Applica le regole aggiornate al criterio di accesso IAM:

# update iam access policy
gcloud iam access-policies update ${UAP_POLICY_NAME} \
  --details-rules=cfg/${UAP_POLICY_NAME}-rule-update.json \
  --project=${PROJ_ID} \
  --location=global

Verifica la policy di accesso IAM

Controlla che il nuovo criterio di accesso IAM sia applicato e che sia consentito solo lo strumento di sottrazione:

# show iam access policy details
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
  --project=${PROJ_ID} \
  --location=global \
  --flatten="details.rules[]" \
  --format="table( \
    details.rules.principals[0].scope(engines).sub('assistants/default_assistant/agents/default', '...'):label=PRINCIPAL, \
    details.rules.effect:label=EFFECT, \
    details.rules.conditions.'iap.googleapis.com'.expression.sub('\s*&&\s*', '\n&& ').sub('\s*\|\|\s*', '\n|| '):label=EXPRESSION
  )"

Testare una chiamata allo strumento vietata

Torna alla UI della chat dell'app web Gemini Enterprise e prova un'altra query di test:

what is 100 plus 20?

L'assistente tenta di richiamare add, ma Agent Gateway e IAP valutano la condizione dei criteri IAM come false e negano la richiesta in uscita con HTTP 403 Forbidden. Nell'interfaccia utente della chat, vedrai l'assistente visualizzare Calculate Sum e ruotare su 🤖 Agentgateway Agent ... Working on it. mentre riprova la chiamata allo strumento bloccata. Questo è un comportamento previsto. Conferma che Agent Gateway e IAP intercettano e negano attivamente l'esecuzione di strumenti non consentiti a livello di rete.

Eseguire nuovamente l'ispezione dei log in Cloud Logging

Visualizza le voci di log di Agent Gateway e nota le nuove voci 403 corrispondenti alla chiamata allo strumento add non consentita:

# show agent gateway logs
gcloud logging read 'resource.type="networkservices.googleapis.com/Gateway"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="table( \
    timestamp.date(tz=LOCAL):label=TIMESTAMP, \
    httpRequest.status:label=STATUS, \
    httpRequest.serverIp:label=SERVER_IP, \
    jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD, \
    jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL, \
    jsonPayload.authzPolicyInfo.result:label=AUTHZ, \
    jsonPayload.agentGatewayInfo.agentRegistryResource.basename():label=REGISTRY_MCP
  )"

Output previsto:

TIMESTAMP            STATUS  SERVER_IP         MCP_METHOD                 TOOL  AUTHZ    REGISTRY_MCP
YYYY-MM-DDTHH:MM:SS  403                       tools/call                 add   DENIED   agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS  403
YYYY-MM-DDTHH:MM:SS  202     172.16.20.20:443  notifications/initialized        ALLOWED  agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS          172.16.20.20:443                                   ALLOWED  agentregistry-00000000-0000-0000-0012-3456789abcde
YYYY-MM-DDTHH:MM:SS  200     172.16.20.20:443  initialize                       ALLOWED  agentregistry-00000000-0000-0000-0012-3456789abcde

Verifica che la richiesta aggiuntiva non abbia mai raggiunto il backend di Cloud Run:

# show cloud run logs
gcloud logging read 'resource.type="cloud_run_revision"
  AND textPayload:"Tool:"' \
  --project=${PROJ_ID} \
  --limit=5 \
  --format="value(timestamp.date(tz=LOCAL), textPayload)"

Il comando non restituisce nuove voci, il che conferma che Agent Gateway ha applicato correttamente la policy di accesso IAM.

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

9. Esegui la pulizia

Segui questi passaggi per eliminare le risorse e le configurazioni create in questo lab.

Rimuovere i componenti di Gemini Enterprise

# delete gemini enterprise engine (app)
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

# delete custom mcp collection, data connector, and backing data store
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}"

# reset identity provider configuration
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "X-Goog-User-Project: ${PROJ_ID}" \
  -H "Content-Type: application/json" \
  -d '{"idpConfig":{"idpType":"IDP_TYPE_UNSPECIFIED"}}'

Rimuovere i componenti del server MCP

# delete agent registry service
gcloud -q agent-registry services delete ${MCP_NAME} \
  --location=${REGION} \
  --project=${PROJ_ID}

# delete cloud run service, source-deploy artifact registry repo, and staging bucket
gcloud -q run services delete ${MCP_NAME} \
  --region=${REGION} \
  --project=${PROJ_ID}

gcloud -q artifacts repositories delete cloud-run-source-deploy \
  --location=${REGION} \
  --project=${PROJ_ID}

gcloud -q storage rm --recursive gs://run-sources-${PROJ_ID}-${REGION} \
  --project=${PROJ_ID}

Rimuovi le policy di accesso IAM e Agent Gateway

# delete gateway authorization policy, iap extension, and agent gateway
gcloud -q network-security authz-policies delete ${AGW_NAME}-authz-policy-iap \
  --location=${REGION} \
  --project=${PROJ_ID}

gcloud -q service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
  --location=${REGION} \
  --project=${PROJ_ID}

gcloud -q network-services agent-gateways delete ${AGW_NAME} \
  --location=${REGION} \
  --project=${PROJ_ID}
# delete iam policy binding and access policy
gcloud -q iam policy-bindings delete ${UAP_BINDING_NAME} \
  --location=global \
  --project=${PROJ_ID}

gcloud -q iam access-policies delete ${UAP_POLICY_NAME} \
  --location=global \
  --project=${PROJ_ID}

Rimuovi i componenti DNS e firewall

# delete dns record set, managed zone, and policy
gcloud -q dns record-sets delete "*.run.app." \
  --type=A \
  --zone=priv-zone-run \
  --project=${PROJ_ID}

gcloud -q dns managed-zones delete priv-zone-run \
  --project=${PROJ_ID}

gcloud -q dns policies update dns-policy-${SLUG} \
  --networks="" \
  --project=${PROJ_ID}

gcloud -q dns policies delete dns-policy-${SLUG} \
  --project=${PROJ_ID}
# delete firewall policy association, rule, and policy
gcloud -q compute network-firewall-policies associations delete \
  --name=fw-policy-bind-${SLUG} \
  --firewall-policy=fw-policy-${SLUG} \
  --global-firewall-policy \
  --project=${PROJ_ID}

gcloud -q compute network-firewall-policies rules delete 1001 \
  --firewall-policy=fw-policy-${SLUG} \
  --global-firewall-policy \
  --project=${PROJ_ID}

gcloud -q compute network-firewall-policies delete fw-policy-${SLUG} \
  --global \
  --project=${PROJ_ID}

Rimuovi i componenti di PSC e della rete VPC

# delete psc forwarding rule and internal ip address
gcloud -q compute forwarding-rules delete psc2gapis \
  --global \
  --project=${PROJ_ID}

gcloud -q compute addresses delete ip-psc2gapis \
  --global \
  --project=${PROJ_ID}
# delete psc network attachment, subnet, and vpc network
gcloud -q compute network-attachments delete psc-na-${REGION}-agw \
  --region=${REGION} \
  --project=${PROJ_ID}

gcloud -q compute networks subnets delete subnet-${REGION}-agw \
  --region=${REGION} \
  --project=${PROJ_ID}

gcloud -q compute networks delete vnet-${SLUG} \
  --project=${PROJ_ID}

Rimuovi gli override delle policy dell'organizzazione e i file locali

# delete project-level organization policy overrides
gcloud -q org-policies delete discoveryengine.managed.disableCustomMcpServerConnector --project=${PROJ_ID}
gcloud -q org-policies delete iam.managed.disableAccessPolicyBinding --project=${PROJ_ID}
# remove local project files
rm -rf cfg math-wizard

Il lavoro di pulizia è terminato. Passiamo alla conclusione.

10. Conclusione

Complimenti! Hai creato un'architettura end-to-end che consente a un'app Gemini Enterprise di rilevare e richiamare in modo sicuro gli strumenti su un server MCP personalizzato privato:

  • Server MCP personalizzato e Agent Registry: è stato eseguito il deployment di un servizio FastMCP privato su Cloud Run (--ingress=internal) e sono stati registrati il relativo endpoint e lo schema degli strumenti (add e subtract) in Agent Registry.
  • Integrazione di Gemini Enterprise:è stata eseguita il provisioning di un'app Gemini Enterprise, è stato associato il traffico degli strumenti in uscita a Agent Gateway ed è stato collegato il server MCP registrato come connettore dati REGISTRY_MCP.
  • Egress privato VPC e governance zero-trust:esecuzione privata dello strumento tramite PSC (172.16.20.20) e applicazione del privilegio minimo a livello di strumento utilizzando IAP e le Unified Access Policies IAM (destination.agent_registry.*).

cosmopup

Cosmpup pensa che i codelab siano assolutamente fantastici.

Quali sono i passaggi successivi?

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

Grazie.