1. Введение
По мере того как корпоративные организации внедряют генеративный ИИ, архитектуры быстро развиваются от автономных монолитных чат-ботов до распределенных мультиагентных систем (Agent-to-Agent/A2A). В этих современных топологиях высокоуровневые агенты-оркестраторы координируют сложные бизнес-процессы, делегируя задачи специализированным агентам-исполнителям, серверам инструментов Model Context Protocol (MCP) и корпоративным базам данных в независимых облачных проектах Google Cloud.
Однако работа с мультиагентными системами в больших масштабах сопряжена с серьезными проблемами в области безопасности, управления и эксплуатации:
- Теневые агенты и разрастание инструментов. Когда команды разработчиков развертывают агентов в изолированных проектах без централизованного каталога, организации теряют видимость того, какие инструменты и субагенты существуют.
- Неконтролируемый исходящий трафик между проектами. Если у агентов есть прямые непроверенные сетевые маршруты, это создает риски кражи данных и обхода периметров безопасности.
- Ненадежные интеграции с жестко заданным кодом. Жесткое задание URL дочерних агентов и идентификаторов Reasoning Engine создает хрупкие зависимости, которые нарушаются при обновлениях или повторном развертывании.
- Отсутствие идентификации с минимальными привилегиями. Общие сервисные аккаунты не обеспечивают криптографическую неотказуемость на уровне отдельных экземпляров агентов.
Чтобы решить эти проблемы, Gemini Enterprise Agent Platform предоставляет единую плоскость управления и контроля подключений, состоящую из четырех основных компонентов:
- Шлюз агента (
networkservices.googleapis.com): управляемый региональный прокси-сервер для сети и применения правил. Работая в режиме исходящего трафикаAGENT_TO_ANYWHERE, он перехватывает исходящий трафик агента, делегирует оценку авторизации расширениям безопасности и маршрутизирует запросы по периметрам проекта. - Реестр агентов (
agentregistry.googleapis.com). Единый каталог сервисов предприятия. Он предоставляет централизованный проверенный каталог всех доступных инструментов, серверов MCP и одноранговых агентов в организации, обеспечивая динамическое автоматическое обнаружение во время выполнения без жестко закодированных конечных точек. - Agent Identity & IAP v2 Governance (
iap.googleapis.comиiam.googleapis.com). Криптографическая платформа для идентификации и доступа. Выполняющие агенты получают уникальные подтвержденные URN SPIFFE (principal://...). Исходящий трафик оценивается на соответствие централизованным унифицированным правилам доступа IAM (UAP/IAP v2), которые проверяют универсальное разрешениеiap.googleapis.com/resources.egressViaIAPс помощью условий каталога на языке Common Expression Language (CEL) (destination.agent_registry.*). - Agent Runtime (Reasoning Engines). Полностью управляемая бессерверная платформа для выполнения агентных приложений на основе Python со встроенными привязками конфигурации (
agent_gateway_config) к центральным шлюзам.
Бизнес-сценарий практической работы: закупка продуктов питания и напитков для нескольких проектов
В этой практической работе вы создадите и настроите реальную многопроектную экосистему закупок, охватывающую три отдельных облачных проекта Google Cloud:
- Проект централизованного управления (
PROJECT_GOVERNANCE). Принадлежит центральному ИТ-отделу и SecOps. В нем размещаются центральный шлюз агентов, центральный реестр агентов и унифицированные правила доступа IAM. - Проект Consumer Orchestrator (
PROJECT_CONCIERGE). Принадлежит команде по закупкам. В нем размещен агент Purchasing Concierge, который динамически находит поставщиков и направляет заказы клиентов. - Проект поставщика домена (
PROJECT_SELLERS). Принадлежит внешним или внутренним поставщикам, в нем размещены агент по продаже бургеров и агент по продаже пиццы.
Рис. 1. Архитектура централизованного управления несколькими проектами
Зачем нужно централизованное управление несколькими проектами?
В крупных организациях команды продуктов и специалисты по обработке данных создают ИИ-агентов в десятках независимых облачных проектов Google Cloud. Если предоставить каждой команде прямой контроль над регистрацией инструментов, маршрутами исходящего трафика и мерами безопасности, это приведет к бесконтрольному росту числа инструментов, несогласованности правил DLP, отсутствию мониторинга исходящего трафика VPC и фрагментации журналов аудита.
Централизованное управление несколькими проектами позволяет отделить создание правил от выполнения агентов.
- Центральный ИТ-отдел и SecOps разрабатывают правила безопасности, проверяют инструменты и отслеживают исходящий трафик в рамках одного проекта централизованного управления.
- Команды по продуктам и приложениям сосредотачиваются исключительно на бизнес-логике в своих независимых проектах среды выполнения агентов, напрямую связываясь с центральным шлюзом без операционных расходов на управление локальными VPC, межсоединениями или фрагментированными механизмами политик.
Рис. 2. Трехуровневая архитектура и границы управления межпроектными связями
Двухуровневая модель идентификации в единых правилах доступа
Когда агенты обмениваются данными через Central Agent Gateway, Identity-Aware Proxy (IAP v2) оценивает доступ на основе идентификатора агента вызывающей стороны – криптографически подтвержденного идентификатора на основе SPIFFE, автоматически выдаваемого контейнеру среды выполнения, – в соответствии с глобальными правилами доступа IAM:
- Уровень 1. Базовые API Google Cloud (общие, через
principalSet://в правиле 1). Авторизация исходящего трафика на уровне проекта, позволяющая всем средам выполнения агентов в дочерних проектах обращаться к стандартным API Google (aiplatform,iamcredentials,telemetry,agentregistry) для обнаружения, создания токенов и логического вывода. - Уровень 2. Бизнес-инструменты и сервисы A2A (точная настройка с помощью
principal://в правилах 2 и 3). Строгий доступ с минимальными привилегиями, привязанный к отдельным экземплярам Reasoning Engine и обеспечиваемый условиями Common Expression Language (CEL), которые нацелены на определенные зарегистрированные сервисы Agent Registry (destination.agent_registry.agent.name).
Что вы создаете
- Централизованный шлюз агента (
centralized-agw) вPROJECT_GOVERNANCE - Расширение сервиса авторизации IAP v2 и правила авторизации в строгом режиме принудительного применения (
failOpen: false) - Базовая унифицированная политика доступа IAM (
uap-rules.json) и привязка политики проекта - Разрешения IAM для агента сервиса, работающего с несколькими проектами (
ar_agw_cross_project_sa) - Общий центральный промежуточный сегмент Google Cloud Storage (GCS)
- Изолированные агенты по продаже бургеров и пиццы в
PROJECT_SELLERS - Агент Purchasing Concierge с динамическим автообнаружением REST в
PROJECT_CONCIERGE - Регистрация сервисов в центральном реестре агентов с URL mTLS для нескольких проектов
- Динамические обновления правил исходящего трафика IAP v2 с проверкой в реальном времени и аудитом Cloud Logging
Рис. 3. Пошаговое руководство по настройке
Что вы узнаете
- Как настроить разрешения IAM для сервисного агента, работающего с несколькими проектами, для централизованных шлюзов
- Как маршрутизировать исходящий трафик Agent Runtime через центральный шлюз агента в средах с несколькими проектами
- Как делегировать авторизацию Agent Gateway прокси-серверу с идентификацией (IAP v2) с помощью расширений сервисов (
iapPolicyVersion: "V2") - Как создавать и связывать единые правила доступа IAM с правилами Common Expression Language (CEL), регулирующими зарегистрированные целевые объекты Agent Registry (
destination.agent_registry.*) - Как убрать заданные в коде идентификаторы и URL агентов, используя автоматическое обнаружение во время выполнения в реестре агентов
- Как протестировать блокировку по периметру в рамках модели нулевого доверия (
HTTP 403 Forbidden) и проверить обновление правил в Cloud Logging
Что вам потребуется
- 3 облачных проекта Google Cloud с включенной оплатой:
PROJECT_GOVERNANCE– централизованное управление, шлюз, реестр и правила доступа IAM.PROJECT_CONCIERGE: агент-оркестратор консьержа по покупкамPROJECT_SELLERS: агенты по продаже бургеров и пиццы.
- Пользователь IAM или сервисный аккаунт с разрешениями
roles/ownerили администратора для всех трех проектов. - Организация Google Cloud (для сопоставления домена доверия SPIFFE).
- Google Cloud Shell или локальный компьютер с установленными
gcloudCLI,python(3.11+) иuv.
На этом вводная часть заканчивается. Далее мы перейдем к разделу Настройка и среда.
2. Настройка
Хотя эта архитектура охватывает три отдельных облачных проекта Google Cloud, вы можете выполнять все команды развертывания терминала, скачивания репозитория и промежуточные операции из одного терминала Cloud Shell, настроенного на PROJECT_GOVERNANCE. Каждый скрипт развертывания и команда gcloud явно нацелены на соответствующий целевой проект через флаги CLI (--project).
Для начала откройте командную строку проекта Google Cloud:
- Cloud Shell на странице
shell.cloud.google.com; - Локальный терминал с
gcloudCLI установленным.
Задайте контекст проекта
# set terminal project context to Central Governance Project
gcloud config set project SET_YOUR_GOVERNANCE_PROJECT_ID_HERE
# login to gcloud cli
gcloud auth login
# login for application default credentials
gcloud auth application-default login
Обновите gcloud CLI (рекомендуется)
# update gcloud components
gcloud components update --quiet
Как настроить переменные среды оболочки
Введите идентификаторы проекта.
# 1. Project Identifiers
export PROJECT_GOVERNANCE="SET_YOUR_GOVERNANCE_PROJECT_ID_HERE"
export PROJECT_CONCIERGE="SET_YOUR_CONCIERGE_PROJECT_ID_HERE"
export PROJECT_SELLERS="SET_YOUR_SELLERS_PROJECT_ID_HERE"
Эти переменные оболочки будут получены автоматически.
# 2. Regional & Gateway Settings
export REGION="us-central1"
export AGW_NAME="centralized-agw"
export UAP_POLICY_NAME="uap-policy-${AGW_NAME}"
export UAP_BINDING_NAME="uap-binding-${AGW_NAME}"
# 3. Retrieve Project Numbers
export PROJECT_NUMBER_GOVERNANCE=$(gcloud projects describe ${PROJECT_GOVERNANCE} --format="value(projectNumber)")
export PROJECT_NUMBER_CONCIERGE=$(gcloud projects describe ${PROJECT_CONCIERGE} --format="value(projectNumber)")
export PROJECT_NUMBER_SELLERS=$(gcloud projects describe ${PROJECT_SELLERS} --format="value(projectNumber)")
# 4. Obtain Organization ID
export ORG_ID=$(gcloud projects get-ancestors ${PROJECT_GOVERNANCE} --format="value(id, type)" | grep organization | awk '{print $1}')
# 5. Set Application Default Credentials (ADC) Quota Project
gcloud auth application-default set-quota-project ${PROJECT_GOVERNANCE}
echo "Governance Project: ${PROJECT_GOVERNANCE} (${PROJECT_NUMBER_GOVERNANCE})"
echo "Concierge Project: ${PROJECT_CONCIERGE} (${PROJECT_NUMBER_CONCIERGE})"
echo "Sellers Project: ${PROJECT_SELLERS} (${PROJECT_NUMBER_SELLERS})"
echo "Organization ID: ${ORG_ID}"
echo "UAP Policy Name: ${UAP_POLICY_NAME}"
echo "UAP Binding Name: ${UAP_BINDING_NAME}"
Создайте локальный каталог для файлов конфигурации
# create config folder
mkdir -p cfg
Как назначить роль администратора правил доступа для унифицированных правил доступа
# grant Access Policy Admin and Project IAM Admin to current user in Governance Project
for ROLE in "roles/iam.accessPolicyAdmin" "roles/resourcemanager.projectIamAdmin"; do
gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="user:$(gcloud config get-value account)" \
--role="${ROLE}" \
--condition=None
done
Как включить журналы доступа к данным Cloud Audit для IAP v2
По умолчанию Google Cloud отключает журналы аудита доступа к данным, чтобы предотвратить непредвиденные расходы на хранение. Поскольку IAP v2 передает решения об авторизации (granted=true и granted=false) в виде журналов аудита доступа к данным, включите ведение журналов ADMIN_READ, DATA_READ и DATA_WRITE для iap.googleapis.com в PROJECT_GOVERNANCE:
# 1. export current IAM policy for PROJECT_GOVERNANCE
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} \
--format=json > cfg/gov_iam_policy.json
# 2. append auditConfigs for iap.googleapis.com
python3 -c "
import json
with open('cfg/gov_iam_policy.json') as f:
policy = json.load(f)
audit_configs = [c for c in policy.get('auditConfigs', []) if c.get('service') != 'iap.googleapis.com']
audit_configs.append({
'service': 'iap.googleapis.com',
'auditLogConfigs': [
{'logType': 'ADMIN_READ'},
{'logType': 'DATA_READ'},
{'logType': 'DATA_WRITE'}
]
})
policy['auditConfigs'] = audit_configs
with open('cfg/gov_iam_policy.json', 'w') as f:
json.dump(policy, f, indent=2)
"
# 3. apply updated policy
gcloud projects set-iam-policy ${PROJECT_GOVERNANCE} cfg/gov_iam_policy.json
# 4. verify auditConfigs applied
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} --format="yaml(auditConfigs)"
Включите необходимые API Google Cloud
# enable google apis (agent platform & security bundle, part 1)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
gcloud services enable \
agentregistry.googleapis.com \
aiplatform.googleapis.com \
apphub.googleapis.com \
apptopology.googleapis.com \
cloudapiregistry.googleapis.com \
cloudtrace.googleapis.com \
compute.googleapis.com \
dataform.googleapis.com \
iam.googleapis.com \
agentidentity.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 \
--project=${PROJ}
done
# enable google apis (agent platform bundle, part 2)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
gcloud services enable \
securitycenter.googleapis.com \
saasservicemgmt.googleapis.com \
storage.googleapis.com \
telemetry.googleapis.com \
texttospeech.googleapis.com \
--project=${PROJ}
done
# enable google apis (foundational & agent runtime build bundle, part 3)
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
gcloud services enable \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
cloudresourcemanager.googleapis.com \
iamcredentials.googleapis.com \
serviceusage.googleapis.com \
run.googleapis.com \
orgpolicy.googleapis.com \
--project=${PROJ}
done
Проверьте, включен ли API во всех проектах
Если во всех трех проектах (PROJECT_GOVERNANCE, PROJECT_CONCIERGE и PROJECT_SELLERS) включены одни и те же API, это обеспечивает согласованность работы и предотвращает сбои при создании токенов во время выполнения, ошибки каталогизации схем и пропуски телеметрии.
Чтобы проверить паритет API во всех трех проектах, запустите в Cloud Shell следующий скрипт:
# validate that all required APIs are enabled across all 3 projects
python3 - << 'EOF'
import subprocess
import os
import sys
REQUIRED_APIS = [
"agentregistry.googleapis.com",
"aiplatform.googleapis.com",
"apphub.googleapis.com",
"apptopology.googleapis.com",
"cloudapiregistry.googleapis.com",
"cloudtrace.googleapis.com",
"compute.googleapis.com",
"dataform.googleapis.com",
"iam.googleapis.com",
"agentidentity.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",
"securitycenter.googleapis.com",
"saasservicemgmt.googleapis.com",
"storage.googleapis.com",
"telemetry.googleapis.com",
"texttospeech.googleapis.com",
"artifactregistry.googleapis.com",
"cloudbuild.googleapis.com",
"cloudresourcemanager.googleapis.com",
"iamcredentials.googleapis.com",
"serviceusage.googleapis.com",
"run.googleapis.com",
"orgpolicy.googleapis.com"
]
projects = {
"GOVERNANCE": os.environ.get("PROJECT_GOVERNANCE", ""),
"CONCIERGE": os.environ.get("PROJECT_CONCIERGE", ""),
"SELLERS": os.environ.get("PROJECT_SELLERS", "")
}
enabled = {}
for role, proj in projects.items():
if not proj:
print(f"Error: Environment variable for {role} is not set.")
sys.exit(1)
res = subprocess.run(
["gcloud", "services", "list", "--enabled", f"--project={proj}", "--format=value(config.name)"],
capture_output=True, text=True, check=True
)
enabled[role] = set(res.stdout.strip().splitlines())
print(f"\n{'API Name':<36} | {'GOVERNANCE':<12} | {'CONCIERGE':<12} | {'SELLERS':<12}")
print("-" * 78)
all_synced = True
for api in REQUIRED_APIS:
g_status = "ENABLED" if api in enabled["GOVERNANCE"] else "MISSING"
c_status = "ENABLED" if api in enabled["CONCIERGE"] else "MISSING"
s_status = "ENABLED" if api in enabled["SELLERS"] else "MISSING"
if "MISSING" in (g_status, c_status, s_status):
all_synced = False
print(f"{api:<36} | {g_status:<12} | {c_status:<12} | {s_status:<12}")
print("-" * 78)
if all_synced:
print("✅ All 29 required APIs are ENABLED and synchronized across all three projects.\n")
else:
print("❌ Discrepancies detected. Please re-run the enablement commands for missing services.\n")
sys.exit(1)
EOF
Пример результата проверки:
Вы увидите, что все API включены.
✅ All 30 required APIs are ENABLED and synchronized across all three projects.
Настройка правил организации
Стандартные правила организации Google Cloud применяют ограничения, которые запрещают привязку правил доступа IAM v3 к ресурсам (constraints/iam.managed.disableAccessPolicyBinding).
Переопределите все унаследованные ограничения правил организации на уровне проекта, явно задав для enforce: false значение allow.
# disable iam v3 constraint (allow v3 access policies)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJECT_NUMBER_GOVERNANCE}/policies/iam.managed.disableAccessPolicyBinding
spec:
rules:
- enforce: false
EOF
# verify org policy constraints on project
gcloud org-policies describe iam.managed.disableAccessPolicyBinding \
--project=${PROJECT_GOVERNANCE} --effective
На этом настройка завершена. Перейдите к разделу Регистрация основных API Google.
3. Реестр агентов
Зарегистрировать сервис конечных точек основных API Google
Для Agent Gateway требуется, чтобы URL API Google были зарегистрированы в Central Agent Registry. Это позволит агентам, настроенным с помощью agent_gateway_config, безопасно направлять исходящий трафик в основные бэкенд-сервисы Google Cloud, такие как aiplatform, IAM Credentials и Telemetry.
Создать core-gapi-services в реестре агентов
# register core google api endpoints in agent registry with standard and :443 port variants
gcloud agent-registry services create core-gapi-services \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--display-name="gapi.core.services" \
--description="Core Google Cloud APIs and Service Endpoints" \
--endpoint-spec-type=no-spec \
--interfaces=protocolBinding=JSONRPC,url=https://telemetry.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://telemetry.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://aiplatform.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://aiplatform.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://aiplatform.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://aiplatform.mtls.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://cloudresourcemanager.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://cloudresourcemanager.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://cloudresourcemanager.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://cloudresourcemanager.mtls.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.mtls.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://agentregistry.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://agentregistry.mtls.googleapis.com \
--interfaces=protocolBinding=JSONRPC,url=https://agentregistry.googleapis.com:443 \
--interfaces=protocolBinding=JSONRPC,url=https://agentregistry.mtls.googleapis.com:443
Идентификатор ресурса конечной точки Capture Core API
# capture the underlying Agent Registry endpoint ID
export ENDPOINT_ID=$(gcloud agent-registry services describe core-gapi-services \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--format="value(registryResource)" | awk -F'/' '{print $NF}')
echo "Core APIs Endpoint ID: ${ENDPOINT_ID}"
Разница между principalSet и principal в идентификации агента
В Google Cloud IAM и Gemini Enterprise Agent Platform идентификаторы машин, выданные выполняющимся контейнерам агентов, используют криптографически подтвержденные URN SPIFFE, которые оцениваются Identity-Aware Proxy (IAP v2). При настройке единых правил доступа IAM вы можете выбрать в качестве цели либо один определенный principal, либо principalSet на основе атрибутов:
Параметр |
|
|
Синтаксис IAM |
|
|
Детализация | Точный (на уровне экземпляра). Идентифицирует один конкретный экземпляр контейнера Reasoning Engine. | Общие (на уровне проекта). Позволяют найти все механизмы рассуждения, у которых совпадает атрибут проекта. |
Шаблон URN |
|
|
Пример использования на платформе агентов | Уровень 2 (бизнес-инструменты и A2A). Авторизация определенных агентов-оркестраторов для вызова инструментов целевого домена (например, помощник по покупкам $\rightarrow$ продавец бургеров). | Уровень 1 (базовая инфраструктура). Предоставление всем агентам в проекте доступа к исходящему трафику для Google Cloud API ( |
Влияние на жизненный цикл | Если агент удален и создан заново, для его нового идентификатора Engine ID требуется обновленная привязка правила IAM. | Автоматически применяется к новым агентам, развернутым в этом проекте, без дополнительных обновлений IAM. |
Декларативное управление с помощью унифицированных правил доступа (UAP/IAP v2)
В устаревшей версии IAP v1 правила исходящего трафика прикреплялись непосредственно к отдельным ресурсам реестра агентов с помощью gcloud beta iap web add-iam-policy-binding. В IAP v2 и унифицированных правилах доступа привязки для отдельных ресурсов заменены едиными централизованными правилами доступа IAM (cfg/uap-rules.json).
Базовая авторизация исходящего трафика для core-gapi-services будет настроена как Правило 1 в Единых правилах доступа в разделе 5. Это позволит убедиться, что для всех контейнеров агентов перед развертыванием настроены базовые маршруты исходящего трафика.
Дополнительные технические сведения об идентификаторах субъектов и механизмах Workload Identity можно найти в следующих статьях:
- Google Cloud IAM: идентификаторы и наборы субъектов
- Как работает идентификация агентов
- Как настроить унифицированные правила доступа IAM для Agent Gateway
На этом регистрация конечных точек основных API завершена. Перейдите к разделу Развертывание централизованного шлюза агента.
4. Шлюз агента
Развертывание централизованного шлюза агента
Разверните централизованный шлюз Agent Gateway (centralized-agw) в режиме исходящего трафика AGENT_TO_ANYWHERE в проекте $PROJECT_GOVERNANCE.
Определите манифест конфигурации шлюза
Создайте cfg/${AGW_NAME}.yaml для управления исходящим трафиком:
# generate agent gateway config yaml
cat > cfg/${AGW_NAME}.yaml << EOF
name: ${AGW_NAME}
protocols:
- MCP
googleManaged:
governedAccessPath: AGENT_TO_ANYWHERE
registries:
- "//agentregistry.googleapis.com/projects/${PROJECT_GOVERNANCE}/locations/${REGION}"
EOF
Импорт конфигурации шлюза агента
# import and create agent gateway
gcloud network-services agent-gateways import ${AGW_NAME} \
--source="cfg/${AGW_NAME}.yaml" \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Проверьте сведения о шлюзе агента
# show agent gateway status
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Пример результата:
agentGatewayCard:
mtlsEndpoint: projects/${AGW_TP_ID}/regions/us-central1/serviceAttachments/unitkind1-swp-mtls-psc-sa
rootCertificates:
- |
-----BEGIN CERTIFICATE-----
MIIDwzCCAqugAwIBAgITNQuWGopdOZaHdcK7r7AYFhonqDANBgkqhkiG9w0BAQsF
...
-----END CERTIFICATE-----
serviceExtensionsServiceAccount: service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com
createTime: 'YYYY-MM-DDT12:34:56.789098765Z'
googleManaged:
governedAccessPath: AGENT_TO_ANYWHERE
name: projects/${PROJECT_GOVERNANCE}/locations/us-central1/agentGateways/centralized-agw
protocols:
- MCP
registries:
- //agentregistry.googleapis.com/projects/${PROJECT_GOVERNANCE}/locations/us-central1
updateTime: 'YYYY-MM-DDT12:34:56.789098765Z'
На этом развертывание шлюза завершено. Перейдите к разделу Настройка авторизации.
5. Авторизация
Как настроить авторизацию Agent Gateway и базовую платформу UAP
Agent Gateway защищает исходящий трафик инструментов и агентов и управляет им с помощью правил авторизации (networksecurity.authzPolicies), интегрированных с унифицированными правилами доступа (UAP) Identity-Aware Proxy (IAP v2).
Обзор архитектуры авторизации
Рис. 4. Обзор архитектуры авторизации
Архитектура авторизации состоит из трех взаимосвязанных уровней:
- Расширение сервиса IAP (
authzExtension). Региональный ресурс, настроенный с помощьюservice: iap.googleapis.com,metadata: iapPolicyVersion: "V2"иfailOpen: falseдля строгого соблюдения принципа нулевого доверия по периметру. - Gateway Authorization Policy (
authzPolicy) – региональный ресурс, который направляет трафик на Agent Gateway с помощьюpolicyProfile: REQUEST_AUTHZиaction: CUSTOM, а проверки авторизации – на расширение авторизации IAP. - IAM Unified Access Policy & Binding (
accessPolicy&policyBinding): глобальный ресурс IAM v3, оцениваемый IAP. Она проверяет универсальное разрешениеiap.googleapis.com/resources.egressViaIAPна соответствие идентификаторам SPIFFE вызывающего абонента и условиям каталога CEL.
Шаг 1. Создайте и импортируйте расширение авторизации IAP v2
Создайте манифест расширения сервиса с iapPolicyVersion: "V2" и failOpen: false в строгом режиме ENFORCE:
# create authz extension config file in ENFORCE mode
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
Импортируйте расширение Authz:
# import IAP v2 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} \
--project=${PROJECT_GOVERNANCE}
Убедитесь, что расширение Authz активно:
# describe authz extension
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Пример результата:
createTime: 'YYYY-MM-DDT12:34:56.789098765Z'
failOpen: false
metadata:
iapPolicyVersion: V2
name: projects/${PROJECT_GOVERNANCE}/locations/us-central1/authzExtensions/centralized-agw-svc-ext-authz-iap
service: iap.googleapis.com
timeout: 1s
Шаг 2. Создайте и импортируйте правила авторизации шлюза
Создайте конфигурацию правил авторизации, которая подключается к шлюзу агента и делегирует проверку запросов расширению авторизации IAP:
# create authz policy manifest
cat > cfg/${AGW_NAME}-authz-policy-profile-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-profile-iap
target:
resources:
- "projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
authzExtension:
resources:
- "projects/${PROJECT_GOVERNANCE}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap"
EOF
Импортируйте правило авторизации:
# import authz policy
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-profile-iap \
--source=cfg/${AGW_NAME}-authz-policy-profile-iap.yaml \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Проверьте активное правило авторизации:
# describe authz policy
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-profile-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Шаг 3. Создайте начальное единое правило доступа (правило 1: основные API Google)
Создайте cfg/uap-rules.json с правилом 1, разрешающим трем principalSet проекта доступ к core-gapi-services:
# create initial unified access policy rules manifest
cat > cfg/uap-rules.json << EOF
[
{
"description": "Rule 1: Allow agent runtimes across all 3 projects to reach Core Google APIs",
"effect": "ALLOW",
"principals": [
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_GOVERNANCE}",
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}",
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.resource_type == 'ENDPOINT' && ( \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/core-gapi-services' || \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}' || \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}')"
}
}
}
]
EOF
Шаг 4. Создайте и привяжите правило доступа IAM
Создайте глобальное правило доступа IAM:
# create global IAM access policy
gcloud iam access-policies create ${UAP_POLICY_NAME} \
--details-rules=cfg/uap-rules.json \
--project=${PROJECT_GOVERNANCE} \
--location=global
Привяжите правило доступа к PROJECT_GOVERNANCE:
# bind access policy to governance project
gcloud iam policy-bindings create ${UAP_BINDING_NAME} \
--policy="projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/${UAP_POLICY_NAME}" \
--target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJECT_GOVERNANCE}" \
--project=${PROJECT_GOVERNANCE} \
--location=global
Убедитесь, что привязка правил активна:
# verify policy binding
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global
Пример результата:
name: projects/${PROJECT_GOVERNANCE}/locations/global/policyBindings/uap-binding-centralized-agw
policy: projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/uap-policy-centralized-agw
policyKind: ACCESS_POLICY
target:
resource: //cloudresourcemanager.googleapis.com/projects/${PROJECT_GOVERNANCE}
Исходящий трафик Foundational Google Cloud API теперь безопасно авторизуется во всех трех проектах в строгом режиме ENFORCE.
На этом настройка авторизации шлюза завершена. Перейдите к разделу Настройка разрешений IAM для нескольких проектов.
6. IAM для нескольких проектов
Как настроить разрешения IAM для нескольких проектов
В этой топологии с несколькими проектами среды выполнения агентов находятся в дочерних проектах (PROJECT_CONCIERGE и PROJECT_SELLERS), а центральный шлюз агента и реестр агентов – в PROJECT_GOVERNANCE.
Поскольку проекты Google Cloud представляют собой изолированные периметры безопасности, доступ между проектами должен быть явно предоставлен на двух операционных уровнях:
- Уровень управления (время развертывания). При развертывании контейнера агента, настроенного с помощью
--agent-gateway-config, агент сервиса среды выполнения агента (service-) дочернего проекта должен подключить контейнер к центральному шлюзу. Мы создаем минимальную специальную роль (@gcp-sa-aiplatform.iam.gserviceaccount.com ar_agw_cross_project_sa), предоставляющую разрешенияnetworkservices.agentGateways.use,getиoperations.getвPROJECT_GOVERNANCE. - Уровень данных (выполнение во время работы):
- Обнаружение каталога. Идентификаторам дочерних узлов требуется роль
roles/agentregistry.viewerвPROJECT_GOVERNANCE, чтобы динамически разрешать конечные точки целевых агентов. - Целевой вызов. Агенту Concierge требуется
roles/aiplatform.userвPROJECT_SELLERS, чтобы выполнять запросы к механизмам рассуждения продавца.
- Обнаружение каталога. Идентификаторам дочерних узлов требуется роль
Создание специальной роли IAM в PROJECT_GOVERNANCE
# create custom role in central governance project
gcloud iam roles create ar_agw_cross_project_sa \
--project=${PROJECT_GOVERNANCE} \
--title="Runtime Agent Gateway Cross-Project SA" \
--description="Custom role for cross-project service agents to access Central Agent Gateway" \
--permissions="networkservices.agentGateways.get,networkservices.agentGateways.use,networkservices.operations.get" \
--stage="GA"
Назначение настраиваемой роли сервисным агентам Agent Runtime
# 1. ensure aiplatform service identities are provisioned across all projects
for PROJ in ${PROJECT_GOVERNANCE} ${PROJECT_CONCIERGE} ${PROJECT_SELLERS}; do
gcloud beta services identity create --service=aiplatform.googleapis.com --project=${PROJ}
done
# 2. derive aiplatform service agent emails
export CONCIERGE_AI_SA="service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com"
export CONCIERGE_RE_SA="service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
export CONCIERGE_COMPUTE_SA="${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com"
export SELLERS_AI_SA="service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform.iam.gserviceaccount.com"
export SELLERS_RE_SA="service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
export SELLERS_COMPUTE_SA="${PROJECT_NUMBER_SELLERS}-compute@developer.gserviceaccount.com"
# 3. grant custom role & network viewer to Concierge and Sellers Service Agents
for SA in ${CONCIERGE_AI_SA} ${SELLERS_AI_SA}; do
gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="serviceAccount:${SA}" \
--role="projects/${PROJECT_GOVERNANCE}/roles/ar_agw_cross_project_sa" \
--condition=None
gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="serviceAccount:${SA}" \
--role="roles/networkservices.viewer" \
--condition=None
done
# 4. grant agent registry viewer on Governance Project for dynamic autodiscovery
for MEMBER in "serviceAccount:${CONCIERGE_AI_SA}" "serviceAccount:${CONCIERGE_RE_SA}" "serviceAccount:${CONCIERGE_COMPUTE_SA}" "serviceAccount:${SELLERS_AI_SA}" "serviceAccount:${SELLERS_RE_SA}" "serviceAccount:${SELLERS_COMPUTE_SA}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}"; do
gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="${MEMBER}" \
--role="roles/agentregistry.viewer" \
--condition=None
done
# 5. grant agent project viewer on Governance Project for dynamic autodiscovery
for SA in ${CONCIERGE_COMPUTE_SA} ${CONCIERGE_AI_SA}; do
gcloud projects add-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="serviceAccount:${SA}" \
--role="roles/viewer" \
--condition=None
done
# 6. grant aitplatform user on Sellers project to Concierge for cross-project A2A invocation
for MEMBER in "serviceAccount:${CONCIERGE_AI_SA}" "serviceAccount:${CONCIERGE_RE_SA}" "serviceAccount:${CONCIERGE_COMPUTE_SA}" "principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}"; do
gcloud projects add-iam-policy-binding ${PROJECT_SELLERS} \
--member="${MEMBER}" \
--role="roles/aiplatform.user" \
--condition=None
done
На этом настройка IAM для нескольких проектов завершена. Перейдите к разделу Развертывание агентов Seller и Concierge.
7. Agent Runtime
Развертывание агентов Seller и Concierge
База кода мультиагентного приложения и скрипты развертывания, используемые в этой практической работе, хранятся в удаленном хранилище Google Cloud на GitHub. Выполните следующие действия, чтобы клонировать репозиторий локально, скопировать необходимые файлы в структуру текущего рабочего каталога, очистить временные файлы и установить зависимости с помощью uv.
Получение удаленных артефактов
# clone remote repository to temp local dir
git clone https://github.com/GoogleCloudPlatform/cloud-networking-solutions.git ./temp_agw_multiproject
# copy multi-agent application files to current working directory
cp -r temp_agw_multiproject/codelabs/agw-multiproject ./cross-project-multiagent
# remove temporary directory
rm -rf temp_agw_multiproject
# install dependencies
uv sync --directory ./cross-project-multiagent
Создание общего центрального промежуточного сегмента
# create shared central staging bucket
gcloud storage buckets create gs://${PROJECT_GOVERNANCE}-shared-staging \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION}
# grant cross-project read/write access to runtime service agents
gcloud storage buckets add-iam-policy-binding gs://${PROJECT_GOVERNANCE}-shared-staging \
--member="serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
--role="roles/storage.objectAdmin"
gcloud storage buckets add-iam-policy-binding gs://${PROJECT_GOVERNANCE}-shared-staging \
--member="serviceAccount:service-${PROJECT_NUMBER_SELLERS}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
--role="roles/storage.objectAdmin"
Как работает привязка шлюза агента между проектами
На этом шаге вы развернете агентов продавца в дочернем проекте (PROJECT_SELLERS) и настроите их так, чтобы исходящий трафик направлялся через центральный шлюз агентов в PROJECT_GOVERNANCE.
# !-- for example purposes -- NOT a command to execute --!
# snippet from deploy_burger.py
burger_config = {
"staging_bucket": staging_bucket_uri,
"gcs_dir_name": "burger_agent",
"display_name": "burger-seller-agent-adk",
"identity_type": "AGENT_IDENTITY",
"agent_gateway_config": {
"agent_to_anywhere_config": {
"agent_gateway": f"projects/{args.governance_project}/locations/{args.region}/agentGateways/{args.gateway}"
}
},
}
deployed_burger = client.agent_engines.create(agent=burger_playground, config=burger_config)
Поскольку правило 1 было установлено в нашей единой политике доступа раньше, запросы на инициализацию контейнера к Google Cloud API разрешены через шлюз без прерывания.
Развертывание агентов по продаже бургеров и пиццы в PROJECT_SELLERS
# 1. deploy Burger Seller Agent to PROJECT_SELLERS
uv run --directory ./cross-project-multiagent python deploy_burger.py \
--project=${PROJECT_SELLERS} \
--region=${REGION} \
--governance-project=${PROJECT_GOVERNANCE} \
--gateway=projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}
# 2. deploy Pizza Seller Agent to PROJECT_SELLERS
uv run --directory ./cross-project-multiagent python deploy_pizza.py \
--project=${PROJECT_SELLERS} \
--region=${REGION} \
--governance-project=${PROJECT_GOVERNANCE} \
--gateway=projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agentGateways/${AGW_NAME}
Проверка маршрутизации шлюза продавца
# retrieve deployed seller reasoning engine IDs
export BURGER_ENGINE_ID=$(grep BURGER_SELLER_AGENT_ID cross-project-multiagent/burger_agent.env | awk -F'/' '{print $NF}')
export PIZZA_ENGINE_ID=$(grep PIZZA_SELLER_AGENT_ID cross-project-multiagent/pizza_agent.env | awk -F'/' '{print $NF}')
echo "Burger Engine ID: ${BURGER_ENGINE_ID}"
echo "Pizza Engine ID: ${PIZZA_ENGINE_ID}"
# inspect runtime configuration for both Seller Agents
for ENGINE_ID in ${BURGER_ENGINE_ID} ${PIZZA_ENGINE_ID}; do
curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/${REGION}/reasoningEngines/${ENGINE_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
| jq '{displayName: .displayName, identityType: .spec.identityType, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'
done
Разверните помощника по покупкам в PROJECT_CONCIERGE
# deploy Purchasing Concierge to PROJECT_CONCIERGE
uv run --directory ./cross-project-multiagent python deploy_concierge_adk.py \
--project=${PROJECT_CONCIERGE} \
--region=${REGION} \
--staging-bucket=gs://${PROJECT_GOVERNANCE}-shared-staging \
--gateway-name=${AGW_NAME} \
--gateway-project=${PROJECT_GOVERNANCE}
Проверка маршрутизации шлюза покупок
# retrieve Concierge engine ID
export CONCIERGE_ENGINE_ID=$(grep CONCIERGE_AGENT_ID cross-project-multiagent/concierge_agent.env | awk -F'/' '{print $NF}')
echo "Concierge Engine ID: ${CONCIERGE_ENGINE_ID}"
# inspect runtime configuration for Purchasing Concierge
curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "Content-Type: application/json" \
| jq '{displayName: .displayName, identityType: .spec.identityType, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'
В выходных данных должны быть указаны идентификатор среды выполнения агента Concierge, проект и привязка к Agent Gateway проекта Governance.
{
"displayName": "purchasing-concierge-adk",
"identityType": "AGENT_IDENTITY",
"effectiveIdentity": "agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_CONCIERGE}/locations/us-central1/reasoningEngines/${CONCIERGE_ENGINE_ID}",
"agentGatewayConfig": {
"agentToAnywhereConfig": {
"agentGateway": "projects/${PROJECT_GOVERNANCE}/locations/us-central1/agentGateways/centralized-agw"
}
}
}
На этом развертывание агентов завершено. Перейдите к разделу Регистрация агентов в центральном реестре.
8. Реестр для нескольких проектов
Регистрация агентов в центральном реестре агентов
Зарегистрируйте всех трех агентов в Центральном реестре агентов в регионе PROJECT_GOVERNANCE, используя региональные конечные точки mTLS для нескольких проектов и числовые номера проектов.
Как зарегистрировать сервисы в качестве агентов, не относящихся к типу A2A, в реестре агентов
# 1. register Burger Seller Agent
gcloud agent-registry services create burger-seller-agent \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--display-name="Burger Seller Agent" \
--description="Specialist agent that sells burgers and fries" \
--agent-spec-type=no-spec \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${BURGER_ENGINE_ID}:query
# 2. register Pizza Seller Agent
gcloud agent-registry services create pizza-seller-agent \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--display-name="Pizza Seller Agent" \
--description="Specialist agent that sells pizzas and pasta" \
--agent-spec-type=no-spec \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_SELLERS}/locations/${REGION}/reasoningEngines/${PIZZA_ENGINE_ID}:query
# 3. register Purchasing Concierge Agent
gcloud agent-registry services create purchasing-concierge-adk \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--display-name="Purchasing Concierge Agent" \
--description="Orchestrator concierge agent that routes purchasing requests" \
--agent-spec-type=no-spec \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query \
--interfaces=protocolBinding=JSONRPC,url=https://${REGION}-aiplatform.mtls.googleapis.com:443/v1beta1/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}:query
Регистрационные идентификаторы базовых агентов
# capture underlying Agent Registry Agent UUIDs
export BURGER_AGENT_ID=$(gcloud agent-registry services describe burger-seller-agent --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')
export PIZZA_AGENT_ID=$(gcloud agent-registry services describe pizza-seller-agent --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')
export CONCIERGE_AGENT_ID=$(gcloud agent-registry services describe purchasing-concierge-adk --project=${PROJECT_GOVERNANCE} --location=${REGION} --format="value(registryResource)" | awk -F'/' '{print $NF}')
echo "Burger Agent ID: ${BURGER_AGENT_ID}"
echo "Pizza Agent ID: ${PIZZA_AGENT_ID}"
echo "Concierge Agent ID: ${CONCIERGE_AGENT_ID}"
На этом настройка реестра завершена. Перейдите к разделу Настройка правил исходящего трафика A2A.
9. Правила UAP
Как настроить правила исходящего трафика A2A в единых правилах доступа
В архитектуре Agent Gateway Запрет по умолчанию в строгом режиме ENFORCE:
- Правило 1 (базовые API Google Cloud). Позволяет контейнерам агентов во всех трех проектах подключаться к
core-gapi-services. - Правило 2 (Burger Seller Agent: ALLOW). Разрешает экземпляру Purchasing Concierge Agent вызывать Burger Seller Agent.
- Агент по продаже пиццы (ЗАПРЕЩЕНО по умолчанию). Намеренно не включен в правила. В режиме
ENFORCE(failOpen: false) любая попытка Concierge вызвать Pizza Seller будет немедленно прервана на периметре шлюза с ошибкойHTTP 403 Forbidden.
Сформулируйте личность агента Concierge
# formulate the exact SPIFFE machine identity for the Concierge Agent
export CONCIERGE_SPIFFE_PRINCIPAL="principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}"
echo "Concierge SPIFFE Principal: ${CONCIERGE_SPIFFE_PRINCIPAL}"
Обновление манифеста с правилами 1 и 2
Чтобы безопасно обновить правила доступа, не затронув существующие, определите полный консолидированный манифест, содержащий правило 1 (основные API Google) и правило 2 (агент Burger Seller):
# create consolidated policy manifest with Rule 1 and Rule 2
cat > cfg/uap-rules-consolidated.json << EOF
[
{
"description": "Rule 1: Allow agent runtimes across all 3 projects to reach Core Google APIs",
"effect": "ALLOW",
"principals": [
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_GOVERNANCE}",
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}",
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.resource_type == 'ENDPOINT' && ( \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/core-gapi-services' || \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}' || \
destination.agent_registry.endpoint.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/endpoints/${ENDPOINT_ID}')"
}
}
},
{
"description": "Rule 2: Allow Purchasing Concierge to invoke Burger Seller Agent via Central Gateway",
"effect": "ALLOW",
"principals": [
"${CONCIERGE_SPIFFE_PRINCIPAL}",
"principal://agents.global.org-${ORG_ID}.system.id.goog/attribute.agentIdentity/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}",
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.agentIdentity/projects/${PROJECT_NUMBER_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.resource_type == 'AGENT' && ( \
destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/burger-seller-agent' || \
destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/${BURGER_AGENT_ID}' || \
destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/agents/${BURGER_AGENT_ID}')"
}
}
}
]
EOF
Применить обновленные правила доступа
Примените манифест объединенных правил декларативно с помощью --details-rules:
# update IAM access policy with consolidated manifest (Rule 1 + Rule 2)
gcloud iam access-policies update ${UAP_POLICY_NAME} \
--details-rules=cfg/uap-rules-consolidated.json \
--project=${PROJECT_GOVERNANCE} \
--location=global
Проверьте сведения о правиле доступа IAM
# inspect updated access policy
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global
Пример результата:
details:
rules:
- conditions:
iap.googleapis.com:
expression: destination.is_registered == true && destination.agent_registry.resource_type
== 'ENDPOINT' && (destination.agent_registry.endpoint.name == 'projects/${PROJECT_GOVERNANCE}/locations/us-central1/endpoints/core-gapi-services'
|| destination.agent_registry.endpoint.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/us-central1/endpoints/${ENDPOINT_ID}')
description: 'Rule 1: Allow agent runtimes across all 3 projects to reach Core
Google APIs'
effect: ALLOW
operation:
permissions:
- iap.googleapis.com/resources.egressViaIAP
principals:
- principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_GOVERNANCE}
- principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}
- principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_SELLERS}
- conditions:
iap.googleapis.com:
expression: (destination.is_registered == true) && (destination.agent_registry.resource_type
== 'AGENT') && (destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/us-central1/agents/burger-seller-agent'
|| destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/us-central1/agents/${BURGER_AGENT_ID}')
description: 'Rule 2: Allow Purchasing Concierge to invoke Burger Seller Agent
via Central Gateway'
effect: ALLOW
operation:
permissions:
- iap.googleapis.com/resources.egressViaIAP
principals:
- principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}/locations/us-central1/reasoningEngines/${CONCIERGE_ENGINE_ID}
name: projects/${PROJECT_GOVERNANCE}/locations/global/accessPolicies/uap-policy-centralized-agw
На этом настройка правил завершена. Перейдите к разделу Тестирование и проверка правил управления.
10. Проверка правил
Тестирование и проверка правил управления с помощью Cloud Logging
В этом разделе вы протестируете межпроектные взаимодействия между агентами в Agent Runtime AI Playground, понаблюдаете за реальной блокировкой периметра HTTP 403 Forbidden в строгом режиме ENFORCE, измените единые правила доступа в реальном времени и проверите немедленное одобрение заказа.
Шаг 1. Откройте Agent Runtime ИИ-студию в PROJECT_CONCIERGE
- Откройте консоль Google Cloud.
- На панели выбора проекта вверху перейдите к проекту
PROJECT_CONCIERGE. - В меню навигации выберите Agent Platform (Платформа агентов) > Agents (Агенты) > Deployments (Развертывания).
- Нажмите на значок
purchasing-concierge-adk. - Выберите Playground (Игровая площадка), чтобы открыть интерактивный чат в правой части экрана.
Шаг 2. Тестирование заказа бургера (соответствие правилу 2 -> 200 OK)
В окне чата Playground введите следующий запрос:
I would like 10 Classic Cheeseburgers. Place this order now.
Если требуется подтверждение, отправь следующий ответ:
Confirmed, please place the order.
Вы также можете выполнить проверку программно из Cloud Shell или терминала:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input={'message': 'I would like 22 Spicy Cajun Burgers please. Place this order now.'})
print(response)
"
Если требуется подтверждение, используйте следующую команду:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"
Что происходит за кулисами:
- Динамическое обнаружение. Во время запуска сеанса Purchasing Concierge запросил у Central Agent Registry в
PROJECT_GOVERNANCE(черезcore-gapi-servicesчерез Agent Gateway, авторизованный правилом 1) региональную конечную точку mTLS дляburger-seller-agent. - Определение намерения и вызов A2A. Gemini в помощнике по покупкам анализирует намерение заказать еду и вызывает агента по продаже бургеров через исходящий RPC-запрос к
https://${REGION}-aiplatform.mtls.googleapis.com/.../reasoningEngines/${BURGER_ENGINE_ID}. - Перехват шлюза и распространение SPIFFE. Исходящий трафик перехватывается
agent_gateway_configи направляется в центральный шлюз агента вPROJECT_GOVERNANCE, неся криптографическую идентификацию SPIFFE Concierge (principal://...). - Оценка правил IAP v2. Центральный шлюз агента вызывает расширение авторизации IAP (
authzExtension). IAP v2 оценивает правило 2 в единых правилах доступа IAM. Поскольку вызывающий абонент соответствует${CONCIERGE_SPIFFE_PRINCIPAL}, а цель –burger-seller-agent, IAP возвращаетALLOW(granted: true). - Выполнение в разных проектах. Шлюз агента передает авторизованный запрос в другой проект –
PROJECT_SELLERS, где механизм рассуждений Burger Seller обрабатывает заказ и возвращает подтверждение.
Ожидаемый ответ:
Your order for 10 Classic Cheeseburger(s) has been placed!
Here is a summary of your order:
- 10x Classic Cheeseburger @ IDR 85,000/each = IDR 850,000
Total: IDR 850,000
Your Order ID is: e8f9c732-f347-4cc4-acff-cfe09ccbeddd
Шаг 3. Проверьте журналы аудита Agent Gateway и IAP v2 (HTTP 200/ALLOWED)
Запрос журналов запросов шлюза агента в PROJECT_GOVERNANCE:
# query Agent Gateway logs for successful 200 OK requests
gcloud logging read "
logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
AND jsonPayload.authzPolicyInfo.result=\"ALLOWED\"
" \
--project="${PROJECT_GOVERNANCE}" \
--limit=10 \
--format="table(
timestamp.date('%H:%M:%S'):label=TIME,
httpRequest.requestMethod:label=METHOD,
httpRequest.status:label=STATUS,
jsonPayload.authzPolicyInfo.result:label=AUTHZ,
httpRequest.requestUrl:label=URL
)"
Журналы должны фиксировать исходящий трафик, поступающий из обоих дочерних проектов (PROJECT_CONCIERGE и PROJECT_SELLERS), с полями исходящего трафика для вызовов Gemini (generateContent), телеметрии Cloud Trace (/v1/traces) и поиска учетных данных IAM, которые прозрачно перехватываются и авторизуются правилом 1 (core-gapi-services).
Чтобы проверить версию правил POLICY_VERSION_V2, запросите журналы доступа к данным Cloud Audit для IAP v2:
# query IAP v2 audit logs with shortened principal and resource fields
gcloud logging read "
logName=\"projects/${PROJECT_GOVERNANCE}/logs/cloudaudit.googleapis.com%2Fdata_access\"
AND protoPayload.serviceName=\"iap.googleapis.com\"
" \
--project="${PROJECT_GOVERNANCE}" \
--limit=5 \
--format="table(
timestamp.date('%H:%M:%S'):label=TIME,
protoPayload.authenticationInfo.principalSubject.sub('\.global\..*\/reasoningEngines\/', '.[...]/reasoningEngines/'):label=CALLER,
protoPayload.authorizationInfo[0].granted:label=GRANTED,
protoPayload.metadata.destination.agent_registry.resource_type.basename():label=TYPE,
protoPayload.metadata.destination.agent_registry.resource_id.basename():label=RESOURCE_ID,
protoPayload.authorizationInfo[0].permission.basename():label=PERMISSION
)"
Пример результата:
TIME CALLER GRANTED TYPE RESOURCE_ID PERMISSION
HH:MM:SS principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID} True Endpoint ${ENDPOINT_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${BURGER_ENGINE_ID} True Endpoint ${ENDPOINT_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID} True Endpoint ${ENDPOINT_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${BURGER_ENGINE_ID} True Endpoint ${ENDPOINT_ID} resources.egressViaIAP
Шаг 4. Проверьте заказ пиццы (запрет по умолчанию -> HTTP 403 Forbidden ENFORCED)
В том же окне чата Playground отправьте следующий запрос на заказ пиццы:
I would like 10 BBQ Chicken Pizzas. Place this order now.
Если требуется подтверждение, отправь следующий ответ:
Confirmed, please place the order.
Вы также можете выполнить проверку программно из Cloud Shell или терминала:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='I would like 8 Hawaiian pizzas, please. Place this order now.')
print(response)
"
Если требуется подтверждение, используйте следующую команду:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"
Ожидаемый ответ:
I apologize, but I am unable to process that request at the moment. It seems
there was an issue connecting to the pizza seller agent. Please try again later.
Что происходит за кулисами:
- Динамическое обнаружение. Помощник по покупкам разрешил конечную точку
pizza-seller-agentиз центрального реестра агентов во время запуска. - Определение намерения и вызов A2A. Gemini в помощнике по покупкам пытается отправить запрос на заказ пиццы в конечную точку продавца пиццы в
PROJECT_SELLERS. - Перехват шлюзом. Исходящий RPC перехватывается
agent_gateway_configи направляется на центральный шлюз агента. - Оценка правил IAP v2 (запрет по умолчанию). Центральный шлюз агента вызывает IAP v2. Поскольку в единых правилах доступа нет правила, соответствующего
pizza-seller-agent, IAP возвращаетDENY(granted: false). - Строгая блокировка периметра. Поскольку расширение Authz находится в режиме принудительного применения (
failOpen: false), шлюз центрального агента немедленно прерывает исходящее подключение и возвращаетHTTP 403 Forbidden. Трафик не покидает шлюз и не достигаетPROJECT_SELLERS.
Шаг 5. Проверьте журналы шлюза агента на наличие заблокированных запросов (HTTP 403/DENIED)
# query Agent Gateway logs for blocked 403 requests
gcloud logging read "
logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
AND httpRequest.status=403
" \
--project="${PROJECT_GOVERNANCE}" \
--limit=5 \
--format="table(
timestamp.date('%H:%M:%S'):label=TIME,
httpRequest.requestMethod:label=METHOD,
httpRequest.status:label=STATUS,
jsonPayload.authzPolicyInfo.result:label=AUTHZ,
httpRequest.requestUrl:label=URL
)"
Пример выходных данных журнала запрещенных действий:
TIME METHOD STATUS AUTHZ URL
HH:MM:SS POST 403 DENIED https://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/reasoningEngines/${PIZZA_ENGINE_ID}:query
Запросите журналы аудита доступа к данным IAP v2, чтобы узнать причину отказа:
# query IAP v2 audit logs with shortened principal and resource fields
gcloud logging read "
logName=\"projects/${PROJECT_GOVERNANCE}/logs/cloudaudit.googleapis.com%2Fdata_access\"
AND protoPayload.serviceName=\"iap.googleapis.com\"
" \
--project="${PROJECT_GOVERNANCE}" \
--limit=5 \
--format="table(
timestamp.date('%H:%M:%S'):label=TIME,
protoPayload.authenticationInfo.principalSubject.sub('\.global\..*\/reasoningEngines\/', '.[...]/reasoningEngines/'):label=CALLER,
protoPayload.authorizationInfo[0].granted:label=GRANTED,
protoPayload.metadata.destination.agent_registry.resource_type.basename():label=TYPE,
protoPayload.metadata.destination.agent_registry.resource_id.basename():label=RESOURCE_ID,
protoPayload.authorizationInfo[0].permission.basename():label=PERMISSION
)"
Пример выходных данных журнала аудита для отклоненных запросов:
TIME CALLER GRANTED TYPE RESOURCE_ID PERMISSION
HH:MM:SS principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID} True Endpoint ${REGISTRY_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID} True Endpoint ${REGISTRY_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${CONCIERGE_ENGINE_ID} False Agent ${REGISTRY_ID} resources.egressViaIAP
HH:MM:SS principal://agents.[...]/reasoningEngines/${PIZZA_ENGINE_ID} True Endpoint ${REGISTRY_ID} resources.egressViaIAP
Шаг 6. Динамически предоставьте агенту Pizza доступ к исходящему трафику
Создайте новый файл cfg/uap-rules-update-3.json, в который будут входить Правило 1 (основные API), Правило 2 (агент по продаже бургеров) и Правило 3 (агент по продаже пиццы).
# create addendum to update policy manifest with Rule 3 for Pizza Agent
cat > cfg/uap-rules-update-3.json << EOF
[
{
"description": "Rule 3: Allow Purchasing Concierge to invoke Pizza Seller Agent via Central Gateway",
"effect": "ALLOW",
"principals": [
"${CONCIERGE_SPIFFE_PRINCIPAL}"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true && \
destination.agent_registry.resource_type == 'AGENT' && ( \
destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/pizza-seller-agent' || \
destination.agent_registry.agent.name == 'projects/${PROJECT_GOVERNANCE}/locations/${REGION}/agents/${PIZZA_AGENT_ID}' || \
destination.agent_registry.agent.name == 'projects/${PROJECT_NUMBER_GOVERNANCE}/locations/${REGION}/agents/${PIZZA_AGENT_ID}')"
}
}
}
]
EOF
Примените обновление правил в реальном времени:
# update IAM access policy with Pizza rule
gcloud iam access-policies update ${UAP_POLICY_NAME} \
--add-details-rules=cfg/uap-rules-update-3.json \
--project=${PROJECT_GOVERNANCE} \
--location=global
Шаг 7. Повторный запрос к агенту Pizza Agent (немедленный ответ 200 OK)
В окне чата Playground повторно отправьте запрос на заказ пиццы:
I would like 10 BBQ Chicken Pizzas. Place this order now.
Если требуется подтверждение, отправьте следующий ответ:
Confirmed, please place the order.
Вы также можете выполнить проверку программно из Cloud Shell или терминала:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='I would like 11 Veggie pizzas, please. Place this order now.')
print(response)
"
Если требуется подтверждение, используйте следующую команду:
uv run --directory ./cross-project-multiagent python -c "
import vertexai
from vertexai.preview import reasoning_engines
vertexai.init(project='${PROJECT_CONCIERGE}', location='${REGION}')
agent = reasoning_engines.ReasoningEngine('projects/${PROJECT_CONCIERGE}/locations/${REGION}/reasoningEngines/${CONCIERGE_ENGINE_ID}')
response = agent.query(input='Yes please place the order now.')
print(response['text'])
"
Ожидаемый ответ:
Your order has been placed!
**Order ID:** 8d6c13d7-31dc-4d80-b6a7-80d1e50b6411
**Order Details:**
* 10 x BBQ Chicken Pizza @ IDR 130,000 each = IDR 1,300,000
**Total: IDR 1,300,000**
Что происходит за кулисами:
- Динамическое обновление правил. Изменения в единых правилах доступа IAM сразу же вступают в силу в механизме оценки IAP без простоев и повторного развертывания контейнеров.
- Вызов A2A. Concierge отправляет запрос через Central Agent Gateway.
- Оценка правил IAP v2 (одобрение). IAP v2 соответствует правилу 3, проверяет идентификационные данные вызывающего абонента и целевое выражение CEL и возвращает
ALLOW(granted: true). - Выполнение в разных проектах. Центральный шлюз агента передает авторизованный трафик в
PROJECT_SELLERS, где продавец пиццы обрабатывает заказ.
Шаг 8. Проверьте журналы шлюза агента на наличие запросов на пиццу
# query Agent Gateway logs for successful 200 OK requests
gcloud logging read "
logName=\"projects/${PROJECT_GOVERNANCE}/logs/networkservices.googleapis.com%2Fgateway_requests\"
AND jsonPayload.authzPolicyInfo.result=\"ALLOWED\"
" \
--project="${PROJECT_GOVERNANCE}" \
--limit=10 \
--format="table(
timestamp.date('%H:%M:%S'):label=TIME,
httpRequest.requestMethod:label=METHOD,
httpRequest.status:label=STATUS,
jsonPayload.authzPolicyInfo.result:label=AUTHZ,
httpRequest.requestUrl:label=URL
)"
Пример выходных данных журнала с предоставленным доступом:
TIME METHOD STATUS AUTHZ URL
HH:MM:SS POST 200 ALLOWED https://aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/global/publishers/google/models/gemini-3.5-flash:generateContent
HH:MM:SS POST 200 ALLOWED https://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/reasoningEngines/${PIZZA_ENGINE_ID}:query
На этом тестирование и проверка завершены. Перейдите к разделу Очистка.
11. Очистка
Чтобы избежать списания средств с вашего аккаунта Google Cloud за ресурсы, используемые в этой практической работе, выполните действия по удалению в строгом порядке обратной зависимости:
1. Как удалить развертывания Reasoning Engine
Выполните скрипт cleanup_old_deployments.py в обоих проектах среды выполнения, чтобы удалить механизмы рассуждения и дождаться завершения их продолжительных операций.
# delete all Reasoning Engines deployed in Concierge and Sellers projects
uv run --directory ./cross-project-multiagent python cleanup_old_deployments.py --project=${PROJECT_CONCIERGE} --region=${REGION}
uv run --directory ./cross-project-multiagent python cleanup_old_deployments.py --project=${PROJECT_SELLERS} --region=${REGION}
Вы также можете получить список движков и удалить их:
uv run --directory ./cross-project-multiagent python -c '
import vertexai
import os
from vertexai.preview import reasoning_engines
region = os.environ.get("REGION", "us-central1")
for proj in [os.environ.get("PROJECT_CONCIERGE"), os.environ.get("PROJECT_SELLERS")]:
if not proj:
continue
print(f"Cleaning reasoning engines in {proj}...")
vertexai.init(project=proj, location=region)
for eng in reasoning_engines.ReasoningEngine.list():
print(f" Deleting {eng.resource_name} ({eng.display_name})...")
eng.delete()
'
2. Удаление служб реестра агентов
# delete agent registry services in Central Governance Project
for SERVICE in burger-seller-agent pizza-seller-agent purchasing-concierge-adk core-gapi-services; do
gcloud agent-registry services delete ${SERVICE} \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} \
--quiet || true
done
3. Удаление привязки унифицированных правил доступа IAM и правил доступа
# 1. delete IAM policy binding
gcloud -q iam policy-bindings delete ${UAP_BINDING_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global || true
# 2. delete IAM access policy
gcloud -q iam access-policies delete ${UAP_POLICY_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global || true
4. Удаление шлюза агента и политик безопасности
# 1. delete authorization policy
gcloud beta network-security authz-policies delete ${AGW_NAME}-authz-policy-profile-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE} --quiet || true
# 2. delete authorization extension
gcloud service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE} --quiet || true
# 3. delete agent gateway
gcloud network-services agent-gateways delete ${AGW_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=${REGION} --quiet || true
5. Удалите привязки IAM между проектами и специальную роль
# 1. remove custom role and network viewer bindings for spoke service agents
for NUM in "${PROJECT_NUMBER_CONCIERGE}" "${PROJECT_NUMBER_SELLERS}"; do
SA="service-${NUM}@gcp-sa-aiplatform.iam.gserviceaccount.com"
gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="serviceAccount:${SA}" \
--role="projects/${PROJECT_GOVERNANCE}/roles/ar_agw_cross_project_sa" --quiet || true
gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="serviceAccount:${SA}" \
--role="roles/networkservices.viewer" --quiet || true
done
# 2. remove registry viewer permissions across both spoke projects
for NUM in "${PROJECT_NUMBER_CONCIERGE}" "${PROJECT_NUMBER_SELLERS}"; do
for MEMBER in \
"serviceAccount:service-${NUM}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
"serviceAccount:service-${NUM}@gcp-sa-aiplatform-re.iam.gserviceaccount.com" \
"serviceAccount:${NUM}-compute@developer.gserviceaccount.com" \
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${NUM}"; do
gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="${MEMBER}" \
--role="roles/agentregistry.viewer" --quiet || true
done
done
# 3. remove project viewer permissions
for MEMBER in \
"serviceAccount:${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com" \
"serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com"; do
gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="${MEMBER}" \
--role="roles/viewer" --quiet || true
done
# 4. remove spoke-to-spoke delegation in Sellers project
for MEMBER in \
"serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform.iam.gserviceaccount.com" \
"serviceAccount:service-${PROJECT_NUMBER_CONCIERGE}@gcp-sa-aiplatform-re.iam.gserviceaccount.com" \
"serviceAccount:${PROJECT_NUMBER_CONCIERGE}-compute@developer.gserviceaccount.com" \
"principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER_CONCIERGE}"; do
gcloud projects remove-iam-policy-binding ${PROJECT_SELLERS} \
--member="${MEMBER}" \
--role="roles/aiplatform.user" --quiet || true
done
# 5. delete custom IAM role after all bindings have been unlinked
gcloud iam roles delete ar_agw_cross_project_sa \
--project=${PROJECT_GOVERNANCE} --quiet || true
Если вы назначили роли roles/iam.accessPolicyAdmin и roles/resourcemanager.projectIamAdmin на этапе настройки, удалите их из активного аккаунта пользователя, чтобы восстановить минимальные привилегии:
# 6. remove Access Policy Admin and Project IAM Admin roles from user
for ROLE in "roles/iam.accessPolicyAdmin" "roles/resourcemanager.projectIamAdmin"; do
gcloud projects remove-iam-policy-binding ${PROJECT_GOVERNANCE} \
--member="user:$(gcloud config get-value account)" \
--role="${ROLE}" \
--condition=None --quiet || true
done
6. Отмена ведения журнала аудита и ограничений правил организации
# 1. Export current Central Governance IAM policy
gcloud projects get-iam-policy ${PROJECT_GOVERNANCE} --format=json > cfg/gov_iam_policy.json
# 2. Filter out iap.googleapis.com from auditConfigs
python3 -c "
import json
with open('cfg/gov_iam_policy.json') as f:
policy = json.load(f)
if 'auditConfigs' in policy:
# Remove iap.googleapis.com; if nothing else remains, clear the list
policy['auditConfigs'] = [
ac for ac in policy['auditConfigs'] if ac.get('service') != 'iap.googleapis.com'
]
with open('cfg/gov_iam_policy.json', 'w') as f:
json.dump(policy, f, indent=2)
"
# 3. Apply the updated policy to revert audit logging to default
gcloud projects set-iam-policy ${PROJECT_GOVERNANCE} cfg/gov_iam_policy.json
7. Отменить ограничения правил организации
# revert iam v3 access policy binding org policy on project to org level setting
gcloud org-policies delete iam.managed.disableAccessPolicyBinding --project=${PROJECT_GOVERNANCE}
8. Удаление общей промежуточной корзины GCS и локальных артефактов
# delete central staging bucket
gcloud storage rm -r gs://${PROJECT_GOVERNANCE}-shared-staging
# remove local configuration manifests, environment files, and application
rm -rf cfg/ cross-project-multiagent/ *.env
На этом мы заканчиваем раздел, посвященный очистке. Далее переходим к заключению.
12. Заключение
Поздравляем! Вы развернули многопроектную архитектуру Agent-to-Agent (A2A) в Google Cloud и настроили управление ею с помощью Vertex AI Agent Runtime, Central Agent Gateway, Agent Registry и IAM Unified Access Policies (UAP).
Краткое изложение основных понятий
- Централизованный периметр исходящего трафика. Контейнеры среды выполнения дочерних проектов (
PROJECT_CONCIERGE,PROJECT_SELLERS) маршрутизируются через центральный шлюз Agent Gateway вPROJECT_GOVERNANCEс помощьюagentGatewayConfig. - Декларативное управление (UAP). Фрагментированные привязки для отдельных ресурсов заменены единой политикой доступа IAM, подлежащей аудиту и оцениваемой на шлюзе с помощью IAP v2.
- Криптографическая идентификация. Принудительное применение минимальных привилегий для исходящего трафика с использованием идентификаторов SPIFFE контейнера (
principal://...) вместо долгосрочных ключей. - Динамическое обнаружение сервисов. Конечные точки одноранговых агентов разрешаются во время выполнения через центральный реестр агентов, что устраняет необходимость в жестко закодированных URL и идентификаторах проектов.
- Гибкость правил во время выполнения. Переход
pizza-seller-agentот запрета по умолчанию (403 Forbidden) к разрешению (200 OK) в реальном времени с помощью обновления правил без перезапуска контейнеров.

Космопес говорит: "Агенты – это здорово. Они выполняют всю работу по проектам, а я могу сосредоточиться на своей главной цели – вздремнуть!"
Дальнейшие действия и документация
- Обзор Gemini Enterprise Agent Platform
- Как настроить и развернуть Agent Gateway
- Подробный анализ идентификации агента и аттестации SPIFFE
- Единые правила доступа IAM и атрибуты CEL
- Обзор каталога сервисов реестра агентов
- Ограничения Model Armor и защита конфиденциальных данных
- Интерфейсы Private Service Connect (PSC-I) со шлюзом агента