Agent Gateway обеспечивает централизованное управление с помощью межпроектного реестра агентов для среды выполнения агентов.

1. Введение

По мере внедрения генеративного ИИ в организациях архитектуры быстро эволюционируют от автономных монолитных чат-ботов к распределенным многоагентным системам (Agent-to-Agent / A2A) . В этих современных топологиях высокоуровневые агенты-оркестраторы координируют сложные бизнес-процессы, делегируя задачи специализированным агентам-обработчикам, серверам инструментов Model Context Protocol (MCP) и внутренним корпоративным базам данных в рамках независимых проектов Google Cloud.

Однако масштабируемая эксплуатация многоагентных систем влечет за собой серьезные проблемы в области безопасности, управления и функционирования:

  • Распространение теневых агентов и инструментов: Когда команды разработчиков развертывают агентов в изолированных проектах без централизованного каталога, организации теряют представление о том, какие инструменты и субагенты существуют.
  • Неконтролируемый исходящий трафик между проектами: предоставление агентам возможности использовать прямые, непроверяемые сетевые маршруты создает риски утечки данных и обходит периметры безопасности.
  • Хрупкие жестко закодированные интеграции: Жесткое кодирование URL-адресов агентов и идентификаторов механизмов вывода создает ненадежные зависимости, которые могут нарушиться при обновлениях или повторном развертывании.
  • Отсутствие принципа наименьших привилегий при идентификации: общие учетные записи служб не обеспечивают криптографическую неопровержимость на уровне отдельных экземпляров агентов.

Для решения этих задач платформа Gemini Enterprise Agent Platform предоставляет единую плоскость управления и контроля подключения, состоящую из четырех основных компонентов:

  1. Agent Gateway ( networkservices.googleapis.com ) : управляемый региональный прокси-сервер для управления сетью и обеспечения соблюдения политик. Работая в режиме исходящего трафика AGENT_TO_ANYWHERE , он перехватывает исходящий трафик агентов, делегирует оценку авторизации расширениям безопасности и направляет запросы через периметр проекта.
  2. Agent Registry ( agentregistry.googleapis.com ) : Единый корпоративный каталог сервисов. Он предоставляет централизованный, проверенный каталог всех доступных инструментов, серверов MCP и агентов-партнеров в масштабах всей организации, обеспечивая динамическое автоматическое обнаружение в режиме реального времени без каких-либо жестко заданных конечных точек.
  3. Идентификация агентов и управление IAP v2 ( 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.* ).
  4. Agent Runtime (Reasoning Engines) : Полностью управляемая бессерверная платформа выполнения для агентских приложений на основе Python, включающая собственные привязки конфигурации ( agent_gateway_config ) к центральным шлюзам.

Бизнес-сценарий Codelab: Закупки продуктов питания и напитков в рамках нескольких проектов

В этом практическом занятии вы создадите и будете управлять реальной экосистемой закупок для нескольких проектов, охватывающей три отдельных проекта Google Cloud:

  • Проект централизованного управления ( PROJECT_GOVERNANCE ): находится в ведении центрального ИТ-отдела и отдела безопасности, включает в себя центральный шлюз агентов, центральный реестр агентов и унифицированные политики доступа IAM.
  • Проект «Организатор потребительских процессов» ( PROJECT_CONCIERGE ): находится в ведении отдела закупок и включает в себя агента по организации закупок , который динамически находит поставщиков и направляет заказы клиентов.
  • Проект поставщика домена ( PROJECT_SELLERS ): Принадлежит внешним или ведомственным поставщикам и размещает агенты для продавцов бургеров и пиццы .

рисунок1

Рис. 1. Архитектура централизованного управления несколькими проектами.

Почему необходимо централизованное управление всеми проектами?

