1. Introduction
This codelab explores private, governed egress connectivity for Gemini Enterprise using Agent Gateway in agent-to-anywhere (egress) mode. You will configure a Gemini Enterprise app to securely invoke a custom Model Context Protocol (MCP) server hosted on Cloud Run by routing traffic through Agent Gateway using Private Service Connect (PSC) interfaces to connect to a PSC endpoint for Google APIs in a VPC network.
In enterprise environments, granting autonomous agents direct network access risks data exfiltration and unvetted tool execution. Agent Gateway provides a centralized, platform-level zero-trust enforcement point that dynamically inspects streamable HTTP MCP tool payloads. Outbound requests are authenticated with a cryptographically verifiable Agent Identity and authorized through Identity-Aware Proxy (IAP) using IAM Unified Access Policies (UAP) with Common Expression Language (CEL) rules. This enables granular access control over specific MCP tools and methods without exposing backend workloads to the public internet.
What you build
- Agent Gateway operating in egress (agent-to-anywhere) mode with Agent Registry endpoint verification
- Cloud Run service hosting a private streamable HTTP MCP server (
--ingress=internal) registered with its tool specifications in Agent Registry - Identity-Aware Proxy (IAP) authorization extension for Agent Gateway
- IAM Unified Access Policies (UAP) with CEL conditions for MCP tool authorization
- Gemini Enterprise app bound to Agent Gateway and connected to a custom MCP server data store imported from Agent Registry
- VPC network resources, Cloud DNS zone, and PSC endpoint for Google APIs
- PSC network attachment for Agent Gateway private VPC egress
- Cloud Next Generation Firewall (NGFW) policy rules to secure VPC traffic
Fig 1. Codelab architecture
What you learn
- How to deploy a private streamable HTTP MCP server from source on Cloud Run and register its endpoint and tool schema in Agent Registry
- How to configure Agent Gateway with compliant registry entries and route Gemini Enterprise app tool calls through the gateway
- How to establish private VPC egress using PSC network attachments and interfaces
- How to delegate Agent Gateway authorization to Identity-Aware Proxy (IAP)
- How to author and bind IAM Unified Access Policies (UAP) using
destination.agent_registry.*anddestination.is_registeredCEL attributes to restrict MCP tool execution - How to validate policy enforcement and network egress using Cloud Logging
What you need
- A Google Cloud project with billing enabled
- An active Gemini Enterprise license or 30-day trial
- IAM permissions to provision networking services, Gemini Enterprise, and Agent Platform resources
- A POSIX-compatible shell (
bashorzsh) with Google Cloud CLI (gcloud),curl, andjqinstalled
This concludes the introduction portion... next on to the Concepts section.
2. Concepts
Deployment sequence
This codelab deploys the infrastructure first so private network paths and governance controls are operational before registering and connecting MCP tools with Gemini Enterprise:
- Network infrastructure: Provision VPC subnets, a PSC endpoint, a PSC network attachment, Cloud NGFW policy rules, and private Cloud DNS zones.
- Agent Gateway: Deploy Agent Gateway in egress mode with Agent Registry integration (
registries) and private VPC egress (networkAttachment). - Authorization policies: Configure the IAP authorization extension, Gateway Authz policy, and IAM Unified Access Policy (UAP) using
destination.is_registeredanddestination.agent_registry.*CEL conditions. - Deploy & register MCP server: Deploy the math MCP server from source to Cloud Run (
--ingress=internal) and register the service and tool specifications (addandsubtract) in Agent Registry. - Gemini Enterprise app: Create the Gemini Enterprise app (
Engine), configure identity and observability settings, and bind outbound egress to Agent Gateway (agentGatewaySetting). - Import custom MCP data connector: Create and activate the
REGISTRY_MCPdata connector (:setUpDataConnector) to link the registered MCP server's backing data store to the Gemini Enterprise app. - Validate: Test allowed and denied tool executions in chat and verify policy enforcement across Agent Gateway, DNS, Firewall, and Cloud Run logs.
Gemini Enterprise egress
Gemini Enterprise routes custom MCP server tool requests to Agent Gateway when both agentGatewaySetting on the Engine and use_agent_gateway_egress: true on the DataConnector are configured.
Fig 2. Gemini Enterprise egress architecture
The Gemini Enterprise app organizes tool routing across four key areas:
- Widget (
default_search_widget_config):- Serves the web client interface. The widget receives prompts from the user and initiates chat sessions with the underlying engine.
- Core Assistant (
assistants/default_assistant/agents/default/core_assistant):- The root conversational reasoning agent within the engine. When evaluating a user query, the Core Assistant determines whether arithmetic calculation is required, inspects available tools, and delegates execution to the synthesized Agent Gateway sub-agent.
- Data Store and Data Connector:
DataStore: Provisioned inside a dedicatedCollectionwhen:setUpDataConnectorruns, it links (dataStoreIds) the imported Agent Registry tool schemas (add,subtract), argument types, and agent instructions to the Gemini EnterpriseEngine.DataConnector: Manages theREGISTRY_MCPaction connection (createBapConnection: true) to the remote MCP server (instance_uri), resolves the Agent Registry MCP server resource (registry_mcp_server_name), and enables Agent Gateway egress (use_agent_gateway_egress: true).
- Agent Identity, Agent Registry, and Agent Gateway:
- When the Data Connector dispatches the outbound tool call, it routes traffic to the gateway specified in
agentGatewaySetting. The Core Assistant mints a SPIFFE identity token asserting its identity:principal://agents.global.org-.../agents/default/core_assistant. - Agent Gateway integrates with Agent Registry using the
registriesfield to dynamically resolve destination endpoints and registered tool schemas. It populatesdestination.is_registeredanddestination.agent_registry.*attributes and passes them to IAP v2 for evaluation against IAM Unified Access Policy (UAP) CEL rules before permitting transit into the VPC network.
- When the Data Connector dispatches the outbound tool call, it routes traffic to the gateway specified in
Gateway VPC connectivity
Agent Gateway enables private VPC network connectivity using two YAML fields:
networkConfig.egress.networkAttachment: Directs private IP traffic to be routed through the PSC network attachment into the VPC network.dnsPeeringConfig.domains: Peers DNS resolution with the VPC network Cloud DNS zone so target hostnames (*.run.app) resolve to the private PSC endpoint IP address defined in the VPC network.
Limitations & requirements
- StreamableHTTP only: The legacy Server-Sent Events (SSE) transport is not supported. MCP servers must use StreamableHTTP.
- Public CA TLS required: MCP endpoints must use TLS certificates signed by a publicly trusted CA, even when accessed privately over PSC.
- Org policy override: You must explicitly override the organization policy for Custom MCP data stores before registering the data store.
This concludes the concepts portion... next on to the Setup section.
3. Setup
Required IAM roles
The following roles are required to complete Codelab:
Domain | Required IAM roles |
Project & IAM |
|
Networking & Gateway |
|
Gemini Enterprise & Registry |
|
Workloads & Build |
|
Observability |
|
Or use a broad basic role like roles/owner combined with roles/orgpolicy.policyAdmin (since roles/owner alone cannot modify organization policies).
Access your project
This Codelab uses a single Google Cloud project. Configuration steps use gcloud CLI and Linux shell commands.
Start by accessing your Google Cloud project command line:
- Cloud Shell at
shell.cloud.google.com, or - A local terminal with
gcloudCLI installed
Set your Project ID
gcloud config set project SET_YOUR_PROJECT_ID_HERE
Authenticate session
# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login
Set shell environment variables
# 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}
Set agent identity trust domains
The if-then-else statement checks if the project belongs to an organization in order to set the correct trust domain for the principal agent identities.
# 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}"
Set billing and quota project
# 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}
Create local directory for config files
# create config folder
mkdir -p cfg
Update gcloud cli (recommended)
If running a self-managed install of the Google Cloud SDK (ie, outside of Cloud Shell), update the components to the latest version.
# update gcloud cli
gcloud components update
Enable API services
# 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
Organization Policies
Default Google Cloud managed organization policy constraints restrict features used in this Codelab:
discoveryengine.managed.disableCustomMcpServerConnector:- Restricts creation of data connectors that use a custom MCP server (
custom_mcp) as a data source (enforced by default).
- Restricts creation of data connectors that use a custom MCP server (
iam.managed.disableAccessPolicyBinding:- Restricts IAM v3 access policy bindings to resources (enforced by default).
discoveryengine.managed.allowedEgressFqdns:- Restricts outbound egress domains (
instance_uriFQDNs) for data connectors when VPC Service Controls (VPC-SC) is active or the project is listed in the organization'senforcedProjectsparameter.
- Restricts outbound egress domains (
discoveryengine.managed.allowedDataSources:- Restricts allowed data connector types (
dataSource) when VPC-SC is active or the project is listed in the organization'senforcedProjectsparameter.
- Restricts allowed data connector types (
Override any inherited organization policy restrictions on the project level by explicitly setting enforce: false.
Disable custom MCP constraint
# 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
Disable access policy constraint
# 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
Check and disable conditional data connector constraints
By default, discoveryengine.managed.allowedEgressFqdns and discoveryengine.managed.allowedDataSources only block connector creation if your project is inside a VPC Service Controls (VPC SC) perimeter or if an organization administrator has added your project to enforcedProjects.
First, inspect the effective policies on your project:
# 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~~ these constraints are enforced, to ensure they do not block custom_mcp connector setup in a VPC SC or policy-restricted organization, set enforce: false on both policies for your project:
# 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
IAM permissions
Grant the required IAM roles to your user account and the Compute Engine default service account used by Cloud Build:
- User account (
${USER_IDENTITY}):- Requires permissions to deploy and invoke Cloud Run services (
roles/run.admin,roles/run.invoker,roles/iam.serviceAccountUser), build container images (roles/cloudbuild.builds.editor), manage Gemini Enterprise (roles/discoveryengine.admin), and author Unified Access Policies (roles/iam.accessPolicyAdmin).
- Requires permissions to deploy and invoke Cloud Run services (
- Compute Engine default service account(
${PROJ_NO}-compute@developer.gserviceaccount.com):- Used by Cloud Build to stage source code in Cloud Storage (
roles/storage.admin), push images to Artifact Registry (roles/artifactregistry.writer), and write build logs (roles/logging.logWriter).
- Used by Cloud Build to stage source code in Cloud Storage (
Execute the following commands to assign the role bindings:
# 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"
Verify IAM permissions
Check for the six (6) role bindings on the user account.
# 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)"
Check for the three (3) role bindings on the default compute service account.
# 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)"
Verify service agent bindings (precautionary)
In a new project, Google Cloud automatically provisions the Agent Gateway service agent and grants it roles/agentgateway.serviceAgent when networkservices.googleapis.com is first enabled. If you are reusing an existing project where prior cleanup may have removed default service agent bindings, run the following commands as a fail-safe to ensure the identity and role binding are intact:
# 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"
This concludes the setup portion... next on to the Network section.
4. Network
In this section you will deploy a VPC network using custom mode with a dedicated /28 subnet (192.168.10.0/28) supporting the PSC network attachment for Agent Gateway network egress into the VPC network.
The PSC endpoint for Google APIs is deployed using a single /32global internal IPv4 address (172.16.20.20) to support private internal access to Google APIs and services. In this Codelab, Agent Gateway targets Cloud Run using the PSC endpoint by resolving the run.app. domain by Cloud DNS peering.
Create networks
Create a global VPC network.
# create vpc network
gcloud compute networks create vnet-${SLUG} --subnet-mode=custom
Create subnets for the Agent Gateway PSC network attachment:
# 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
Create firewall rules
Create a firewall policy to allow all egress traffic with logging enabled. This will be used to monitor traffic egressing from Agent Gateway to the VPC network. Cloud NGFW supports both Essentials and Standard tiers for network security and traffic monitoring.
# 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
Create PSC network attachment
Create a Private Service Connect (PSC) network attachment configured to automatically accept connections from Agent Gateway. The network attachment establishes the consumer VPC network side of the connection to securely link with the Agent Gateway producer side for outbound egress traffic. For additional information on subnet requirements and IP range specifications, see Configure VPC connectivity.
# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
--region=${REGION} \
--subnets=subnet-${REGION}-agw \
--connection-preference=ACCEPT_AUTOMATIC
Verify PSC network attachment
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}
Retrieve the resource URI of the PSC network attachment and store it in the PSC_NA_URI environment variable. This URI will be referenced in the Agent Gateway configuration (networkConfig.egress.networkAttachment) to provision the PSC Interface for network egress into the VPC network:
# 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}
Create PSC endpoint
A Private Service Connect (PSC) endpoint for Google APIs is used for Agent Gateway to establish private connectivity to the Cloud Run MCP server over an internal network path without exposing traffic to the public internet. Outbound tool calls egressing from Agent Gateway into the VPC network will resolve the target Cloud Run service URL (*.run.app) to this private endpoint IP address.
Reserve a global internal IPv4 address for the PSC endpoint. The IP address chosen must be a /32 address that does not overlap with any existing subnets in your VPC network:
# 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}
Create a PSC endpoint for Google APIs using the all-apis bundle, which includes 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
Verify PSC endpoint
# show psc endpoint details
gcloud compute forwarding-rules describe psc2gapis --global
Create DNS zone and records
Cloud DNS is used to enable Agent Gateway to communicate privately with the Cloud Run hosted MCP server. When Agent Gateway evaluates outbound tool requests targeting Cloud Run, it uses DNS peering (dnsPeeringConfig.domains) to resolve DNS queries for *.run.app using your private Cloud DNS zone associated with your VPC network. The private DNS record returns the query with the internal PSC endpoint IP address (172.16.20.20), allowing MCP tool requests to be routed through a private network path.
Create a private Cloud DNS managed zone for the run.app. domain:
# 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}
Create a wildcard DNS A record for *.run.app. pointing to the IP address of the PSC endpoint:
# create dns record
gcloud dns record-sets create "*.run.app." \
--zone=priv-zone-run \
--type=A \
--ttl=300 \
--rrdatas=${PSC_EP_IP}
Create a Cloud DNS policy to enable DNS query logging. DNS logging captures domain resolution requests originating from Agent Gateway within your VPC network, providing auditability and allowing you to verify that *.run.app tool requests correctly resolve to the internal PSC endpoint:
# create dns policy (logging)
gcloud dns policies create dns-policy-${SLUG} \
--description="dns logging for vnet-${SLUG}" \
--networks=vnet-${SLUG} \
--enable-logging
This concludes the network portion... next on to the Agent Gateway section.
5. Agent Gateway
Agent Gateway specifies registries for Agent Registry instances alongside the networkConfig fields that configure the PSC network attachment and DNS peering settings for private VPC connectivity:
registries: Associates the gateway with up to two Agent Registry instances: one regional (../locations/${REGION}) and one global (../locations/global). This integrates Agent Gateway with Agent Registry to resolve both regional deployments (such as Cloud Run MCP servers in${REGION}) and global resources (such as Gemini Enterprise agents and global endpoints) for fine-grained IAP v2 policy enforcement. Regional entries take precedence over global entries when resolving destination URLs.networkAttachment: Points to the PSC network attachment (psc-na-${REGION}-agw), connecting Agent Gateway into your VPC network for private egress.dnsPeeringConfig.domains: Configuresrun.app.so that DNS queries originating from Agent Gateway for Cloud Run services use DNS peering to resolve hostnames to the private Google APIs PSC endpoint IP address (172.16.20.20) configured in your Cloud DNS private zone.
Deploy Agent Gateway
Create and import the Agent Gateway configuration file.
# 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}
Verify Agent Gateway deployment
Confirm the Agent Registry and network configuration:
# show agent gateway registries and network config
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--format="yaml(registries,networkConfig)"
Expected output:
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}
Verify that the output displays the required configuration details:
registries: Lists the regional (${REGION}) Agent Registry URI associated with the gateway.egress.networkAttachment: Specifies the PSC network attachment URI for VPC egress.dnsPeeringConfig.domains: Containsrun.app.pointing totargetNetworkfor private domain resolution.
Inspect the PSC network attachment to confirm the gateway connection:
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="yaml(connectionEndpoints)"
Check there is an accepted connection endpoint:
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
Delegate authorization
Agent Gateway secures and governs outbound tool traffic using Authorization Policies (networksecurity.authzPolicies) integrated with Identity-Aware Proxy (IAP) Unified Access Policies (UAP).
While Agent Gateway supports basic inline ALLOW and DENY rules, enterprise environments require centralized, identity-centric governance. With IAM Unified Access Policies (or Access Policies), you manage egress access rules using standard IAM v3 access policies.
Fig 3. Authorization architecture
The authorization flow connects three components:
- Gateway Authorization Policy (
authzPolicy):- A regional resource targeting Agent Gateway.
- Configured with
policyProfile: REQUEST_AUTHZandaction: CUSTOMto route all outbound authorization checks to the IAP Authz Extension.
- IAP Service Extension (
authzExtension):- A regional resource that delegates request authorization to Identity-Aware Proxy (
iap.googleapis.com). - Evaluates policies in
ENFORCEmode using policy versionV2.
- A regional resource that delegates request authorization to Identity-Aware Proxy (
- IAM Unified Access Policy and Binding (
accessPolicy&policyBinding):- Global IAM v3 resources containing fine-grained access rules.
- Authenticates the SPIFFE principal identity of the calling agent, verifies the universal
iap.googleapis.com/resources.egressViaIAPpermission, and evaluates Common Expression Language (CEL) conditions against destination attributes.
Deploy authorization extension
Create a service-extensions authorization extension configuration that delegates authorization decisions to the IAP service:
# 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}