1. Wprowadzenie
W miarę jak organizacje wdrażają generatywną AI, architektury szybko ewoluują od samodzielnych, monolitycznych czatbotów do rozproszonych systemów wieloagentowych (Agent-to-Agent / A2A). W tych nowoczesnych topologiach agenty orkiestratora wysokiego poziomu koordynują złożone przepływy pracy w firmie, delegując zadania do wyspecjalizowanych agentów roboczych domeny, serwerów narzędzi Model Context Protocol (MCP) i baz danych przedsiębiorstwa w ramach niezależnych projektów w chmurze Google.
Jednak działanie systemów wieloagentowych na dużą skalę wiąże się z poważnymi wyzwaniami dotyczącymi bezpieczeństwa, zarządzania i operacji:
- Shadow Agent i rozrost narzędzi: gdy zespoły programistów wdrażają agentów w odizolowanych projektach bez scentralizowanego katalogu, organizacje tracą wgląd w to, jakie narzędzia i subagenci istnieją.
- Niemonitorowany ruch wychodzący między projektami: zezwalanie agentom na bezpośrednie, niesprawdzone trasy sieciowe stwarza ryzyko wydobycia danych i pomija granice zabezpieczeń.
- Niestabilne integracje zakodowane na stałe: kodowanie na stałe adresów URL agentów niższego poziomu i identyfikatorów silnika rozumowania tworzy niestabilne zależności, które przestają działać podczas uaktualniania lub ponownego wdrażania.
- Brak tożsamości o najmniejszych uprawnieniach: udostępnione konta usługi nie zapewniają kryptograficznej niezaprzeczalności na poziomie poszczególnych instancji agenta.
Aby rozwiązać te problemy, platforma Gemini Enterprise Agent Platform udostępnia ujednoliconą platformę sterującą do zarządzania i zapewniania łączności, która składa się z 4 głównych filarów:
- Brama agentów (
networkservices.googleapis.com): zarządzany, regionalny serwer proxy sieci i egzekwowania zasad. Działa w trybie ruchu wychodzącegoAGENT_TO_ANYWHERE, przechwytuje ruch wychodzący agenta, przekazuje oceny autoryzacji do rozszerzeń zabezpieczeń i kieruje żądania przez granice projektu. - Rejestr agentów (
agentregistry.googleapis.com): pojedynczy katalog usług dla przedsiębiorstw. Zapewnia scentralizowany, zweryfikowany katalog wszystkich dostępnych narzędzi, serwerów MCP i agentów równorzędnych w organizacji, umożliwiając dynamiczne automatyczne wykrywanie w czasie działania bez zakodowanych na stałe punktów końcowych. - Agent Identity & IAP v2 Governance (
iap.googleapis.comiiam.googleapis.com): kryptograficzna platforma tożsamości i dostępu. Agenty wykonawcze otrzymują unikalne, atestowane identyfikatory URN maszyn SPIFFE (principal://...). Ruch wychodzący jest oceniany pod kątem scentralizowanych ujednoliconych zasad dostępu IAM (UAP / IAP w wersji 2), które weryfikują uprawnienia uniwersalneiap.googleapis.com/resources.egressViaIAPza pomocą rozbudowanych warunków katalogu Common Expression Language (CEL) (destination.agent_registry.*). - Agent Runtime (silniki rozumowania): w pełni zarządzana, bezserwerowa platforma do wykonywania aplikacji opartych na agentach w języku Python, z natywnymi powiązaniami konfiguracji (
agent_gateway_config) z bramami centralnymi.
Scenariusz biznesowy ćwiczenia: zakupy żywności i napojów w wielu projektach
W tym ćwiczeniu utworzysz rzeczywisty ekosystem zakupowy obejmujący wiele projektów i będziesz nim zarządzać. Ekosystem ten będzie obejmować 3 różne projekty w chmurze Google Cloud:
- Centralny projekt zarządzania (
PROJECT_GOVERNANCE): należy do centralnego zespołu IT i SecOps, hostuje centralną bramę agentów, centralny rejestr agentów i ujednolicone zasady dostępu uprawnień. - Projekt Consumer Orchestrator (
PROJECT_CONCIERGE): należy do zespołu ds. zakupów i zawiera agenta obsługi zakupów, który dynamicznie wykrywa dostawców i kieruje zamówienia klientów. - Projekt dostawcy domeny (
PROJECT_SELLERS): należy do dostawców zewnętrznych lub dostawców działu i hostuje agenta sprzedawcy burgerów oraz agenta sprzedawcy pizzy.
Rys. 1. Architektura scentralizowanego zarządzania wieloma projektami
Dlaczego warto korzystać ze scentralizowanego zarządzania między projektami?
W dużych przedsiębiorstwach zespoły zajmujące się usługami i grupy badaczy danych tworzą agenty AI w dziesiątkach niezależnych projektów w chmurze Google Cloud. Zapewnienie każdemu zespołowi bezpośredniej kontroli nad rejestracją narzędzi, trasami sieci wychodzącej i zabezpieczeniami powoduje niekontrolowany wzrost liczby niesprawdzonych narzędzi, niespójne zasady DLP, niemonitorowany ruch wychodzący VPC i pofragmentowane dzienniki kontrolne.
Scentralizowane zarządzanie między projektami oddziela tworzenie zasad od wykonywania agentów:
- Centralny zespół IT i SecOps tworzy zasady bezpieczeństwa, sprawdza narzędzia i monitoruje ruch wychodzący w ramach jednego projektu scentralizowanego zarządzania.
- Zespoły ds. usług i aplikacji skupiają się wyłącznie na logice biznesowej w swoich niezależnych Agent Runtime Projects, łącząc się bezpośrednio z bramą centralną bez narzutu operacyjnego związanego z zarządzaniem lokalnymi sieciami VPC, połączeniami międzysieciowymi czy rozproszonymi silnikami zasad.
Rysunek 2. Trzypoziomowa architektura i granice zarządzania między projektami
Dwupoziomowy model określania zakresu tożsamości w ujednoliconych zasadach dostępu
Gdy agenty komunikują się przez centralną bramę agentów, Identity-Aware Proxy (IAP v2) ocenia dostęp na podstawie tożsamości agenta wywołującego (tożsamości opartej na SPIFFE, poświadczonej kryptograficznie, wydawanej automatycznie kontenerowi środowiska wykonawczego) w odniesieniu do globalnej zasady dostępu uprawnień:
- Poziom 1. Podstawowe interfejsy Google Cloud API (ogólne, za pomocą
principalSet://w regule 1): autoryzacja ruchu wychodzącego na poziomie projektu, która umożliwia wszystkim środowiskom wykonawczym agentów w projektach promieniowych dostęp do standardowych interfejsów API Google (aiplatform,iamcredentials,telemetry,agentregistry) na potrzeby wykrywania, generowania tokenów i wnioskowania. - Poziom 2. Narzędzia biznesowe i usługi A2A (szczegółowe uprawnienia za pomocą
principal://w regułach 2 i 3): rygorystyczny dostęp z jak najmniejszymi uprawnieniami powiązany z poszczególnymi instancjami silnika rozumowania, egzekwowany za pomocą warunków języka CEL (Common Expression Language) kierowanych na konkretne zarejestrowane usługi rejestru agentów (destination.agent_registry.agent.name).
Co utworzysz
- Scentralizowana brama agentów (
centralized-agw) w regioniePROJECT_GOVERNANCE - Rozszerzenie usługi autoryzacji IAP w wersji 2 i zasady autoryzacji w trybie ścisłego WYMUSZANIA (
failOpen: false) - Podstawowa ujednolicona zasada dostępu uprawnień (
uap-rules.json) i powiązanie zasad projektu - Uprawnienia agenta usługi do wielu projektów (
ar_agw_cross_project_sa) - Udostępniony centralny zasobnik przejściowy Google Cloud Storage (GCS)
- Odizolowani sprzedawcy burgerów i pizzy w regionie
PROJECT_SELLERS - Agent Concierge ds. zakupów z dynamicznym automatycznym wykrywaniem REST w
PROJECT_CONCIERGE - Rejestracje usług w centralnym rejestrze agentów z adresami URL mTLS obejmującymi wiele projektów
- Dynamiczne aktualizacje zasad ruchu wychodzącego IAP v2 z weryfikacją na żywo i audytami Cloud Logging
Rysunek 3. Sekwencja implementacji krok po kroku
Czego się nauczysz
- Jak skonfigurować uprawnienia agenta usługi w wielu projektach dla scentralizowanych bram
- Jak kierować ruch wychodzący z Agent Runtime przez centralną Bramę agentów w środowiskach obejmujących wiele projektów
- Jak przekazać uprawnienia bramy agentów do Identity-Aware Proxy (IAP w wersji 2) za pomocą rozszerzeń usługi (
iapPolicyVersion: "V2") - Jak tworzyć i wiązać ujednolicone zasady dostępu (UAP) uprawnień z regułami języka CEL (Common Expression Language) zarządzającymi zarejestrowanymi miejscami docelowymi w Agent Registry (
destination.agent_registry.*) - Jak wyeliminować zakodowane na stałe identyfikatory i adresy URL agentów, korzystając z automatycznego wykrywania w czasie działania w rejestrze agentów.
- Jak przetestować rzeczywiste blokowanie w ramach modelu zero-trust (
HTTP 403 Forbidden) i sprawdzić aktualizacje zasad na żywo w Cloud Logging.
Wymagania
- 3 projekty Google Cloud z włączonymi rozliczeniami:
PROJECT_GOVERNANCE: centralne zarządzanie, brama, rejestr i zasady dostępu uprawnieńPROJECT_CONCIERGE: agent orkiestratora usługi Concierge ds. zakupówPROJECT_SELLERS: agenty sprzedawcy specjalizującego się w burgerach i pizzy.
- Użytkownik uprawnień lub konto usługi z uprawnieniami
roles/ownerlub uprawnieniami administracyjnymi we wszystkich 3 projektach. - organizację Google Cloud (na potrzeby mapowania domeny zaufania SPIFFE).
- Google Cloud Shell lub komputer lokalny z zainstalowanym interfejsem wiersza poleceń
gcloud,python(w wersji 3.11 lub nowszej) iuv.
To już koniec wprowadzenia. Przejdźmy do sekcji Konfiguracja i środowisko.
2. Konfiguracja
Chociaż ta architektura obejmuje 3 różne projekty w chmurze Google Cloud, możesz wykonać wszystkie polecenia wdrażania w terminalu, pobierania repozytoriów i operacji przejściowych z poziomu jednego terminala Cloud Shell ustawionego na PROJECT_GOVERNANCE. Każdy skrypt wdrażania i polecenie gcloud wyraźnie kieruje do odpowiedniego projektu docelowego za pomocą flag interfejsu wiersza poleceń (--project).
Zacznij od uzyskania dostępu do wiersza poleceń projektu w chmurze Google Cloud:
- Cloud Shell na stronie
shell.cloud.google.com, - terminal lokalny z zainstalowanym interfejsem wiersza poleceń
gcloud,
Ustawianie kontekstu projektu
# 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
Zaktualizuj interfejs wiersza poleceń gcloud (zalecane)
# update gcloud components
gcloud components update --quiet
Ustawianie zmiennych środowiskowych powłoki
Wpisz identyfikatory projektu.
# 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"
Te zmienne powłoki zostaną automatycznie wygenerowane.
# 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}"
Tworzenie katalogu lokalnego na pliki konfiguracji
# create config folder
mkdir -p cfg
Przypisywanie roli administratora zasad dostępu na potrzeby ujednoliconych zasad dostępu
# 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
Włączanie logów kontrolnych dostępu do danych Cloud Audit Logs dla IAP w wersji 2
Domyślnie Google Cloud wyłącza logi kontrolne dostępu do danych, aby zapobiec niezamierzonym kosztom przechowywania. IAP w wersji 2 generuje decyzje dotyczące autoryzacji (granted=true i granted=false) jako logi kontrolne sprawdzania dostępu do danych, dlatego włącz logowanie ADMIN_READ, DATA_READ i DATA_WRITE dla iap.googleapis.com w 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)"
Włączanie wymaganych interfejsów Google Cloud API
# 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
Sprawdzanie, czy interfejsy API są włączone we wszystkich projektach
Zapewnienie, że wszystkie 3 projekty (PROJECT_GOVERNANCE, PROJECT_CONCIERGE i PROJECT_SELLERS) mają włączone dokładnie te same interfejsy API, zapewnia spójność operacyjną i zapobiega błędom generowania tokenów w czasie działania, błędom katalogowania schematów i przerwom w telemetrii.
Aby sprawdzić, czy interfejsy API są takie same we wszystkich 3 projektach, uruchom w Cloud Shell ten skrypt walidacji:
# 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
Przykładowe dane wyjściowe weryfikacji:
Wszystkie interfejsy API powinny być włączone.
✅ All 30 required APIs are ENABLED and synchronized across all three projects.
Konfigurowanie zasad organizacji
Domyślne zasady organizacji Google Cloud wymuszają ograniczenia, które ograniczają powiązania zasad dostępu uprawnień w wersji 3 z zasobami (constraints/iam.managed.disableAccessPolicyBinding).
Zastąp wszystkie odziedziczone ograniczenia zasad organizacji na poziomie projektu, jawnie ustawiając wartość enforce: false na „zezwól”.
# 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
To już koniec konfiguracji. Przejdź do sekcji Rejestrowanie podstawowych interfejsów API Google.
3. Rejestr agentów
Rejestrowanie usługi punktu końcowego podstawowych interfejsów API Google
Brama agentów wymaga zarejestrowania adresów URL interfejsów API Google w centralnym rejestrze agentów, aby agenty skonfigurowane za pomocą agent_gateway_config mogły bezpiecznie kierować ruch wychodzący do podstawowych usług backendu Google Cloud (takich jak aiplatform, dane logowania uprawnień i telemetria).
Tworzenie agenta core-gapi-services w rejestrze agentów
# 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
Przechwyć identyfikator zasobu punktu końcowego interfejsów API Core
# 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}"
Różnice między principalSet a principal w tożsamości agenta
W Google Cloud IAM i Gemini Enterprise Agent Platform tożsamości maszyn wydawane kontenerom agentów wykonawczych używają kryptograficznie poświadczonych identyfikatorów SPIFFE URN ocenianych przez Identity-Aware Proxy (IAP v2). Podczas konfigurowania ujednoliconych zasad dostępu uprawnień możesz kierować na konkretny pojedynczy principal lub na principalSet oparty na atrybutach:
Wymiar |
|
|
Składnia uprawnień |
|
|
Szczegółowość | Szczegółowe (na poziomie instancji): identyfikuje pojedynczą, konkretną instancję kontenera silnika rozumowania. | Ogólne (na poziomie projektu): identyfikuje wszystkie silniki rozumowania, które mają wspólny atrybut projektu. |
Wzorzec URN |
|
|
Przypadek użycia w Agent Platform | Poziom 2 (narzędzia biznesowe i A2A): autoryzowanie określonych agentów orkiestratora do wywoływania narzędzi domeny docelowej (np. Concierge zakupów $ ightarrow$ sprzedawca burgerów). | Poziom 1 (infrastruktura podstawowa): przyznanie wszystkim agentom w projekcie dostępu do interfejsów Google Cloud API ( |
Wpływ cyklu życia | Jeśli agent zostanie usunięty i utworzony ponownie, jego nowy identyfikator wyszukiwarki będzie wymagał zaktualizowanego powiązania zasady uprawnień. | Automatycznie stosuje się do nowo wdrożonych agentów w tym projekcie bez dodatkowych aktualizacji uprawnień. |
Zarządzanie deklaratywne za pomocą ujednoliconych zasad dostępu (UAP / IAP v2)
W starszej wersji IAP v1 zasady ruchu wychodzącego były dołączane bezpośrednio do poszczególnych zasobów Agent Registry za pomocą gcloud beta iap web add-iam-policy-binding. W przypadku IAP v2 i ujednoliconych zasad dostępu powiązania poszczególnych zasobów są eliminowane na rzecz jednej, scentralizowanej zasady dostępu uprawnień (cfg/uap-rules.json).
Podstawowa autoryzacja ruchu wychodzącego dla core-gapi-services zostanie skonfigurowana jako Reguła 1 w ujednoliconych zasadach dostępu w sekcji 5, co zapewni, że wszystkie kontenery agentów będą miały ustanowione podstawowe trasy ruchu wychodzącego przed wdrożeniem.
Więcej informacji technicznych o identyfikatorach podmiotów zabezpieczeń i mechanizmach Workload Identity znajdziesz w tych artykułach:
- Google Cloud IAM: identyfikatory i zbiory podmiotów zabezpieczeń
- Jak działa tożsamość agenta
- Konfigurowanie ujednoliconych zasad dostępu uprawnień dla bramy agentów
To już koniec rejestracji punktu końcowego podstawowych interfejsów API. Przejdź do sekcji Wdrażanie scentralizowanej bramy agentów.
4. Brama agentów
Wdrażanie scentralizowanej bramy agentów
Wdróż scentralizowaną bramę agentów (centralized-agw) w trybie ruchu wychodzącego AGENT_TO_ANYWHERE w projekcie $PROJECT_GOVERNANCE.
Definiowanie pliku manifestu konfiguracji bramy
Utwórz cfg/${AGW_NAME}.yaml na potrzeby zarządzania ruchem wychodzącym:
# 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
Importowanie konfiguracji bramy agentów
# import and create agent gateway
gcloud network-services agent-gateways import ${AGW_NAME} \
--source="cfg/${AGW_NAME}.yaml" \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Weryfikowanie szczegółów bramy agentów
# show agent gateway status
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Przykładowe dane wyjściowe:
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'
To już koniec wdrażania bramy. Teraz przejdź do sekcji Konfigurowanie autoryzacji.
5. Autoryzacja
Skonfiguruj autoryzację bramy agentów i podstawową platformę UAP
Brama agentów zabezpiecza ruch wychodzący narzędzi i agentów oraz nim zarządza przy użyciu zasad autoryzacji (networksecurity.authzPolicies) zintegrowanych z ujednoliconymi zasadami dostępu (UAP) Identity-Aware Proxy (IAP w wersji 2).
Omówienie architektury autoryzacji
Rysunek 4. Omówienie architektury autoryzacji
Architektura autoryzacji składa się z 3 połączonych ze sobą warstw:
- Rozszerzenie usługi IAP (
authzExtension): zasób regionalny skonfigurowany z użyciemservice: iap.googleapis.com,metadata: iapPolicyVersion: "V2"ifailOpen: falsena potrzeby rygorystycznego egzekwowania modelu zero-trust na granicy. - Zasady autoryzacji bramy (
authzPolicy): zasób regionalny kierujący do bramy agentów za pomocąpolicyProfile: REQUEST_AUTHZiaction: CUSTOM, który przekierowuje kontrole autoryzacji do rozszerzenia autoryzacji IAP. - Ujednolicone zasady dostępu i powiązanie uprawnień (
accessPolicyipolicyBinding): globalny zasób uprawnień w wersji 3 oceniany przez IAP. Sprawdza uprawnienia uniwersalneiap.googleapis.com/resources.egressViaIAPpod kątem tożsamości SPIFFE elementu wywołującego i warunków katalogu CEL.
Krok 1. Utwórz i zaimportuj rozszerzenie autoryzacji IAP w wersji 2
Utwórz plik manifestu rozszerzenia usługi z iapPolicyVersion: "V2" i failOpen: false w trybie ścisłym 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
Zaimportuj rozszerzenie autoryzacji:
# 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}
Sprawdź, czy rozszerzenie Authz jest aktywne:
# describe authz extension
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Przykładowe dane wyjściowe:
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
Krok 2. Utwórz i zaimportuj zasadę autoryzacji bramy
Utwórz konfigurację zasad autoryzacji, która jest dołączona do bramy agentów i deleguje weryfikację żądań do rozszerzenia autoryzacji 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
Zaimportuj zasadę autoryzacji:
# 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}
Sprawdź aktywną zasadę autoryzacji:
# describe authz policy
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-profile-iap \
--location=${REGION} \
--project=${PROJECT_GOVERNANCE}
Krok 3. Utwórz początkową ujednoliconą zasadę dostępu (reguła 1: podstawowe interfejsy API Google)
Utwórz cfg/uap-rules.json z regułą 1, która autoryzuje 3 principalSet projektu do uzyskiwania dostępu do 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
Krok 4. Utwórz i powiąż zasadę dostępu uprawnień
Utwórz globalną zasadę dostępu uprawnień:
# create global IAM access policy
gcloud iam access-policies create ${UAP_POLICY_NAME} \
--details-rules=cfg/uap-rules.json \
--project=${PROJECT_GOVERNANCE} \
--location=global
Powiąż zasadę dostępu z 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
Sprawdź, czy powiązanie zasady jest aktywne:
# verify policy binding
gcloud iam policy-bindings describe ${UAP_BINDING_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global
Przykładowe dane wyjściowe:
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}
Ruch wychodzący podstawowego interfejsu Google Cloud API jest teraz bezpiecznie autoryzowany we wszystkich 3 projektach w trybie ścisłym (ENFORCE).
To kończy konfigurację autoryzacji bramy. Przejdź do sekcji Konfigurowanie uprawnień obejmujących wiele projektów.
6. Uprawnienia między projektami
Konfigurowanie uprawnień między projektami
W tej topologii obejmującej wiele projektów środowiska wykonawcze Agent Runtime znajdują się w projektach podrzędnych (PROJECT_CONCIERGE i PROJECT_SELLERS), a centralna Brama agentów i Agent Registry znajdują się w projekcie PROJECT_GOVERNANCE.
Projekty Google Cloud są odizolowanymi obwodami zabezpieczeń, dlatego dostęp między projektami musi być wyraźnie przyznany na 2 warstwach operacyjnych:
- Platforma sterująca (czas wdrażania): podczas wdrażania kontenera agenta skonfigurowanego za pomocą
--agent-gateway-configAgent Runtime Service Agent (service-) projektu podrzędnego musi podłączyć kontener do bramy centralnej. Tworzymy minimalną rolę niestandardową (@gcp-sa-aiplatform.iam.gserviceaccount.com ar_agw_cross_project_sa) przyznającą uprawnienianetworkservices.agentGateways.use,getioperations.getw usłudzePROJECT_GOVERNANCE. - Płaszczyzna danych (wykonywanie w środowisku wykonawczym):
- Wykrywanie katalogu: tożsamości promienia wymagają uprawnienia
roles/agentregistry.viewerwPROJECT_GOVERNANCE, aby dynamicznie rozpoznawać docelowe punkty końcowe agenta. - Wywołanie docelowe: agent Concierge potrzebuje uprawnień
roles/aiplatform.userwPROJECT_SELLERS, aby wykonywać zapytania do silników rozumowania sprzedawcy.
- Wykrywanie katalogu: tożsamości promienia wymagają uprawnienia
Tworzenie niestandardowej roli uprawnień w: 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"
Przypisywanie roli niestandardowej do agentów usługi 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
To już koniec konfiguracji uprawnień obejmujących wiele projektów. Przejdź do sekcji Wdrażanie agentów sprzedawcy i Concierge.
7. Agent Runtime
Wdrażanie agentów sprzedawcy i usługi Concierge
Baza kodu aplikacji z wieloma agentami i skrypty wdrażania używane w tym ćwiczeniu są przechowywane w zdalnym repozytorium Google Cloud na GitHubie. Te kroki spowodują sklonowanie repozytorium lokalnie, skopiowanie niezbędnych plików do bieżącej struktury katalogu roboczego, wyczyszczenie plików tymczasowych i zainstalowanie zależności za pomocą uv.
Pobieranie artefaktów zdalnych
# 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
Tworzenie współdzielonego centralnego zasobnika przejściowego
# 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"
Jak działa wiązanie bramy agentów między projektami
W tym kroku wdrożysz agentów sprzedawcy w projekcie promienia (PROJECT_SELLERS) i skonfigurujesz ich tak, aby kierowali ruch wychodzący przez centralną bramę agentów w projekcie 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)
Ponieważ reguła 1 została ustanowiona wcześniej w ujednoliconych zasadach dostępu, żądania inicjowania kontenera do interfejsów Google Cloud API są dozwolone przez bramę bez przerw.
Wdrażanie agentów sprzedających burgery i pizzę w 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}
Sprawdzanie routingu bramy sprzedawcy
# 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
Wdrażanie agenta asystenta zakupów w: 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}
Weryfikacja routingu bramy zakupowej
# 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}'
Dane wyjściowe powinny zawierać tożsamość i projekt Agent Runtime agenta Concierge oraz powiązanie z Bramą agentów projektu zarządzania.
{
"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"
}
}
}
To już koniec wdrażania agentów… Przejdźmy do sekcji Rejestrowanie agentów w centralnym rejestrze agentów.
8. Rejestr obejmujący wiele projektów
Rejestrowanie agentów w centralnym rejestrze agentów
Zarejestruj wszystkie 3 agenty w centralnym rejestrze agentów w regionie PROJECT_GOVERNANCE, używając regionalnych punktów końcowych mTLS między projektami i numerycznych numerów projektów.
Rejestrowanie usług jako agentów innych niż agent A2A w Agent Registry
# 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
Przechwytywanie identyfikatorów bazowych rejestru agentów
# 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}"
To kończy konfigurację rejestru. Przejdź do sekcji Konfigurowanie zasad ruchu wychodzącego A2A.
9. Zasady UAP
Konfigurowanie zasad ruchu wychodzącego A2A w ujednoliconych zasadach dostępu
W architekturze domyślnej odmowy bramy agentów w trybie ścisłym ENFORCE:
- Reguła 1 (podstawowe interfejsy Google Cloud API): umożliwia kontenerom agentów we wszystkich 3 projektach dostęp do
core-gapi-services. - Reguła 2 (Burger Seller Agent: ALLOW): zezwala instancji Purchasing Concierge Agent na wywoływanie agenta Burger Seller Agent.
- Agent sprzedawcy pizzy (domyślnie ODMOWA): celowo pominięty w regułach zasad. W trybie
ENFORCE(failOpen: false) każda próba wywołania sprzedawcy pizzy przez Concierge zostanie natychmiast zakończona na granicy bramy z błędemHTTP 403 Forbidden.
Formułowanie tożsamości agenta 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}"
Zaktualizuj plik manifestu aktualizacji za pomocą reguł 1 i 2
Aby bezpiecznie zaktualizować zasadę dostępu bez nadpisywania istniejących reguł, zdefiniuj pełny skonsolidowany plik manifestu zawierający Regułę 1 (podstawowe interfejsy API Google) i Regułę 2 (Burger Seller Agent):
# 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
Zastosuj zaktualizowaną zasadę dostępu
Zastosuj skonsolidowany plik manifestu reguł deklaratywnie za pomocą polecenia --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
Sprawdzanie szczegółów zasady dostępu uprawnień
# inspect updated access policy
gcloud iam access-policies describe ${UAP_POLICY_NAME} \
--project=${PROJECT_GOVERNANCE} \
--location=global
Przykładowe dane wyjściowe:
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
To już koniec konfiguracji zasad. Przejdź do sekcji Testowanie i weryfikowanie zasad zarządzania.
10. Sprawdzanie zasad
Testowanie i weryfikowanie zasad zarządzania za pomocą Cloud Logging
W tej sekcji przetestujesz interakcje między agentami w różnych projektach w Laboratorium AI Agent Runtime, zaobserwujesz rzeczywiste blokowanie obwodowe HTTP 403 Forbidden w trybie ścisłym ENFORCE, zmodyfikujesz ujednolicone zasady dostępu na żywo i sprawdzisz natychmiastowe zatwierdzanie zamówień.
Krok 1. Otwórz Laboratorium AI w Agent Runtime w PROJECT_CONCIERGE
- Otwórz konsolę Google Cloud.
- Na górnym pasku selektora projektów przełącz się na
PROJECT_CONCIERGE. - W menu nawigacyjnym kliknij Agent Platform > Agenty > Wdrożenia.
- Kliknij
purchasing-concierge-adk. - Wybierz Playground, aby otworzyć interaktywny interfejs czatu po prawej stronie ekranu.
Krok 2. Przetestuj zamówienie burgera (dopasowanie do reguły 2 -> 200 OK)
W oknie czatu w Playground prześlij tego prompta:
I would like 10 Classic Cheeseburgers. Place this order now.
Jeśli wymagana jest odpowiedź z potwierdzeniem, prześlij tę odpowiedź:
Confirmed, please place the order.
Możesz też przetestować programowo z Cloud Shell lub terminala:
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)
"
Jeśli potrzebujesz odpowiedzi z potwierdzeniem, użyj tego polecenia:
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'])
"
Co dzieje się za kulisami:
- Dynamiczne wykrywanie: podczas uruchamiania sesji usługa Purchasing Concierge wysłała zapytanie do centralnego rejestru agentów w regionie
PROJECT_GOVERNANCE(za pomocącore-gapi-servicesprzez Bramę agentów autoryzowaną przez regułę 1), aby wykryć regionalny punkt końcowy mTLS dla usługiburger-seller-agent. - Rozpoznawanie intencji i wywoływanie A2A: Gemini w usłudze Purchasing Concierge analizuje intencję zamówienia jedzenia i wywołuje agenta Burger Seller Agent za pomocą wychodzącego wywołania RPC do
https://${REGION}-aiplatform.mtls.googleapis.com/.../reasoningEngines/${BURGER_ENGINE_ID}. - Przechwytywanie przez bramę i propagacja SPIFFE: ruch wychodzący jest przechwytywany przez
agent_gateway_configi kierowany do centralnej bramy agentów wPROJECT_GOVERNANCE, przenosząc kryptograficzną tożsamość SPIFFE usługi Concierge (principal://...). - Ocena zasad IAP w wersji 2: centralna brama agentów wywołuje rozszerzenie autoryzacji IAP (
authzExtension). IAP w wersji 2 ocenia regułę 2 w ujednoliconych zasadach dostępu uprawnień. Ponieważ element wywołujący pasuje do${CONCIERGE_SPIFFE_PRINCIPAL}, a element docelowy pasuje doburger-seller-agent, IAP zwracaALLOW(granted: true). - Wykonywanie między projektami: brama agentów przekazuje autoryzowane żądanie między projektami do
PROJECT_SELLERS, gdzie silnik rozumowania Burger Seller przetwarza zamówienie i zwraca potwierdzenie.
Oczekiwana odpowiedź:
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
Krok 3. Sprawdź dzienniki kontrolne bramy agentów i IAP v2 (HTTP 200 / ALLOWED)
Zapytanie o logi żądań bramy agentów w 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
)"
Logi powinny rejestrować ruch wychodzący z obu projektów typu spoke (PROJECT_CONCIERGE i PROJECT_SELLERS) z polami ruchu wychodzącego, takimi jak wywołania wnioskowania Gemini (generateContent), dane telemetryczne Cloud Trace (/v1/traces) i wyszukiwania danych uwierzytelniających uprawnień, które są w przejrzysty sposób przechwytywane i autoryzowane przez regułę 1 (core-gapi-services).
Wyślij zapytanie do logów dostępu do danych logów kontrolnych Cloud IAP w wersji 2, aby sprawdzić wersję zasad 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
)"
Przykładowe dane wyjściowe:
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
Krok 4. Przetestuj zamawianie pizzy (domyślna odmowa -> HTTP 403 Forbidden ENFORCED)
W tym samym oknie czatu w Playground prześlij tego prompta z zamówieniem pizzy:
I would like 10 BBQ Chicken Pizzas. Place this order now.
Jeśli wymagana jest odpowiedź z potwierdzeniem, prześlij tę odpowiedź:
Confirmed, please place the order.
Możesz też przetestować programowo z Cloud Shell lub terminala:
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)
"
Jeśli potrzebujesz odpowiedzi z potwierdzeniem, użyj tego polecenia:
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'])
"
Oczekiwana odpowiedź:
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.
Co dzieje się za kulisami:
- Dynamiczne wykrywanie: agent obsługi zakupów rozwiązał punkt końcowy
pizza-seller-agentz centralnego rejestru agentów podczas uruchamiania. - Rozpoznanie intencji i wywołanie A2A: Gemini w usłudze Concierge ds. zakupów próbuje wysłać prośbę o zamówienie pizzy do punktu końcowego sprzedawcy pizzy w
PROJECT_SELLERS. - Przechwytywanie przez bramę: wychodzące wywołanie RPC jest przechwytywane przez
agent_gateway_configi kierowane do centralnej bramy agentów. - Ocena zasad IAP w wersji 2 (domyślna odmowa): centralna brama agentów wywołuje IAP w wersji 2. Ponieważ w ujednoliconych zasadach dostępu nie ma reguły pasującej do
pizza-seller-agent, IAP zwraca błądDENY(granted: false). - Rygorystyczna blokada obwodowa: ponieważ rozszerzenie autoryzacji jest w trybie WYMUSZANIA (
failOpen: false), centralna brama agentów natychmiast przerywa połączenie wychodzące i zwraca błądHTTP 403 Forbidden. Ruch nigdy nie opuszcza bramy i nie dociera doPROJECT_SELLERS.
Krok 5. Sprawdź dzienniki bramy agentów pod kątem zablokowanych żądań (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
)"
Przykładowe dane wyjściowe logu odmowy:
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
Wyślij zapytanie do logów kontrolnych dostępu do danych IAP w wersji 2, aby sprawdzić decyzję o odmowie:
# 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
)"
Przykładowe dane wyjściowe logu kontrolnego odmowy:
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
Krok 6. Dynamicznie przyznaj agentowi Pizza dostęp do ruchu wychodzącego
Utwórz nową cfg/uap-rules-update-3.json, aby uwzględnić Regułę 1 (podstawowe interfejsy API), Regułę 2 (agent sprzedawcy burgerów) i nową Regułę 3 (agent sprzedawcy pizzy).
# 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
Zastosuj aktualizację zasad na żywo:
# 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
Krok 7. Ponownie wyślij zapytanie do agenta Pizza (natychmiastowy sukces 200 OK)
W oknie czatu w Playgroundzie ponownie prześlij prompta z zamówieniem pizzy:
I would like 10 BBQ Chicken Pizzas. Place this order now.
Jeśli wymagana jest odpowiedź z potwierdzeniem, prześlij tę odpowiedź:
Confirmed, please place the order.
Możesz też przetestować programowo z Cloud Shell lub terminala:
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)
"
Jeśli potrzebujesz odpowiedzi z potwierdzeniem, użyj tego polecenia:
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'])
"
Oczekiwana odpowiedź:
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**
Co dzieje się za kulisami:
- Dynamiczne odświeżanie zasad: aktualizacja ujednoliconych zasad dostępu uprawnień IAM zaczyna obowiązywać natychmiast w silniku oceny IAP bez przestojów i bez konieczności ponownego wdrażania kontenerów.
- Wywołanie A2A: Concierge wysyła żądanie przez centralną bramę agentów.
- Ocena zasad IAP w wersji 2 (zatwierdzenie): IAP w wersji 2 dopasowuje regułę 3, weryfikuje tożsamość elementu wywołującego i docelowe wyrażenie CEL, a następnie zwraca
ALLOW(granted: true). - Wykonywanie w różnych projektach: centralna brama agentów przekazuje autoryzowany ruch do
PROJECT_SELLERS, gdzie sprzedawca pizzy przetwarza zamówienie.
Krok 8. Sprawdź dzienniki bramy agentów pod kątem przyznanych żądań dotyczących pizzy
# 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
)"
Przykładowe dane wyjściowe logu przyznania dostępu:
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
To koniec testowania i weryfikacji. Przejdź do sekcji Czyszczenie.
11. Czyszczenie
Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym ćwiczeniu, wykonaj czynności związane z usuwaniem w ścisłej kolejności odwrotnej do zależności:
1. Czyszczenie wdrożeń silnika rozumowania
Uruchom dołączony skrypt cleanup_old_deployments.py w obu projektach środowiska wykonawczego, aby usunąć silniki rozumowania i poczekać na zakończenie ich długo trwających operacji:
# 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}
Możesz też wyświetlić listę silników rozumowania i usunąć je w tekście:
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. Usuwanie usług rejestru agentów
# 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. Usuwanie powiązania ujednoliconej zasady dostępu i zasady dostępu uprawnień
# 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. Usuwanie bramy agentów i zasad zabezpieczeń
# 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. Usuwanie międzyprojektowych powiązań uprawnień i roli niestandardowej
# 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
Jeśli podczas fazy konfiguracji przypisano role roles/iam.accessPolicyAdmin i roles/resourcemanager.projectIamAdmin, usuń je z aktywnego konta użytkownika, aby przywrócić jak najmniejsze uprawnienia:
# 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. Cofanie logowania danych kontrolnych i ograniczeń zasad organizacji
# 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. Przywracanie ograniczeń wynikających z zasad organizacji
# 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. Usuwanie udostępnionego zasobnika przejściowego GCS i artefaktów lokalnych
# 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
To koniec części dotyczącej czyszczenia. Przejdź do podsumowania.
12. Podsumowanie
Gratulacje! Udało Ci się wdrożyć architekturę Agent-to-Agent (A2A) obejmującą wiele projektów w Google Cloud i zarządzać nią przy użyciu środowiska wykonawczego agenta Vertex AI, centralnej bramy agentów, rejestru agentów i ujednoliconych zasad dostępu (UAP) uprawnień.
Podsumowanie kluczowych pojęć
- Scentralizowany obwód ruchu wychodzącego: kontenery środowiska wykonawczego połączonego fragmentu (
PROJECT_CONCIERGE,PROJECT_SELLERS) są kierowane przez centralną bramę agentów wPROJECT_GOVERNANCEza pomocąagentGatewayConfig. - Zarządzanie deklaratywne (UAP): zastąpiliśmy rozproszone powiązania poszczególnych zasobów jedną zasadą dostępu uprawnień, którą można kontrolować i która jest oceniana w bramie przez IAP w wersji 2.
- Tożsamość kryptograficzna: wymuszanie jak najmniejszych uprawnień do ruchu wychodzącego przy użyciu tożsamości SPIFFE kontenera (
principal://...) zamiast kluczy o długim okresie ważności. - Dynamiczne wykrywanie usług: punkty końcowe agentów równorzędnych są rozpoznawane w czasie działania za pomocą centralnego rejestru agentów, co eliminuje konieczność kodowania na stałe adresów URL i identyfikatorów projektów.
- Elastyczność zasad środowiska wykonawczego: zmieniono
pizza-seller-agentz domyślnej odmowy (403 Forbidden) na dozwolone (200 OK) w czasie rzeczywistym przez aktualizację zasad, bez ponownego uruchamiania kontenera.

Cosmopup mówi: „Agenci są świetni – wykonują całą pracę między projektami, podczas gdy ja mogę skupić się na moim głównym celu: drzemce”.
Dalsze kroki i dokumentacja
- Omówienie platformy agentów Gemini Enterprise
- Konfigurowanie i wdrażanie bramy agentów
- Szczegółowe omówienie tożsamości agenta i atestu SPIFFE
- Ujednolicone zasady dostępu i atrybuty CEL w uprawnieniach
- Omówienie katalogu usług rejestru agentów
- Zabezpieczenia Model Armor i Sensitive Data Protection
- Interfejsy Private Service Connect (PSC-I) z bramą agentów