В крупных корпоративных организациях продуктовые команды и группы анализа данных создают агентов ИИ в рамках десятков независимых проектов Google Cloud. Предоставление каждой команде прямого контроля над регистрацией инструментов, исходящими сетевыми маршрутами и механизмами безопасности приводит к неконтролируемому разрастанию инструментов, непоследовательным политикам DLP, неконтролируемому исходящему трафику VPC и фрагментированным журналам аудита.

Централизованное управление в рамках всего проекта разделяет разработку политик и их выполнение агентами:

  • Централизованное управление ИТ-инфраструктурой и службой безопасности разрабатывает политики безопасности, проверяет инструменты и отслеживает исходящий трафик в рамках единого проекта централизованного управления .
  • В своих независимых проектах по разработке среды выполнения агентов команды разработчиков и приложений сосредотачиваются исключительно на бизнес-логике, напрямую подключаясь к центральному шлюзу без операционных издержек, связанных с управлением локальными VPC, межсетевыми соединениями или разрозненными механизмами политик.

рисунок 2

Рис. 2. Трехуровневая архитектура управления проектами и ее границы.

Двухуровневая модель определения области действия идентификации в унифицированных политиках доступа

Когда агенты взаимодействуют через Центральный шлюз агентов, Identity-Aware Proxy (IAP v2) оценивает доступ на основе идентификатора агента вызывающего абонента — криптографически подтвержденного идентификатора на основе SPIFFE, автоматически выдаваемого контейнеру среды выполнения, — в соответствии с глобальной политикой доступа IAM:

  • Уровень 1: Базовые API Google Cloud (крупномасштабные через principalSet:// в Правиле 1): Авторизация исходящего трафика в масштабе всего проекта, позволяющая всем средам выполнения агентов в периферийных проектах обращаться к стандартным API Google ( aiplatform , iamcredentials , telemetry , agentregistry ) для обнаружения, генерации токенов и вывода информации.
  • Уровень 2: Бизнес-инструменты и сервисы A2A (детальная настройка через principal:// в правилах 2 и 3): Строгий доступ с минимальными привилегиями, привязанный к отдельным экземплярам механизма рассуждений, обеспечиваемый условиями Common Expression Language (CEL), нацеленными на конкретные зарегистрированные сервисы реестра агентов ( destination.agent_registry.agent.name ).

Что вы строите

  • Централизованный шлюз агентов ( centralized-agw ) в PROJECT_GOVERNANCE
  • Расширение службы авторизации IAP v2 и политика авторизации в строгом режиме ENFORCE ( failOpen: false )
  • Базовая политика унифицированного доступа IAM ( uap-rules.json ) и привязка политик проекта.
  • Разрешения IAM для агентов межпроектных сервисов ( ar_agw_cross_project_sa )
  • Общий централизованный промежуточный сегмент Google Cloud Storage (GCS).
  • Изолированные агенты по продаже бургеров и пиццы в PROJECT_SELLERS
  • В проекте PROJECT_CONCIERGE реализована функция «Приобретение консьерж-агента с динамическим REST-автообнаружением».
  • Регистрация сервисов в Центральном реестре агентов с использованием межпроектных mTLS-URL-адресов
  • Динамические обновления политики исходящего трафика IAP v2 с проверкой в ​​реальном времени и аудитом в Cloud Logging.

рисунок3

Рис. 3. Пошаговая последовательность реализации.

Чему вы научитесь

  • Как настроить разрешения IAM для агентов сервисов, работающих в разных проектах, для централизованных шлюзов.
  • Как направлять исходящий трафик Agent Runtime через центральный шлюз Agent Gateway в многопроектных средах
  • Как делегировать авторизацию Agent Gateway прокси-серверу с поддержкой идентификации (IAP v2) с помощью расширений службы ( iapPolicyVersion: "V2" )
  • Как создавать и связывать политики унифицированного доступа IAM (UAP) с правилами Common Expression Language (CEL), регулирующими зарегистрированные целевые объекты реестра агентов ( destination.agent_registry.* ).
  • Как исключить использование жестко закодированных идентификаторов и URL-адресов агентов при автоматическом обнаружении во время выполнения с помощью реестра агентов.
  • Как протестировать блокировку с нулевым доверием на реальном периметре ( HTTP 403 Forbidden ) и проверить обновления политик в режиме реального времени в Cloud Logging.

Что вам нужно

  • 3 проекта Google Cloud с включенной функцией выставления счетов:
    • PROJECT_GOVERNANCE : Централизованное управление, шлюз, реестр и политики доступа IAM.
    • PROJECT_CONCIERGE : Агент по организации консьерж-услуг в сфере закупок
    • PROJECT_SELLERS : Агенты по продаже бургеров и пиццы.
  • Пользователь или сервисная учетная запись IAM с roles/owner или административными правами во всех 3 проектах.
  • Организация Google Cloud (для сопоставления доменов доверия SPIFFE)
  • Google Cloud Shell или локальный компьютер с установленными gcloud CLI, python (версия 3.11 и выше) и uv

На этом вводная часть завершается... далее переходим к разделу «Настройка и среда» .

2. Настройка

Несмотря на то, что эта архитектура охватывает 3 отдельных проекта Google Cloud, вы можете выполнять 100% команд развертывания, загрузки репозиториев и операций подготовки из одного терминала Cloud Shell, настроенного на PROJECT_GOVERNANCE . Каждый скрипт развертывания и команда gcloud явно указывают на соответствующий целевой проект с помощью флагов CLI ( --project ).

Для начала откройте командную строку вашего проекта Google Cloud:

Укажите контекст вашего проекта

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

Включите журналы доступа к данным аудита облака для 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, обеспечивает операционную согласованность и предотвращает сбои при создании токенов во время выполнения, ошибки каталогизации схемы или потери телеметрии.

Запустите следующий скрипт проверки в Cloud Shell, чтобы убедиться в единообразии API во всех трех проектах:

# 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-адреса Google API в Центральном реестре агентов, чтобы агенты, настроенные с помощью agent_gateway_config , могли безопасно направлять исходящий трафик к основным серверным службам Google Cloud (таким как aiplatform , учетные данные IAM и телеметрия).

Создайте 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://iamcredentials.googleapis.com \
  --interfaces=protocolBinding=JSONRPC,url=https://iamcredentials.mtls.googleapis.com \
  --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

Получение идентификатора ресурса конечной точки основных 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 идентификаторы машин, выдаваемые исполняемым контейнерам агентов, используют криптографически подтвержденные SPIFFE URN, оцениваемые Identity-Aware Proxy (IAP v2). При настройке унифицированных политик доступа IAM можно выбрать либо конкретный principal , либо principalSet на основе атрибутов:

Измерение

principal:// (Единый машинный идентификатор)

principalSet:// (Группа на основе атрибутов)

Синтаксис IAM

principal://...

principalSet://...

Гранулярность

Детальная идентификация (на уровне экземпляра): определяет конкретный экземпляр контейнера механизма рассуждений.

Крупномасштабный (на уровне проекта): определяет все механизмы рассуждений, имеющие общий атрибут проекта.

Узор для урны

principal://agents.global.org-${ORG_ID}.system.id.goog/resources/aiplatform/projects/${PROJECT_NUMBER}/locations/${REGION}/reasoningEngines/${ENGINE_ID}

principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJECT_NUMBER}

Вариант использования в агентской платформе

Уровень 2 (Бизнес-инструменты и A2A): Авторизация конкретных агентов оркестратора для вызова инструментов целевого домена (например, «Консьерж по закупкам» > «Продавец бургеров»).

Уровень 1 (Базовая инфраструктура): Предоставление всем агентам в проекте исходящего доступа к API Google Cloud ( core-gapi-services ).

Влияние на жизненный цикл

Если агент удаляется и создается заново, для его нового идентификатора движка потребуется обновить привязку политики 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, что гарантирует наличие базовых маршрутов исходящего трафика для всех контейнеров агентов до развертывания.

Для получения более подробной технической информации об идентификаторах субъектов и механизмах идентификации рабочих нагрузок см.:

На этом завершается регистрация основных конечных точек API... далее переходим к разделу «Развертывание централизованного шлюза агентов» .

4. Шлюз агентов

Разверните централизованный шлюз агентов.

Разверните централизованный шлюз агентов ( 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. Авторизация

Настройка авторизации шлюза агентов и базового UAP.

Шлюз агентов обеспечивает безопасность и управление исходящим трафиком инструментов и агентов с помощью политик авторизации ( networksecurity.authzPolicies ), интегрированных с политиками унифицированного доступа (UAP) Identity-Aware Proxy (IAP v2) .

Обзор архитектуры авторизации

рисунок4

Рис. 4. Обзор архитектуры авторизации

Архитектура авторизации состоит из трех взаимосвязанных уровней:

  1. Расширение службы IAP ( authzExtension ) : Региональный ресурс, настроенный с использованием service: iap.googleapis.com , metadata: iapPolicyVersion: "V2" и failOpen: false для строгого обеспечения нулевого доверия на периметре сети.
  2. Политика авторизации шлюза ( authzPolicy ) : Региональный ресурс, нацеленный на ваш шлюз агента с policyProfile: REQUEST_AUTHZ и action: CUSTOM , перенаправляющий проверки авторизации в расширение IAP Authz.
  3. Единая политика доступа и привязка IAM ( 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}

Теперь исходящий трафик базовых API Google Cloud безопасно авторизуется во всех трех проектах в строгом режиме ENFORCE .

На этом завершается настройка авторизации шлюза... далее переходим к разделу «Настройка разрешений IAM для разных проектов» .

6. Межпроектное управление идентификацией и доступом (IAM)

Настройка разрешений IAM для разных проектов

В этой многопроектной топологии среды выполнения агентов находятся в периферийных проектах ( PROJECT_CONCIERGE и PROJECT_SELLERS ), а центральный шлюз агентов и реестр агентов — в PROJECT_GOVERNANCE .

Поскольку проекты Google Cloud представляют собой изолированные периметры безопасности, доступ между проектами должен быть явно предоставлен на двух операционных уровнях:

  1. Плоскость управления (время развертывания): При развертывании контейнера агента, настроенного с --agent-gateway-config , служба выполнения агентов проекта-спицы ( service- @gcp-sa-aiplatform.iam.gserviceaccount.com ) должен подключить контейнер к центральному шлюзу. Мы создаем минимальную пользовательскую роль ( ar_agw_cross_project_sa ), предоставляющую networkservices.agentGateways.use , get и operations.get в PROJECT_GOVERNANCE .
  2. Плоскость данных (выполнение во время выполнения):
    • Обнаружение в каталоге: Для динамического определения целевых конечных точек агентов периферийным устройствам требуется 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"

Назначение пользовательской роли агентам службы выполнения агентов

# 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 в рамках всего проекта... далее переходим к разделу «Развертывание агентов продавцов и консьержей» .

7. Среда выполнения агента

Внедрите агентов по продажам и консьерж-сервисам.

Код многоагентного приложения и скрипты развертывания, используемые в этом практическом занятии, хранятся в удаленном репозитории Google Cloud GitHub . Следующие шаги клонируют репозиторий локально, скопируют необходимые файлы в текущую структуру рабочих каталогов, очистят временные файлы и установят зависимости с помощью uv .

Получение удаленных артефактов

# clone remote repository to temp local dir
git clone https://github.com/GoogleCloudPlatform/cloud-networking-solutions.git ./temp_agw_cuj_arun_multiproject
# copy multi-agent application files to current working directory
cp -r temp_agw_cuj_arun_multiproject/codelabs/agw-cuj-arun-multiproject ./cross-project-multiagent
# remove temporary directory
rm -rf temp_agw_cuj_arun_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 было установлено ранее в нашей Единой политике доступа, запросы на инициализацию контейнеров к API Google Cloud разрешены через шлюз без прерывания.

Внедрить агентов по продаже бургеров и пиццы в 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 и проект, а также привязка к шлюзу агента проекта 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.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
# 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.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
# 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.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

Получение идентификаторов базового агента из реестра

# 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 с параметром Default Deny в строгом режиме ENFORCE :

  1. Правило 1 (Базовые API Google Cloud): Позволяет контейнерам агентов во всех 3 проектах обращаться к core-gapi-services .
  2. Правило 2 (Агент продавца бургеров: РАЗРЕШИТЬ): Разрешает экземпляру Агента по сопровождению закупок вызывать Агента продавца бургеров.
  3. Агент продавца пиццы (по умолчанию ЗАПРЕЩЕН): Намеренно исключен из правил политики. В режиме ENFORCE ( failOpen: false ) любая попытка консьержа вызвать продавца пиццы будет немедленно прервана на периметре шлюза с HTTP 403 Forbidden .

Сформулируйте идентичность консьерж-агента.

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

Создайте новый cfg/uap-rules-update-2.json , чтобы включить в него Правило 1 (Основные API) и теперь Правило 2 (Агент продавца Burger):

# create addendum to update policy manifest with Rule 2 for Burger Agent
cat > cfg/uap-rules-update-2.json << EOF
[
  {
    "description": "Rule 2: Allow Purchasing Concierge to invoke Burger 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/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

Примените обновленную политику доступа.

# update IAM access policy with Burger rule
gcloud iam access-policies update ${UAP_POLICY_NAME} \
  --add-details-rules=cfg/uap-rules-update-2.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. Проверьте правила.

Тестирование и проверка политик управления с помощью облачного логирования.

В этом разделе вы протестируете взаимодействие между агентами (A2A) в рамках нескольких проектов в среде разработки Agent Runtime AI Playground, понаблюдаете за реальной блокировкой HTTP 403 Forbidden в строгом режиме ENFORCE , внесете изменения в унифицированную политику доступа в режиме реального времени и проверите мгновенное подтверждение заказов.

Шаг 1: Откройте среду выполнения Agent Runtime AI Playground в PROJECT_CONCIERGE

  1. Откройте консоль Google Cloud .
  2. В верхней панели выбора проекта переключитесь на PROJECT_CONCIERGE .
  3. В меню навигации перейдите в раздел «Платформа агентов» > «Агенты» > «Развертывания» .
  4. Нажмите на purchasing-concierge-adk .
  5. Выберите «Игровая площадка» , чтобы открыть интерактивный чат в правой части экрана.

Шаг 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'])
"

Что происходит за кулисами:

  1. Динамическое обнаружение: Во время запуска сессии менеджер по закупкам запросил Центральный реестр агентов в PROJECT_GOVERNANCE (через core-gapi-services через Agent Gateway, авторизованный правилом 1), чтобы обнаружить региональную конечную точку mTLS для burger-seller-agent .
  2. Разрешение намерений и вызов A2A: Gemini внутри системы Purchasing Concierge анализирует намерение заказа еды и вызывает агента продавца бургеров через исходящий RPC-вызов по адресу https://${REGION}-aiplatform.mtls.googleapis.com/.../reasoningEngines/${BURGER_ENGINE_ID} .
  3. Перехват трафика шлюзом и распространение SPIFFE: исходящий трафик перехватывается agent_gateway_config и направляется на центральный шлюз агента в PROJECT_GOVERNANCE , неся криптографический идентификатор SPIFFE консьержа ( principal://... ).
  4. Оценка политики IAP v2: Центральный шлюз агента вызывает расширение авторизации IAP ( authzExtension ). IAP v2 оценивает правило 2 в унифицированной политике доступа IAM. Поскольку вызывающий объект соответствует ${CONCIERGE_SPIFFE_PRINCIPAL} , а целевой объект соответствует burger-seller-agent , IAP возвращает ALLOW ( granted: true ).
  5. Выполнение запросов между проектами: Шлюз агентов передает авторизованный запрос между проектами в PROJECT_SELLERS , где механизм обработки запросов продавцов Burger обрабатывает заказ и возвращает подтверждение.

Ожидаемый ответ:

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)

Запросить журналы запросов Agent Gateway в 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 ).

Запросите журналы доступа к данным аудита облака IAP v2, чтобы проверить версию политики POLICY_VERSION_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.

Что происходит за кулисами:

  1. Динамическое обнаружение: Служба поддержки закупок определила конечную точку pizza-seller-agent из Центрального реестра агентов во время запуска.
  2. Разрешение намерений и вызов A2A: Gemini внутри системы Purchasing Concierge пытается перенаправить запрос на заказ пиццы на конечную точку продавца пиццы в PROJECT_SELLERS .
  3. Перехват шлюза: исходящий RPC-вызов перехватывается функцией agent_gateway_config и направляется на центральный шлюз агентов.
  4. Оценка политики IAP v2 (запрет по умолчанию): Центральный шлюз агентов вызывает IAP v2. Поскольку в Единой политике доступа отсутствует правило , соответствующее pizza-seller-agent , IAP возвращает DENY ( granted: false ).
  5. Строгая блокировка периметра: поскольку расширение аутентификации находится в режиме ENFORCE ( 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 Agent

Создайте новый cfg/uap-rules-update-3.json , чтобы включить в него Правило 1 (Основные API), Правило 2 (Агент продавца Burger) и теперь Правило 3 (Агент продавца Pizza).

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

Что происходит за кулисами:

  1. Динамическое обновление политики: обновление унифицированной политики доступа IAM вступает в силу немедленно в тестовом модуле IAP без простоев и без повторного развертывания каких-либо контейнеров.
  2. Вызов A2A: Консьерж отправляет запрос через центральный шлюз агентов.
  3. Оценка политики IAP v2 (утверждение): IAP v2 соответствует правилу 3, проверяет личность вызывающего абонента и целевое выражение CEL и возвращает ALLOW ( granted: true ).
  4. Выполнение заказов в рамках нескольких проектов: Центральный шлюз агента направляет авторизованный трафик в 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://us-central1-aiplatform.mtls.googleapis.com/v1beta1/projects/${PROJECT_SELLERS}/locations/us-central1/publishers/google/models/gemini-2.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. Очистка развертываний системы логического вывода.

Выполните прилагаемый скрипт 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. Заключение

Поздравляем! Вы успешно развернули и управляете многопроектной архитектурой взаимодействия агентов (A2A) в Google Cloud, используя Vertex AI Agent Runtime, Central Agent Gateway, Agent Registry и IAM Unified Access Policies (UAP).

Краткое изложение основных понятий

  • Централизованный исходящий периметр: маршрутизация периферийных контейнеров среды выполнения ( PROJECT_CONCIERGE , PROJECT_SELLERS ) через центральный шлюз агентов в PROJECT_GOVERNANCE с использованием agentGatewayConfig .
  • Декларативное управление (UAP): Заменены разрозненные привязки для каждого ресурса единой, подлежащей аудиту политикой доступа IAM, оцениваемой на шлюзе с помощью IAP v2.
  • Криптографическая идентификация: Обеспечение минимального уровня привилегий при исходящем трафике с использованием идентификаторов SPIFFE контейнеров ( principal://... ) вместо долгоживущих ключей.
  • Динамическое обнаружение сервисов: разрешение конечных точек агентов-партнеров во время выполнения через Центральный реестр агентов, что исключает использование жестко закодированных URL-адресов и идентификаторов проектов.
  • Runtime Policy Agility: Transitioned pizza-seller-agent from Default Deny ( 403 Forbidden ) to Allowed ( 200 OK ) in real time via policy update, with zero container restarts.

cosmopup

Cosmopup says: "Agents are great—they do all the cross-project work while I focus on my primary objective: napping!"

Next Steps & Documentation