1. Giới thiệu
Lớp học lập trình này khám phá khả năng kết nối truyền dữ liệu tĩnh IP cho Gemini Enterprise bằng Agent Gateway ở chế độ agent-to-anywhere (truyền dữ liệu). Bạn sẽ định cấu hình một ứng dụng Gemini Enterprise để gọi một máy chủ Giao thức ngữ cảnh mô hình (MCP) tuỳ chỉnh, được bảo vệ bằng danh sách cho phép IP nguồn nghiêm ngặt và xác thực OAuth 2.0, bằng cách định tuyến tất cả lưu lượng truy cập đi thông qua Agent Gateway bằng cách sử dụng cấu hình mẫu kết nối. Điểm đính kèm mạng Private Service Connect (PSC) kết nối Agent Gateway với mạng VPC và Cloud NAT cung cấp một địa chỉ IP bên ngoài ổn định cho lưu lượng truy cập Internet đi ra.
Theo mặc định, các kết nối đi từ Gemini Enterprise đến các điểm cuối trên Internet công cộng bắt nguồn từ các nhóm địa chỉ IP động, dùng chung của Google. Các nhóm này không thể được ghim vào một quy tắc danh sách cho phép IP duy nhất do khách hàng sở hữu. Việc ghép nối Agent Gateway với một AgentConnectivityTemplate ở chế độ ALL_TRAFFIC sẽ định tuyến tất cả lưu lượng truy cập đi của tác nhân vào mạng VPC. Tại đây, Cloud NAT sẽ chuyển đổi các kết nối liên kết với Internet thành một địa chỉ IPv4 bên ngoài tĩnh được đặt trước mà bạn kiểm soát, đồng thời duy trì hoạt động quản trị công cụ MCP tập trung thông qua Agent Registry và Identity-Aware Proxy (IAP).
Sản phẩm bạn sẽ tạo ra
- Mẫu kết nối tác nhân (
vpcEgress: ALL_TRAFFIC) và Cổng tác nhân hoạt động ở chế độ truyền dữ liệu ra (agent-to-anywhere) với quy trình xác minh điểm cuối Sổ đăng ký tác nhân - Mạng VPC, điểm đính kèm mạng PSC, Cloud Router và cổng Cloud NAT được liên kết với một địa chỉ IPv4 bên ngoài tĩnh được đặt trước
- Máy chủ tài nguyên MCP HTTP có thể truyền phát bên ngoài (
mcp-sprockets) được Caddy TLS hỗ trợ, bị hạn chế nghiêm ngặt theo các quy tắc tường lửa đối với IP tĩnh Cloud NAT và xác minh mã thông báo Google OAuth 2.0 Bearer do người dùng uỷ quyền dựa trênhttps://oauth2.googleapis.com/tokeninfo - Màn hình xin phép bằng OAuth 2.0 của Nền tảng xác thực của Google và thông tin xác thực ứng dụng OAuth 2.0 của ứng dụng web (
accounts.google.comvàoauth2.googleapis.com/token) - Mục nhập danh mục máy chủ MCP của Sổ đăng ký tác nhân và quy cách công cụ (
toolspec.json) - Tiện ích uỷ quyền Identity-Aware Proxy (IAP) và chính sách uỷ quyền Cổng cho Cổng tác nhân
- Ứng dụng Gemini Enterprise được liên kết với Agent Gateway và kết nối với một kho lưu trữ dữ liệu MCP tuỳ chỉnh OAuth 2.0 được nhập từ Agent Registry
Hình 1. Cấu trúc lớp học lập trình
Kiến thức bạn sẽ học được
- Cách định cấu hình
AgentConnectivityTemplatebằngvpcEgress: ALL_TRAFFICđể định tuyến tất cả lưu lượng truy cập Agent Gateway đi ra vào một mạng VPC - Cách đặt trước một địa chỉ IPv4 tĩnh bên ngoài và liên kết địa chỉ đó với Cloud NAT trên một mạng con đính kèm mạng PSC
- Cách triển khai một Máy chủ tài nguyên MCP HTTP có thể truyền trực tuyến bên ngoài, xác minh mã thông báo Bearer OAuth 2.0 của Google (
oauth2.googleapis.com/tokeninfo) và hạn chế nghiêm ngặt tường lửa đầu vào của máy chủ này đối với IP tĩnh Cloud NAT (${NAT_EXT_IP}/32) - Cách định cấu hình thông tin đăng nhập ứng dụng Google Identity OAuth 2.0 và đăng ký máy chủ MCP cũng như giản đồ công cụ của máy chủ đó trong Agent Registry
- Cách kết nối máy chủ MCP OAuth 2.0 đã đăng ký với Gemini Enterprise và định tuyến các lệnh gọi công cụ do người dùng uỷ quyền thông qua Agent Gateway
- Cách xác thực tính năng dịch IP tĩnh, xác minh danh tính người dùng cuối bằng OAuth 2.0 (
authenticated_user) và thực thi chính sách cổng bằng cách sử dụng các lệnh CLI và Cloud Logging
Bạn cần có
- Một dự án trên Google Cloud đã bật tính năng thanh toán
- Giấy phép Gemini Enterprise đang hoạt động hoặc chương trình dùng thử 30 ngày
- Quyền IAM để cung cấp các dịch vụ mạng, Chính sách tổ chức, Gemini Enterprise và tài nguyên Nền tảng tác nhân
- Một trình bao tương thích với POSIX (
bashhoặczsh) đã cài đặt Google Cloud CLI (gcloud),curlvàjq
Đến đây là kết thúc phần giới thiệu... tiếp theo là phần Khái niệm.
2. Khái niệm
Trình tự triển khai
Lớp học lập trình này triển khai cơ sở hạ tầng mạng và quản trị trước để các đường dẫn truyền dữ liệu tĩnh qua IP và các chế độ kiểm soát cổng hoạt động trước khi đăng ký và kết nối các công cụ MCP với Gemini Enterprise:
- Cơ sở hạ tầng mạng: Đặt trước các địa chỉ IPv4 tĩnh bên ngoài và cung cấp VPC truyền dữ liệu ra, mạng con đính kèm PSC, tệp đính kèm mạng PSC, Cloud Router, cổng Cloud NAT và các quy tắc tường lửa mạng MCP bên ngoài.
- Mẫu kết nối tác nhân và Agent Gateway: Triển khai
AgentConnectivityTemplate(vpcEgress: ALL_TRAFFIC) vàAgentGatewaytheo khu vực ở chế độ truyền dữ liệu ra (AGENT_TO_ANYWHERE) có tích hợp Sổ đăng ký tác nhân (registries). - Chính sách uỷ quyền: Định cấu hình tiện ích uỷ quyền IAP (
AuthzExtension), Chính sách uỷ quyền cổng (AuthzPolicy) và Chính sách truy cập hợp nhất IAM phiên bản 3 (AccessPolicyvàPolicyBinding). - Triển khai và đăng ký máy chủ MCP: Triển khai Máy chủ tài nguyên OAuth 2.0
mcp-sprocketsbên ngoài đằng sau Caddy TLS, xác minh việc thực thi Google OAuth 2.0tokeninfo, khoá tường lửa đầu vào một cách nghiêm ngặt đối với IP tĩnh Cloud NAT (${NAT_EXT_IP}/32) và đăng ký các thông số kỹ thuật về dịch vụ và công cụ (get_sprocketsvàget_sprocket_by_id) trong Sổ đăng ký tác nhân. - Ứng dụng Gemini Enterprise và ứng dụng OAuth 2.0: Định cấu hình nhà cung cấp danh tính Google, giấy phép dùng thử, màn hình đồng ý OAuth 2.0 và thông tin đăng nhập của ứng dụng web (
OAUTH_CLIENT_IDvàOAUTH_CLIENT_SECRET), tạo ứng dụng Gemini Enterprise (Engine) và liên kết lưu lượng truy cập đi với Cổng tác nhân (agentGatewaySetting). - Nhập trình kết nối dữ liệu MCP tuỳ chỉnh: Tạo và kích hoạt trình kết nối dữ liệu
REGISTRY_MCP(:setUpDataConnector) được định cấu hình bằngauth_type: "OAUTH"để liên kết kho lưu trữ dữ liệu hỗ trợ máy chủ MCP đã đăng ký với ứng dụng Gemini Enterprise. - Xác thực: Hoàn tất quy trình đồng ý OAuth 2.0 một lần của người dùng, gọi các công cụ MCP thông qua trợ lý Gemini Enterprise (xác nhận cả
egress_source_ipvàauthenticated_user), đồng thời xác minh việc thực thi chính sách và bản dịch NAT IP tĩnh trong Cloud Logging.
Kiến trúc Máy chủ tài nguyên MCP được bảo vệ bằng OAuth + IdP trung tâm
Trong quá trình triển khai doanh nghiệp, hoạt động quản lý danh tính và thực thi công cụ tuân theo quy trình phân tách vai trò OAuth 2.0 tiêu chuẩn giữa Nhà cung cấp dịch vụ danh tính (Máy chủ uỷ quyền) tập trung và Máy chủ tài nguyên MCP được bảo vệ:
Vai trò OAuth 2.0 | Thành phần trong Lớp học lập trình này | Trách nhiệm |
Chủ sở hữu tài nguyên | Người dùng cuối ( | Đăng nhập vào ứng dụng web Gemini Enterprise và cấp sự đồng ý trong quy trình uỷ quyền OAuth 2.0 một lần gồm 3 bước. |
Ứng dụng OAuth 2.0 | Gemini Enterprise | Giữ |
Máy chủ uỷ quyền | Google Identity OAuth 2.0 ( | Xác thực người dùng trong quá trình chuyển hướng đồng ý của trình duyệt và cấp mã truy cập cũng như mã làm mới OAuth 2.0 cho Gemini Enterprise. |
Máy chủ tài nguyên | Máy chủ | Thực thi danh tính mạng Lớp 3 bằng tường lửa VPC ( |
Vì quá trình chuyển hướng sự đồng ý của trình duyệt (accounts.google.com) và trao đổi mã thông báo qua kênh phụ (oauth2.googleapis.com/token) diễn ra đối với các điểm cuối OAuth 2.0 do Google quản lý, nên tường lửa máy chủ MCP bên ngoài chỉ nhận được các yêu cầu JSON-RPC MCP thời gian chạy (POST /mcp) từ Agent Gateway thông qua Cloud NAT, cho phép tường lửa đầu vào của máy chủ này bị khoá chặt thành ${NAT_EXT_IP}/32.
Mô hình tài nguyên Discovery Engine
Ứng dụng Gemini Enterprise (được biểu thị dưới dạng tài nguyên Engine trong Discovery Engine API) là lớp điều phối trung tâm và giao diện đàm thoại cho người dùng cuối. Nền tảng này quản lý các phiên trò chuyện của người dùng, dựa trên các mô hình tạo sinh về dữ liệu doanh nghiệp và điều phối việc thực thi công cụ linh động.
Các ứng dụng Gemini Enterprise tương tác với dữ liệu và hệ thống thông qua kho dữ liệu:
- Kho dữ liệu kiến thức: Nhập và lập chỉ mục nội dung tĩnh (ví dụ: Cloud Storage, Google Drive, BigQuery) để tạo thông tin dựa trên truy xuất (RAG).
- Trình kết nối dữ liệu (nhà cung cấp hành động): Kết nối với API tuỳ chỉnh hoặc API linh động của bên thứ ba. Kho dữ liệu máy chủ MCP tuỳ chỉnh cung cấp các công cụ do Giao thức ngữ cảnh mô hình (MCP) xác định, cho phép mô hình gọi các hàm bên ngoài một cách linh hoạt trong cuộc trò chuyện.
Dữ liệu đầu ra của Gemini Enterprise
Gemini Enterprise định tuyến các yêu cầu tuỳ chỉnh về công cụ máy chủ MCP đến Agent Gateway khi cả agentGatewaySetting trên Engine và use_agent_gateway_egress: true trên DataConnector đều được định cấu hình.
Hình 2. Cấu trúc truyền dữ liệu ra bên ngoài của Gemini Enterprise
Ứng dụng Gemini Enterprise sắp xếp việc định tuyến công cụ theo 4 khía cạnh chính:
- Tiện ích (
default_search_widget_config):- Phục vụ giao diện ứng dụng web. Tiện ích này nhận lời nhắc từ người dùng, kích hoạt lệnh chuyển hướng lấy sự đồng ý của người dùng một lần theo giao thức OAuth 2.0 khi một công cụ yêu cầu uỷ quyền và bắt đầu các phiên trò chuyện với công cụ cơ bản.
- Trợ lý cốt lõi (
assistants/default_assistant/agents/default/core_assistant):- Tác nhân suy luận đàm thoại gốc trong công cụ. Khi đánh giá một câu hỏi của người dùng, Trợ lý cốt lõi sẽ kiểm tra các công cụ hiện có và uỷ quyền thực thi cho tác nhân phụ Cổng tác nhân được tổng hợp.
- Kho dữ liệu và Trình kết nối dữ liệu:
DataStore: Được cung cấp trong mộtCollectionchuyên dụng khi:setUpDataConnectorchạy, nó liên kết (dataStoreIds) các giản đồ công cụ Agent Registry (get_sprockets,get_sprocket_by_id), các loại đối số và hướng dẫn về tác nhân đã nhập vớiEnginecủa Gemini Enterprise.DataConnector: Quản lý kết nối hành độngREGISTRY_MCP(createBapConnection: true) với máy chủ MCP từ xa (instance_uri), phân giải tài nguyên máy chủ MCP của Sổ đăng ký tác nhân (registry_mcp_server_name), đính kèm mã thông báo Bearer OAuth 2.0 được lưu trữ của người dùng (Authorization: Bearer [access_token]) và bật lưu lượng truy cập đi của Cổng tác nhân (use_agent_gateway_egress: true).
- Danh tính tác nhân, Sổ đăng ký tác nhân và Cổng tác nhân:
- Khi Data Connector gửi lệnh gọi công cụ đi, lệnh gọi này sẽ định tuyến lưu lượng truy cập đến cổng được chỉ định trong
agentGatewaySetting. Trợ lý cốt lõi tạo mã thông báo danh tính SPIFFE để xác nhận danh tính tải của mã thông báo:principal://agents.global.org-.../agents/default/core_assistant. - Agent Gateway tích hợp với Agent Registry bằng cách sử dụng trường
registriesđể giải quyết linh động các điểm cuối đích và lược đồ công cụ đã đăng ký, đánh giá các chính sách uỷ quyền bằng IAP và chuyển tiếp các yêu cầu được phép (giữ lại tiêu đềAuthorization: Bearercủa người dùng) vào mạng VPC bằng cách sử dụngAgentConnectivityTemplate.
- Khi Data Connector gửi lệnh gọi công cụ đi, lệnh gọi này sẽ định tuyến lưu lượng truy cập đến cổng được chỉ định trong
Khả năng kết nối VPC của cổng và NAT IP tĩnh
Agent Gateway hỗ trợ khả năng kết nối mạng VPC bằng cách sử dụng tài nguyên AgentConnectivityTemplate mà agentConnectivityTemplate tham chiếu trên cổng. Mẫu egressNetworkConfig xác định cách lưu lượng truy cập đi vào VPC của bạn thông qua một tệp đính kèm mạng PSC:
PRIVATE_RANGES_ONLY(mặc định): Chỉ định tuyến các dải IP riêng tư RFC 1918, RFC 6598 và Lớp E thông qua tệp đính kèm mạng PSC. Lưu lượng truy cập liên kết với Internet sẽ bỏ qua VPC của bạn và thoát trực tiếp qua cổng thoát Internet mặc định của Google.ALL_TRAFFIC(được dùng trong Lớp học lập trình này): Định tuyến tất cả lưu lượng truy cập đi ra từ Agent Gateway (bao gồm cả Internet công cộng và các điểm cuối MCP của đối tác bên ngoài) vào mạng con VPC của bạn thông qua tệp đính kèm mạng PSC (10.10.10.2).
Khi hoạt động ở chế độ ALL_TRAFFIC, mạng con đính kèm PSC yêu cầu 2 cấu hình:
- Quyền truy cập riêng tư vào Google (
--enable-private-ip-google-access): Đảm bảo các lệnh gọi nội bộ đến API Google Cloud (*.googleapis.com) tiếp tục được định tuyến riêng tư trong mạng Google. - Cloud Router và Cloud NAT (
MANUAL_ONLY): Lưu lượng truy cập liên kết với Internet đi vào mạng con đính kèm PSC sẽ tuân theo tuyến đường mặc định (0.0.0.0/0) thông qua Cloud NAT. Cloud NAT sẽ thực hiện tính năng Dịch địa chỉ mạng nguồn (SNAT) cho địa chỉ IPv4 tĩnh bên ngoài được đặt trước (${NAT_EXT_IP}). Do đó, tường lửa bên ngoài có thể hạn chế nghiêm ngặt quyền truy cập đến${NAT_EXT_IP}/32.
Giới hạn và yêu cầu
- Chỉ StreamableHTTP: Phương thức truyền Sự kiện được gửi bởi máy chủ (SSE) cũ không được hỗ trợ. Máy chủ MCP phải sử dụng StreamableHTTP.
- Ghi đè chính sách của tổ chức: Bạn phải ghi đè chính sách của tổ chức một cách rõ ràng đối với các kho dữ liệu MCP tuỳ chỉnh trước khi đăng ký trình kết nối dữ liệu.
- Sự phù hợp theo khu vực: Gemini Enterprise thực thi sự phù hợp theo khu vực giữa vị trí của ứng dụng, Cổng tác nhân và Sổ đăng ký tác nhân:
Vị trí của ứng dụng Gemini Enterprise | Vị trí của Cổng tác nhân và NAT | Vị trí của Sổ đăng ký tác nhân |
|
|
|
|
|
|
|
|
|
Đến đây là kết thúc phần khái niệm... tiếp theo là phần Thiết lập.
3. Thiết lập
Các vai trò IAM bắt buộc
Bạn cần có các vai trò sau để hoàn tất Lớp học lập trình này:
Miền | Các vai trò IAM bắt buộc |
Dự án và IAM |
|
Mạng và Cổng |
|
Gemini Enterprise và Registry |
|
Tải |
|
Khả năng ghi nhận |
|
Hoặc sử dụng một vai trò cơ bản rộng như roles/owner kết hợp với roles/orgpolicy.policyAdmin (vì chỉ có roles/owner không thể sửa đổi chính sách của tổ chức).
Truy cập vào dự án của bạn
Lớp học lập trình này sử dụng một dự án trên đám mây duy nhất trên Google Cloud. Các bước định cấu hình sử dụng CLI gcloud và các lệnh shell Linux.
Bắt đầu bằng cách truy cập vào dòng lệnh của dự án trên Google Cloud:
- Cloud Shell tại
shell.cloud.google.comhoặc - Một thiết bị đầu cuối cục bộ đã cài đặt CLI
gcloud
Đặt mã dự án
# set target project id
gcloud config set project SET_YOUR_PROJECT_ID_HERE
Xác thực phiên
# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login
Đặt các biến môi trường của trình bao
# set custom var for slug (eg, "foo") and region preference
export SLUG="foo"
export REGION="us-central1"
export ZONE="us-central1-a"
echo ${SLUG}
echo ${REGION}
echo ${ZONE}
# create project vars (automatic)
export PROJ_ID=$(gcloud config list --format="value(core.project)")
export PROJ_NO=$(gcloud projects describe ${PROJ_ID} --format="value(projectNumber)")
export ORG_ID=$(gcloud projects get-ancestors ${PROJ_ID} --format="value(id)" | tail -n 1)
export USER_IDENTITY=$(gcloud config get-value account)
echo ${PROJ_ID}
echo ${PROJ_NO}
echo ${ORG_ID}
echo ${USER_IDENTITY}
# create resource vars for agent platform (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-ata"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export MCP_NAME="mcp-sprockets"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${MCP_NAME}
# create resource vars for gemini enterprise (automatic)
export GE_LOCATION="global"
export GE_APP_ORG_NAME="${SLUG}, Inc."
export GE_APP_DISPLAY_NAME="${SLUG} ${GE_LOCATION} app"
export GE_APP_NAME="app-${SLUG}-${GE_LOCATION}"
export GE_APP_INIT="${GE_APP_NAME}_$(date +%s)"
echo ${GE_LOCATION}
echo ${GE_APP_ORG_NAME}
echo ${GE_APP_DISPLAY_NAME}
echo ${GE_APP_NAME}
echo ${GE_APP_INIT}
Thiết lập các miền tin cậy danh tính của tác nhân
Câu lệnh if-then-else kiểm tra xem dự án có thuộc về một tổ chức hay không để đặt miền tin cậy chính xác cho danh tính của tác nhân chính.
# set var for trust domain
if [[ -n "${ORG_ID}" ]]; then
export TRUST_DOMAIN="agents.global.org-${ORG_ID}.system.id.goog"
else
export TRUST_DOMAIN="agents.global.proj-${PROJ_NO}.system.id.goog"
fi
echo "trust domain: ${TRUST_DOMAIN}"
Đặt dự án thanh toán và hạn mức
# set cli quota project
gcloud config set billing/quota_project ${PROJ_ID}
# set api quota project
gcloud auth application-default set-quota-project ${PROJ_ID}
Tạo thư mục cục bộ cho các tệp cấu hình
# create config folder
mkdir -p cfg
Cập nhật gcloud cli (nên dùng)
Nếu bạn đang chạy bản cài đặt tự quản lý của Google Cloud SDK (tức là bên ngoài Cloud Shell), hãy cập nhật các thành phần lên phiên bản mới nhất.
# update gcloud cli
gcloud components update
Bật các dịch vụ API
# enable google cloud apis
gcloud services enable \
agentregistry.googleapis.com \
aiplatform.googleapis.com \
cloudapiregistry.googleapis.com \
cloudresourcemanager.googleapis.com \
compute.googleapis.com \
discoveryengine.googleapis.com \
dns.googleapis.com \
iam.googleapis.com \
iap.googleapis.com \
logging.googleapis.com \
monitoring.googleapis.com \
networkconnectivity.googleapis.com \
networksecurity.googleapis.com \
networkservices.googleapis.com \
orgpolicy.googleapis.com \
serviceextensions.googleapis.com \
serviceusage.googleapis.com
Chính sách tổ chức
Các chế độ hạn chế mặc định của chính sách tổ chức do Google Cloud quản lý và các chính sách hộp cát có thể hạn chế các tính năng được dùng trong Lớp học lập trình này:
compute.vmExternalIpAccess: Hạn chế địa chỉ IPv4 bên ngoài trên máy ảo Compute Engine trong các tổ chức hộp cát bị khoá.discoveryengine.managed.disableCustomMcpServerConnector: Hạn chế việc tạo trình kết nối dữ liệu sử dụng máy chủ MCP tuỳ chỉnh (custom_mcp) làm nguồn dữ liệu (được thực thi theo mặc định).discoveryengine.managed.allowedEgressFqdns: Hạn chế các miền truyền dữ liệu đi (instance_uriFQDN) cho các trình kết nối dữ liệu khi VPC Service Controls (VPC-SC) đang hoạt động hoặc dự án có trong danh sáchenforcedProjects.discoveryengine.managed.allowedDataSources: Hạn chế các loại trình kết nối dữ liệu được phép (dataSource) khi VPC-SC đang hoạt động hoặc dự án có trong danh sáchenforcedProjects.
Ghi đè mọi quy định hạn chế của chính sách tổ chức được kế thừa ở cấp dự án.
Tắt chế độ ràng buộc MCP tuỳ chỉnh
# disable data connector constraint (allow custom mcp servers)
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/discoveryengine.managed.disableCustomMcpServerConnector
spec:
rules:
- enforce: false
EOF
Tắt các điều kiện ràng buộc của trình kết nối dữ liệu
# disable egress fqdn constraint on project
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/discoveryengine.managed.allowedEgressFqdns
spec:
rules:
- enforce: false
EOF
# disable allowed data sources constraint on project
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/discoveryengine.managed.allowedDataSources
spec:
rules:
- enforce: false
EOF
Tắt chế độ hạn chế chính sách truy cập
# disable iam v3 constraint (allow v3 access policies)
gcloud org-policies set-policy /dev/stdin << EOF
name: projects/${PROJ_NO}/policies/iam.managed.disableAccessPolicyBinding
spec:
rules:
- enforce: false
EOF
Cho phép IP ngoài
# allow external ip address for vms on project
gcloud org-policies set-policy "/dev/stdin" <<EOF
name: projects/${PROJ_ID}/policies/compute.vmExternalIpAccess
spec:
rules:
- allowAll: true
EOF
Xác minh chính sách tổ chức
Kiểm tra để đảm bảo rằng compute.vmExternalIpAccess được đặt thành allowAll: True và các chính sách khác là enforce: False:
# verify effective org policy constraints on project
for policy in \
discoveryengine.managed.disableCustomMcpServerConnector \
discoveryengine.managed.allowedEgressFqdns \
discoveryengine.managed.allowedDataSources \
iam.managed.disableAccessPolicyBinding \
compute.vmExternalIpAccess; do
gcloud org-policies describe ${policy} \
--project=${PROJ_ID} \
--effective \
--format="flattened[no-pad](name.basename(),spec.rules[0])"
done
Xác minh các liên kết của tác nhân dịch vụ (thận trọng)
Trong một dự án mới, Google Cloud sẽ tự động cung cấp tác nhân dịch vụ Cổng tác nhân và cấp cho tác nhân này roles/agentgateway.serviceAgent khi networkservices.googleapis.com được bật lần đầu tiên. Nếu bạn đang sử dụng lại một dự án hiện có mà quá trình dọn dẹp trước đó có thể đã xoá các liên kết tác nhân dịch vụ mặc định, hãy chạy các lệnh sau để đảm bảo rằng danh tính và liên kết vai trò vẫn còn nguyên vẹn:
# ensure network services service account has been created
gcloud beta services identity create \
--service=networkservices.googleapis.com \
--project="${PROJ_ID}"
# ensure network services service account has service agent roles applied
gcloud projects add-iam-policy-binding "${PROJ_ID}" \
--member="serviceAccount:service-${PROJ_NO}@gcp-sa-agentgateway.iam.gserviceaccount.com" \
--role="roles/agentgateway.serviceAgent"
Đến đây là kết thúc phần thiết lập... tiếp theo là phần Mạng.
4. Mạng
Trong phần này, bạn sẽ đặt trước các địa chỉ IPv4 bên ngoài tĩnh, tạo mạng VPC truyền dữ liệu ra bên ngoài và mạng VPC bên ngoài biệt lập, cung cấp điểm đính kèm mạng PSC, định cấu hình Cloud NAT và tạo các quy tắc tường lửa.
Đặt trước địa chỉ IP ngoài tĩnh
Dành riêng 2 địa chỉ IPv4 bên ngoài tĩnh theo khu vực cho Cloud NAT và máy ảo máy chủ MCP bên ngoài:
# reserve static external ipv4 address for cloud nat
gcloud compute addresses create ip-${SLUG}-nat \
--region=${REGION}
# reserve static external ipv4 address for the mcp server
gcloud compute addresses create ip-${SLUG}-mcp \
--region=${REGION}
Xác minh địa chỉ IP ngoài tĩnh
Gemini Enterprise yêu cầu các điểm cuối MCP từ xa sử dụng HTTPS có chứng chỉ TLS được tin cậy công khai. Thay vì đăng ký một miền tuỳ chỉnh cho phòng thí nghiệm này, bạn sẽ sử dụng sslip.io, một dịch vụ DNS dùng ký tự đại diện miễn phí. Dịch vụ này phân giải mọi tên máy chủ có chứa địa chỉ IP (chẳng hạn như mcp.[IP].sslip.io) trực tiếp trở lại địa chỉ IP đó. Vì các Tổ chức phát hành chứng chỉ như Let's Encrypt không phát hành chứng chỉ cho các địa chỉ IP trần, nên tên máy chủ sslip.io này cung cấp cho Caddy một tên miền hợp lệ để tự động cung cấp một chứng chỉ TLS đáng tin cậy cho máy chủ MCP.
Xuất cả địa chỉ IPv4 và tạo tên miền sslip.io cũng như URL cho máy chủ MCP bên ngoài:
# export static ip addresses and set vars for domain
export NAT_EXT_IP=$(gcloud compute addresses describe ip-${SLUG}-nat \
--region=${REGION} \
--format="value(address)")
export MCP_EXT_IP=$(gcloud compute addresses describe ip-${SLUG}-mcp \
--region=${REGION} \
--format="value(address)")
export MCP_DOMAIN="mcp.${MCP_EXT_IP}.sslip.io"
export MCP_URL="https://${MCP_DOMAIN}/mcp"
echo "cloud nat external ip : ${NAT_EXT_IP}"
echo "mcp server external ip : ${MCP_EXT_IP}"
echo "mcp url : ${MCP_URL}"
Ví dụ về đầu ra:
cloud nat external ip : 203.0.113.10
mcp server external ip : 203.0.113.20
mcp url : https://mcp.203.0.113.20.sslip.io/mcp
Tạo mạng nội bộ
Khi mẫu kết nối Agent Gateway được định cấu hình để sử dụng egressNetworkConfig có networkAttachment, mạng con lưu trữ tệp đính kèm mạng PSC phải có ít nhất một khối CIDR /28 và phải bật Quyền truy cập riêng tư vào Google (--enable-private-ip-google-access).
Tạo một mạng VPC toàn cầu cho lưu lượng truy cập ra bên ngoài của Agent Gateway nội bộ:
# create vpc network
gcloud compute networks create vnet-${SLUG}-internal --subnet-mode=custom
# create subnet for agent gateway psc na
gcloud compute networks subnets create subnet-${REGION}-agw \
--network=vnet-${SLUG}-internal \
--range=10.10.10.0/28 \
--region=${REGION} \
--enable-private-ip-google-access
Tạo quy tắc tường lửa nội bộ
Tạo một chính sách tường lửa để cho phép tất cả lưu lượng truy cập đi ra có bật tính năng ghi nhật ký. Điều này sẽ được dùng để giám sát lưu lượng truy cập đi ra từ Agent Gateway đến mạng VPC nội bộ. Cloud NGFW hỗ trợ cả các cấp Essentials và Standard để bảo mật mạng và giám sát lưu lượng truy cập.
# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG}-internal --global
# create fw policy rule
gcloud compute network-firewall-policies rules create 1001 \
--description="allow all out and log" \
--firewall-policy=fw-policy-${SLUG}-internal \
--global-firewall-policy \
--action=allow \
--direction=EGRESS \
--layer4-configs=all \
--dest-ip-ranges=0.0.0.0/0 \
--enable-logging
# bind fw policy to network
gcloud compute network-firewall-policies associations create \
--name=fw-policy-bind-${SLUG}-internal \
--firewall-policy=fw-policy-${SLUG}-internal \
--network=vnet-${SLUG}-internal \
--global-firewall-policy
Tạo tệp đính kèm mạng PSC
Tạo một tệp đính kèm mạng Private Service Connect (PSC) được định cấu hình để tự động chấp nhận các kết nối từ Agent Gateway. Điểm đính kèm mạng thiết lập phía mạng VPC của bên sử dụng của kết nối để liên kết an toàn với phía bên cung cấp của Cổng tác nhân cho lưu lượng truy cập đi ra. Để biết thêm thông tin về các yêu cầu đối với mạng con và quy cách về dải IP, hãy xem bài viết Định cấu hình khả năng kết nối VPC.
# create psc network attachment
gcloud compute network-attachments create psc-na-${REGION}-agw \
--region=${REGION} \
--subnets=subnet-${REGION}-agw \
--connection-preference=ACCEPT_AUTOMATIC
Xác minh việc đính kèm mạng PSC
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw --region=${REGION}
Truy xuất URI tài nguyên của tệp đính kèm mạng PSC và lưu trữ URI đó trong biến môi trường PSC_NA_URI. URI này sẽ được tham chiếu trong cấu hình Agent Gateway (networkConfig.egress.networkAttachment) để cung cấp Giao diện PSC cho lưu lượng truy cập mạng đi ra vào mạng VPC:
# fetch psc network attachment uri
export PSC_NA_URI=$(gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="value(selfLink.scope(v1))")
echo ${PSC_NA_URI}
Tạo Cloud NAT
Cloud NAT được dùng để dịch địa chỉ IP nguồn của lưu lượng truy cập xuất của Agent Gateway sang địa chỉ IP công khai được đặt trước để định tuyến qua Internet công cộng.
Chỉ những nguồn từ mạng con đính kèm mạng xuất của Cổng đại lý mới được xác định là đủ điều kiện sử dụng Cloud NAT.
# create router for nat
gcloud compute routers create cr-nat-${SLUG}-${REGION} \
--network=vnet-${SLUG}-internal \
--asn=16550 \
--region=${REGION}
# create nat
gcloud compute routers nats create nat-${SLUG}-${REGION} \
--router=cr-nat-${SLUG}-${REGION} \
--region=${REGION} \
--nat-custom-subnet-ip-ranges="subnet-${REGION}-agw" \
--nat-external-ip-pool="ip-${SLUG}-nat" \
--enable-logging \
--log-filter=ALL
Xác minh Cloud NAT
Kiểm tra trạng thái Cloud NAT và xác nhận rằng nguồn natIP dự kiến đã được định cấu hình:
# verify cloud nat configuration
gcloud compute routers nats describe nat-${SLUG}-${REGION} \
--router=cr-nat-${SLUG}-${REGION} \
--region=${REGION} \
--format="yaml(name,natIps,subnetworks.name)"
Ví dụ về đầu ra:
name: nat-foo-us-central1
natIps:
- https://www.googleapis.com/compute/v1/projects/[PROJ_ID]/regions/us-central1/addresses/ip-foo-nat
Tạo mạng bên ngoài
Tạo một mạng VPC riêng biệt, biệt lập để lưu trữ VM máy chủ MCP bên ngoài.
# create vpc network
gcloud compute networks create vnet-${SLUG}-external --subnet-mode=custom
# create subnet for mcp server
gcloud compute networks subnets create subnet-${REGION}-mcp \
--network=vnet-${SLUG}-external \
--range=240.240.240.0/24 \
--region=${REGION} \
--enable-private-ip-google-access
Tạo quy tắc tường lửa bên ngoài
Tạo 2 quy tắc tường lửa đầu vào trên mạng VPC bên ngoài:
2001: Cho phép cổng TCP gửi đến80để Let's Encrypt có thể hoàn tất thử thách xác thực miền ACME HTTP-01 cho${MCP_DOMAIN}.2002: Ban đầu cho phép cổng TCP443đến từ0.0.0.0/0để xác minh trạng thái sẵn sàng của TLS và việc thực thi OAuth 2.0tokeninfotừ shell cục bộ trước khi khoá chặt cổng này thành${NAT_EXT_IP}/32.
# create fw policy
gcloud compute network-firewall-policies create fw-policy-${SLUG}-external --global
# create fw policy rules
gcloud compute network-firewall-policies rules create 2001 \
--description="allow in any http" \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy \
--action=allow \
--direction=INGRESS \
--layer4-configs=tcp:80 \
--src-ip-ranges=0.0.0.0/0 \
--dest-ip-ranges=240.240.240.0/24 \
--enable-logging
gcloud compute network-firewall-policies rules create 2002 \
--description="allow in any https" \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy \
--action=allow \
--direction=INGRESS \
--layer4-configs=tcp:443 \
--src-ip-ranges=0.0.0.0/0 \
--dest-ip-ranges=240.240.240.0/24 \
--enable-logging
# bind fw policy to network
gcloud compute network-firewall-policies associations create \
--name=fw-policy-bind-${SLUG}-external \
--firewall-policy=fw-policy-${SLUG}-external \
--network=vnet-${SLUG}-external \
--global-firewall-policy
Đến đây là kết thúc phần mạng... tiếp theo là phần Cổng đại lý.
5. Agent Gateway
Trong phần này, bạn sẽ triển khai Mẫu kết nối tác nhân bằng vpcEgress: ALL_TRAFFIC, triển khai Cổng tác nhân theo khu vực, uỷ quyền cho Identity-Aware Proxy (IAP) và xác định các quy tắc Chính sách truy cập hợp nhất IAM để điều chỉnh các yêu cầu mạng đi.
Tạo mẫu kết nối
Quy cách mẫu kết nối xác định:
egressNetworkConfig.networkAttachment: Trỏ đến tệp đính kèm mạng PSC, kết nối Agent Gateway vào mạng VPC của bạn.egressNetworkConfig.vpcEgress: Đặt thànhALL_TRAFFICđể tất cả các kết nối đi ra của tác nhân (bao gồm cả các điểm cuối MCP trên Internet công cộng) sẽ định tuyến vào mạng VPC và thoát bằng cách sử dụng tính năng dịch địa chỉ IP nguồn Cloud NAT.
Tạo và nhập tệp cấu hình mẫu kết nối:
# create connectivity template config file (vpcEgress: ALL_TRAFFIC)
cat > cfg/act-${AGW_NAME}.yaml << EOF
accessPath: AGENT_TO_ANYWHERE
name: projects/${PROJ_NO}/locations/${REGION}/agentConnectivityTemplates/act-${AGW_NAME}
deploymentModel: CENTRALIZED
egressNetworkConfig:
networkAttachment: ${PSC_NA_URI}
vpcEgress: ALL_TRAFFIC
EOF
# import connectivity template file (create template)
gcloud network-services agent-connectivity-templates import act-${AGW_NAME} \
--source="cfg/act-${AGW_NAME}.yaml" \
--location=${REGION}
Tạo Agent Gateway
Quy cách Agent Gateway xác định:
agentConnectivityTemplate: Chỉ đến mẫu kết nối, nhờ đó, cổng có thể sử dụng tệp đính kèm mạng PSC để kết nối VPC.registries: Liên kết cổng với Agent Registry theo khu vực để phân giải các điểm cuối MCP và lược đồ công cụ được lập danh mục.
Tạo và nhập tệp cấu hình Agent Gateway:
# create agent gateway config file
cat > cfg/${AGW_NAME}.yaml << EOF
name: ${AGW_NAME}
protocols:
- MCP
googleManaged:
governedAccessPath: AGENT_TO_ANYWHERE
agentConnectivityTemplate: projects/${PROJ_NO}/locations/${REGION}/agentConnectivityTemplates/act-${AGW_NAME}
registries:
- "//agentregistry.googleapis.com/projects/${PROJ_ID}/locations/${REGION}"
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
--source="cfg/${AGW_NAME}.yaml" \
--location=${REGION}
Xác minh việc triển khai Cổng nhân viên hỗ trợ
Xác nhận cấu hình Mẫu kết nối và Sổ đăng ký tác nhân:
# verify agent gateway deployment details
gcloud network-services agent-gateways describe ${AGW_NAME} \
--location=${REGION} \
--format="yaml(name,agentConnectivityTemplate,registries)"
Ví dụ về đầu ra:
agentConnectivityTemplate: projects/[PROJ_NO]/locations/us-central1/agentConnectivityTemplates/act-foo-us-central1
name: projects/[PROJ_ID]/locations/us-central1/agentGateways/agw-foo-us-central1-ata
registries:
- //agentregistry.googleapis.com/projects/[PROJ_ID]/locations/us-central1
Kiểm tra tệp đính kèm mạng PSC để xác nhận kết nối cổng:
# show psc network attachment details
gcloud compute network-attachments describe psc-na-${REGION}-agw \
--region=${REGION} \
--format="yaml(connectionEndpoints)"
Ví dụ về đầu ra:
connectionEndpoints:
- ipAddress: 10.10.10.2
projectIdOrNum: '[TENANT_PROJ_NO]'
status: ACCEPTED
subnetwork: https://www.googleapis.com/compute/v1/projects/[PROJ_ID]/regions/us-central1/subnetworks/subnet-us-central1-agw
Uỷ quyền
Agent Gateway bảo mật và quản lý lưu lượng truy cập công cụ gửi đi bằng Chính sách uỷ quyền (networksecurity.authzPolicies) được tích hợp với Chính sách truy cập hợp nhất (UAP) của Identity-Aware Proxy (IAP).
Mặc dù Agent Gateway hỗ trợ các quy tắc cơ bản ALLOW và DENY nội tuyến, nhưng môi trường doanh nghiệp yêu cầu quản trị tập trung, lấy danh tính làm trung tâm. Với Chính sách truy cập thống nhất của IAM (hoặc Chính sách truy cập), bạn quản lý các quy tắc truy cập xuất bằng cách sử dụng các chính sách truy cập IAM phiên bản 3 tiêu chuẩn.
Hình 3. Cấu trúc uỷ quyền
Quy trình uỷ quyền kết nối 3 thành phần:
- Chính sách uỷ quyền cổng (
authzPolicy):- Một tài nguyên theo khu vực nhắm đến Agent Gateway.
- Được định cấu hình bằng
policyProfile: REQUEST_AUTHZvàaction: CUSTOMđể định tuyến tất cả các hoạt động kiểm tra uỷ quyền đi ra đến tiện ích uỷ quyền IAP.
- Tiện ích dịch vụ IAP (
authzExtension):- Một tài nguyên theo khu vực uỷ quyền yêu cầu cho Identity-Aware Proxy (
iap.googleapis.com). - Đánh giá các chính sách ở chế độ
ENFORCEbằng cách sử dụng phiên bản chính sáchV2.
- Một tài nguyên theo khu vực uỷ quyền yêu cầu cho Identity-Aware Proxy (
- Chính sách và mối liên kết về quyền truy cập hợp nhất của IAM (
accessPolicy&policyBinding):- Các tài nguyên IAM phiên bản 3 trên toàn cầu có chứa các quy tắc truy cập chi tiết.
- Xác thực danh tính chính SPIFFE của tác nhân gọi, xác minh quyền
iap.googleapis.com/resources.egressViaIAPchung và đánh giá các điều kiện Ngôn ngữ biểu thức chung (CEL) dựa trên các thuộc tính đích.
Triển khai tiện ích uỷ quyền
# create authz extension config file
cat > "cfg/${AGW_NAME}-svc-ext-authz-iap.yaml" << EOF
name: ${AGW_NAME}-svc-ext-authz-iap
service: iap.googleapis.com
failOpen: false
timeout: 1s
metadata:
iapPolicyVersion: "V2"
EOF
# import authz extension config file (create authz extension)
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-iap \
--source="cfg/${AGW_NAME}-svc-ext-authz-iap.yaml" \
--location=${REGION}
Xác minh tiện ích uỷ quyền
Kiểm tra xem tiện ích uỷ quyền có đang hoạt động hay không:
# list authz extensions
gcloud service-extensions authz-extensions list \
--location=${REGION} \
--format="table(
name.basename():label=NAME,
createTime.date(tz=LOCAL):label=CREATED,
service:label=SERVICE,
metadata:label=METADATA,
timeout:label=TIMEOUT
)"
Triển khai chính sách uỷ quyền
Tạo cấu hình chính sách uỷ quyền network-security nhắm đến Agent Gateway và uỷ quyền xác minh yêu cầu cho tiện ích uỷ quyền cho IAP:
# create authz policy config file
cat > cfg/${AGW_NAME}-authz-policy-iap.yaml << EOF
name: ${AGW_NAME}-authz-policy-iap
target:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: REQUEST_AUTHZ
action: CUSTOM
customProvider:
authzExtension:
resources:
- "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-iap"
EOF
# import authz policy config file (create authz policy)
gcloud network-security authz-policies import ${AGW_NAME}-authz-policy-iap \
--source=cfg/${AGW_NAME}-authz-policy-iap.yaml \
--location=${REGION}
Xác minh chính sách uỷ quyền
Kiểm tra xem chính sách uỷ quyền có đang hoạt động hay không:
# list authz policies
gcloud network-security authz-policies list \
--location=${REGION} \
--format="table(
name.basename():label=NAME,
action:label=ACTION,
policyProfile:label=POLICY_PROFILE,
customProvider.authzExtension.resources[0].basename():label=CUSTOM_PROVIDER_RESOURCE
)"
Tạo chính sách truy cập IAM
Giờ đây, Agent Gateway uỷ quyền kiểm tra cho IAP và phân giải siêu dữ liệu đích đến từ Agent Registry. Tiếp theo, hãy xác định một quy tắc Chính sách truy cập hợp nhất IAM để điều chỉnh việc thực thi công cụ gửi đi.
IAP đánh giá biểu thức thuộc tính CEL dựa trên các thuộc tính đích đến sau đây của Sổ đăng ký tác nhân:
- Trạng thái đã đăng ký (
destination.is_registered):- Boolean (
true/false) cho biết liệu đích đến có được lập danh mục trong Sổ đăng ký tác nhân hay không.
- Boolean (
- Tên máy chủ MCP (
destination.agent_registry.mcp_server.name):- Tên tài nguyên máy chủ MCP chuẩn được đăng ký trong Agent Registry.
- Phương thức MCP (
destination.agent_registry.mcp_server.method):- Phương thức MCP đang được gọi (ví dụ:
tools/call,tools/list,initialize).
- Phương thức MCP đang được gọi (ví dụ:
- Tên công cụ (
destination.agent_registry.mcp_server.tool.name):- Tên công cụ cụ thể được gọi (ví dụ:
get_sprocket_by_idhoặcget_sprockets), cho phép uỷ quyền ở cấp công cụ, chi tiết trên các máy chủ MCP đã đăng ký.
- Tên công cụ cụ thể được gọi (ví dụ:
Xác định quy tắc chính sách truy cập IAM
Tệp kê khai quy tắc chính sách IAM chỉ định:
- Chủ thể: Danh tính chủ thể SPIFFE đại diện cho tác nhân trợ lý cốt lõi của Gemini Enterprise.
- Quyền: Quyền
iap.googleapis.com/resources.egressViaIAPchung bắt buộc đối với tất cả lưu lượng truy cập xuất cảnh do IAP chi phối. - Điều kiện: Một biểu thức CEL (
destination.is_registered == true) đảm bảo rằng chỉ có thể gọi các điểm cuối được lập danh mục trong Agent Registry.
Tạo tệp kê khai quy tắc chính sách:
# create access policy rule file
cat > cfg/uap-policy-${SLUG}-rules.json << EOF
[
{
"description": "allow ge assistant to any registered service",
"effect": "ALLOW",
"principals": [
"principal://${TRUST_DOMAIN}/resources/discoveryengine/projects/${PROJ_NO}/locations/global/engines/${GE_APP_INIT}/assistants/default_assistant/agents/default/core_assistant"
],
"operation": {
"permissions": [
"iap.googleapis.com/resources.egressViaIAP"
]
},
"conditions": {
"iap.googleapis.com": {
"expression": \
"destination.is_registered == true"
}
}
}
]
EOF
Triển khai chính sách truy cập IAM
Tạo chính sách truy cập IAM chung bằng các quy tắc được xác định trong tệp kê khai:
# create iam access policy
gcloud iam access-policies create uap-policy-${SLUG} \
--details-rules=cfg/uap-policy-${SLUG}-rules.json \
--project=${PROJ_ID} \
--location=global
Xác minh chính sách truy cập IAM
Kiểm tra xem chính sách truy cập IAM đã được tạo thành công hay chưa và kiểm tra thông tin chi tiết về quy tắc:
# show iam access policy details
gcloud iam access-policies describe uap-policy-${SLUG} \
--project=${PROJ_ID} \
--location=global
Ví dụ về đầu ra:
details:
rules:
- conditions:
iap.googleapis.com:
expression: destination.is_registered == true
description: allow ge assistant to any registered service
effect: ALLOW
operation:
permissions:
- iap.googleapis.com/resources.egressViaIAP
principals:
- principal://agents.global.org-[ORG_ID].system.id.goog/resources/discoveryengine/projects/[PROJ_NO]/locations/global/engines/app-foo-global_[EPOCH]/assistants/default_assistant/agents/default/core_assistant
name: projects/[PROJ_ID]/locations/global/accessPolicies/uap-policy-foo
Liên kết chính sách truy cập IAM với dự án
Để kích hoạt việc thực thi trên tất cả Cổng tác nhân trong dự án, hãy tạo một liên kết chính sách để đính kèm chính sách truy cập IAM vào tài nguyên dự án:
# bind iam access policy to project resource
gcloud iam policy-bindings create uap-bind-${SLUG} \
--policy="projects/${PROJ_ID}/locations/global/accessPolicies/uap-policy-${SLUG}" \
--target-resource="//cloudresourcemanager.googleapis.com/projects/${PROJ_ID}" \
--project=${PROJ_ID} \
--location=global
Xác minh việc liên kết chính sách truy cập IAM
Kiểm tra các điểm liên kết chính sách đang hoạt động với chính sách và mục tiêu phù hợp:
# show policy binding details
gcloud iam policy-bindings describe uap-bind-${SLUG} \
--project=${PROJ_ID} \
--location=global
Đến đây là kết thúc phần Agent Gateway... tiếp theo là phần máy chủ MCP.
6. Máy chủ MCP
Trong phần này, bạn sẽ triển khai một Máy chủ tài nguyên OAuth 2.0 FastMCP bên ngoài (mcp-sprockets) hiển thị các công cụ get_sprockets và get_sprocket_by_id, xác minh rằng máy chủ này xác thực mã thông báo Bearer OAuth 2.0 của Google một cách mật mã dựa trên https://oauth2.googleapis.com/tokeninfo. Tiếp theo, bạn sẽ khoá chặt quy tắc tường lửa bên ngoài đối với IP tĩnh của Cloud NAT.
Triển khai máy chủ MCP bên ngoài
Một tập lệnh khởi động sẽ cài đặt Caddy và FastMCP, khởi chạy máy chủ mcp-sprockets trên 127.0.0.1:8080 và định cấu hình Caddy để phân phát HTTPS trên ${MCP_DOMAIN}.
Mỗi khi Gemini Enterprise gọi một công cụ MCP (ví dụ: get_sprockets và get_sprocket_by_id), máy chủ sẽ:
- Đọc IP nguồn của người gọi từ tiêu đề
X-Forwarded-For(egress_source_ip). - Trích xuất tiêu đề
Authorization: Bearer [access_token]và xác minh mã thông báo dựa trên điểm cuối xác minh Google OAuth 2.0 (https://oauth2.googleapis.com/tokeninfo?access_token=[token]). - Trả về
"authenticated_user"([user_email]) cùng với"egress_source_ip", chứng minh rằng máy chủ MCP bên ngoài đã xác minh cả IP tĩnh Cloud NAT và danh tính Google OAuth 2.0 của người dùng cuối.
# create startup script for the sprockets mcp server vm
cat > cfg/server-startup.sh << 'EOF'
#!/bin/bash
set -euo pipefail
MCP_DOMAIN=$(curl -s -H "Metadata-Flavor: Google" \
http://metadata.google.internal/computeMetadata/v1/instance/attributes/mcp-domain)
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y caddy python3-venv curl
mkdir -p /opt/mcp-sprockets
python3 -m venv /opt/mcp-sprockets/venv
/opt/mcp-sprockets/venv/bin/pip install --upgrade pip
/opt/mcp-sprockets/venv/bin/pip install "fastmcp>=2.14.0" "uvicorn>=0.34.0"
cat <<'PYEOF' > /opt/mcp-sprockets/main.py
import json
import urllib.parse
import urllib.request
from typing import Any, Dict
from fastmcp import FastMCP
from fastmcp.server.dependencies import get_http_headers
from mcp.types import ToolAnnotations
mcp = FastMCP("mcp-sprockets")
SPROCKETS = {
"SPK-101": {"id": "SPK-101", "model": "ANSI-40-12T", "teeth": 12, "pitch_in": 0.5, "material": "1045 Carbon Steel", "stock": 140, "unit_price": 18.50},
"SPK-102": {"id": "SPK-102", "model": "ANSI-40-24T", "teeth": 24, "pitch_in": 0.5, "material": "1045 Carbon Steel", "stock": 85, "unit_price": 29.00},
"SPK-103": {"id": "SPK-103", "model": "ANSI-60-16T", "teeth": 16, "pitch_in": 0.75, "material": "304 Stainless Steel", "stock": 60, "unit_price": 42.00},
"SPK-104": {"id": "SPK-104", "model": "ANSI-60-32T", "teeth": 32, "pitch_in": 0.75, "material": "304 Stainless Steel", "stock": 35, "unit_price": 68.00},
"SPK-105": {"id": "SPK-105", "model": "ANSI-80-20T", "teeth": 20, "pitch_in": 1.0, "material": "4140 Alloy Steel", "stock": 50, "unit_price": 95.00}
}
def verify_google_oauth_token(headers: Dict[str, str]) -> str:
token = headers.get("authorization", "")[7:].strip() if headers.get("authorization", "").lower().startswith("bearer ") else ""
if not token:
return "unauthenticated (missing Bearer token)"
url = "https://oauth2.googleapis.com/tokeninfo?" + urllib.parse.urlencode({"access_token": token})
with urllib.request.urlopen(url, timeout=5) as resp:
info = json.loads(resp.read().decode("utf-8"))
return info.get("email", info.get("sub", "verified-oauth-user"))
@mcp.tool(
description="list all sprockets in the inventory catalog",
annotations=ToolAnnotations(
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=False
)
)
def get_sprockets() -> Dict[str, Any]:
headers = get_http_headers(include_all=True)
caller_ip = headers.get("x-forwarded-for", "unknown").split(",")[0].strip()
try:
user_email = verify_google_oauth_token(headers)
except Exception as exc:
return {"egress_source_ip": caller_ip, "authenticated_user": None, "error": f"OAuth token verification failed: {exc}"}
return {
"egress_source_ip": caller_ip,
"authenticated_user": user_email,
"sprockets": list(SPROCKETS.values())
}
@mcp.tool(
description="fetch details of a specific sprocket by its ID (eg, SPK-101)",
annotations=ToolAnnotations(
readOnlyHint=True,
destructiveHint=False,
idempotentHint=True,
openWorldHint=False
)
)
def get_sprocket_by_id(sprocket_id: str) -> Dict[str, Any]:
headers = get_http_headers(include_all=True)
caller_ip = headers.get("x-forwarded-for", "unknown").split(",")[0].strip()
try:
user_email = verify_google_oauth_token(headers)
except Exception as exc:
return {"egress_source_ip": caller_ip, "authenticated_user": None, "error": f"OAuth token verification failed: {exc}"}
sprocket = SPROCKETS.get(sprocket_id.upper())
if sprocket:
return {
"egress_source_ip": caller_ip,
"authenticated_user": user_email,
"sprocket": sprocket
}
return {
"egress_source_ip": caller_ip,
"authenticated_user": user_email,
"error": f"Sprocket '{sprocket_id}' not found."
}
app = mcp.http_app(stateless_http=True)
PYEOF
cat <<'SVCEOF' > /etc/systemd/system/mcp-sprockets.service
[Unit]
Description=Sprockets FastMCP Server
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/mcp-sprockets
ExecStart=/opt/mcp-sprockets/venv/bin/uvicorn main:app --host 127.0.0.1 --port 8080 --forwarded-allow-ips="*"
Restart=always
[Install]
WantedBy=multi-user.target
SVCEOF
systemctl daemon-reload
systemctl enable --now mcp-sprockets.service
systemctl restart mcp-sprockets.service
cat <<CADDYEOF > "/etc/caddy/Caddyfile"
${MCP_DOMAIN} {
reverse_proxy 127.0.0.1:8080
}
CADDYEOF
systemctl restart caddy
EOF
# create vm instance
gcloud compute instances create vm-${MCP_NAME} \
--zone=${ZONE} \
--machine-type=e2-micro \
--image-family=debian-12 \
--image-project=debian-cloud \
--shielded-secure-boot \
--network-interface="subnet=subnet-${REGION}-mcp,address=${MCP_EXT_IP}" \
--metadata="mcp-domain=${MCP_DOMAIN}" \
--metadata-from-file="startup-script=cfg/server-startup.sh"
Xác minh trạng thái sẵn sàng của máy chủ MCP và xác thực OAuth 2.0 tokeninfo
Chờ vài phút để tập lệnh khởi động cài đặt FastMCP và Caddy, đồng thời cung cấp chứng chỉ TLS Let's Encrypt.
# poll until caddy serves valid tls and fastmcp responds to tools/list
for i in $(seq 1 30); do
RESP=$(curl -s -X POST "${MCP_URL}" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' || true)
if echo "${RESP}" | grep -q "get_sprockets"; then
echo "mcp server and let's encrypt tls ready"
break
fi
echo "...waiting for mcp server and let's encrypt tls (attempt ${i}/30)..."
sleep 5
done
Xác thực quá trình phân giải DNS sslip.io, chứng chỉ TLS Let's Encrypt do Caddy cung cấp và phản hồi FastMCPtools/list:
# query mcp server for tools list
curl -v -X POST "${MCP_URL}" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}' \
2>&1 | grep -E "Connected to|subject:|issuer:|SSL certificate|HTTP/|event:|data:"
Ví dụ về đầu ra:
* Connected to mcp.203.0.113.20.sslip.io (203.0.113.20) port 443
* subject: CN=mcp.203.0.113.20.sslip.io
* issuer: C=US; O=Let's Encrypt; CN=E5
* SSL certificate verify ok.
> POST /mcp HTTP/2
< HTTP/2 200
event: message
data: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"get_sprockets","description":"list all sprockets in the inventory catalog","inputSchema":{"properties":{},"type":"object"},"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}},{"name":"get_sprocket_by_id","description":"fetch details of a specific sprocket by its ID (eg, SPK-101)","inputSchema":{"properties":{"sprocket_id":{"type":"string"}},"required":["sprocket_id"],"type":"object"},"annotations":{"destructiveHint":false,"idempotentHint":true,"openWorldHint":false,"readOnlyHint":true}}]}}
Trước khi khoá tường lửa bên ngoài, hãy chạy một thử nghiệm tools/call truyền mã thông báo Bearer Google OAuth 2.0 (gcloud auth print-access-token) để xác minh rằng mcp-sprockets xác thực mã thông báo dựa trên https://oauth2.googleapis.com/tokeninfo và trả về email "authenticated_user" của bạn cùng với địa chỉ IP nguồn của người gọi:
# query mcp server (test tools/call with google oauth 2.0 bearer token)
curl -s -X POST "${MCP_URL}" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_sprocket_by_id",
"arguments": {"sprocket_id": "SPK-105"}
}
}' | sed -n 's/^data: //p' | jq '.result.structuredContent'
Ví dụ về đầu ra (cho biết IP Cloud Shell trực tiếp của bạn trước khi tường lửa bị khoá và email Google OAuth đã xác minh của bạn):
{
"egress_source_ip": "198.51.100.154",
"authenticated_user": "user@example.com",
"sprocket": {
"id": "SPK-105",
"model": "ANSI-80-20T",
"teeth": 20,
"pitch_in": 1.0,
"material": "4140 Alloy Steel",
"stock": 50,
"unit_price": 95.0
}
}
Khoá tường lửa đối với IP tĩnh Cloud NAT
Cập nhật chính sách tường lửa mạng VPC bên ngoài để cổng TCP 443 chỉ chấp nhận lưu lượng truy cập từ IP bên ngoài tĩnh của Cloud NAT (${NAT_EXT_IP}/32):
# create fw policy rule allowing https only from cloud nat static ip
gcloud compute network-firewall-policies rules create 2003 \
--description="allow in any https from nat ip" \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy \
--action=allow \
--direction=INGRESS \
--layer4-configs=tcp:443 \
--src-ip-ranges="${NAT_EXT_IP}/32" \
--dest-ip-ranges=240.240.240.0/24 \
--enable-logging
# delete temporary open fw policy rules
gcloud compute network-firewall-policies rules delete 2001 \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy
gcloud compute network-firewall-policies rules delete 2002 \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy
Kiểm tra xem các quy tắc chính sách tường lửa bên ngoài đã được áp dụng hay chưa:
# list all rules in the global network firewall policy
gcloud compute network-firewall-policies describe fw-policy-${SLUG}-external \
--global \
--flatten="rules[]" \
--format="table(
rules.priority:label=RULE,
rules.action:label=ACTION,
rules.direction:label=DIRECTION,
firstof(
rules.match.srcIpRanges,
rules.match.srcAddressGroups,
rules.match.srcSecureTags.name
).map().sub('projects/[^/]+/(locations/global/|global/)', '').list():label=SRC,
firstof(
rules.targetForwardingRules,
rules.match.destIpRanges,
rules.targetType
).map().sub('projects/[^/]+/(locations/global/|global/)', '').list():label=DST
)"
Kiểm tra để đảm bảo rằng các kết nối trực tiếp bên ngoài IP tĩnh Cloud NAT hiện đã bị chặn:
# query mcp server
curl -i --connect-timeout 5 "${MCP_URL}" \
|| echo "Expected: Direct access blocked (not originating from ${NAT_EXT_IP})"
Ví dụ về đầu ra:
curl: (28) Connection timed out after 5001 milliseconds
Expected: Direct access blocked (not originating from 203.0.113.10)
Đến đây là kết thúc phần máy chủ MCP... tiếp theo là phần Sổ đăng ký tác nhân.
7. Sổ đăng ký tác nhân
Agent Registry là một kho lưu trữ tập trung của tất cả các tác nhân, máy chủ MCP và điểm cuối (API) trong hệ sinh thái AI. Đây cũng là một danh mục mà các ứng dụng AI có thể dùng để liệt kê, tìm kiếm và khám phá các công cụ và dịch vụ đã đăng ký khác. Agent Gateway sử dụng mô hình dữ liệu của sổ đăng ký làm khung quản trị để thực thi quyền kiểm soát truy cập đầu ra. Các quyền truy cập vai trò IAM cho các tác nhân gọi đối tượng chính được kiểm tra dựa trên chính sách liên kết với tài nguyên sổ đăng ký.
Trong phần này, bạn sẽ đăng ký máy chủ MCP và giản đồ công cụ (toolspec.json) của máy chủ đó trong Agent Registry. Để hỗ trợ Gemini Enterprise tương tác với Các API và dịch vụ của Google thông qua Agent Gateway, bạn cũng sẽ tạo một dịch vụ điểm cuối đăng ký duy nhất (oauth2-googleapis) chỉ định các giao diện API của Google mà Gemini Enterprise sử dụng để trao đổi mã uỷ quyền cho mã thông báo.
Đăng ký máy chủ MCP
Để cho phép Gemini Enterprise khám phá các công cụ có trên máy chủ MCP, hãy cung cấp một tệp thông số kỹ thuật công cụ (cfg/toolspec.json) khi đăng ký dịch vụ trong Sổ đăng ký tác nhân.
Tạo quy cách công cụ MCP
# create tool spec file for the sprockets mcp server
cat <<'EOF' > cfg/toolspec.json
{
"tools": [
{
"name": "get_sprockets",
"description": "List all sprockets in the inventory catalog.",
"inputSchema": {
"type": "object",
"properties": {}
},
"isReadOnly": true,
"isDestructive": false,
"isIdempotent": true,
"isOpenWorld": false
},
{
"name": "get_sprocket_by_id",
"description": "Fetch details of a specific sprocket by its ID (e.g., SPK-101).",
"inputSchema": {
"type": "object",
"properties": {
"sprocket_id": {
"type": "string",
"description": "The sprocket identifier (e.g., SPK-101, SPK-105)."
}
},
"required": [
"sprocket_id"
]
},
"isReadOnly": true,
"isDestructive": false,
"isIdempotent": true,
"isOpenWorld": false
}
]
}
EOF
Tạo dịch vụ máy chủ MCP
# create registry service (mcp server)
gcloud agent-registry services create ${MCP_NAME} \
--project=${PROJ_ID} \
--location=${REGION} \
--display-name="${MCP_DOMAIN}" \
--description="MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: You MUST \
ALWAYS invoke this tool (get_sprockets or get_sprocket_by_id) for ANY question \
about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through \
SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, \
material, stock levels, unit prices, authenticated_user, or egress_source_ip \
verification. NEVER guess or fabricate inventory data yourself and NEVER \
transfer sprocket queries to file_and_coding_agent or web search. Always \
delegate every sprocket or inventory lookup to this tool." \
--mcp-server-spec-type=tool-spec \
--mcp-server-spec-content=cfg/toolspec.json \
--interfaces=protocolBinding=JSONRPC,url="${MCP_URL}"
Xác minh máy chủ MCP trong Sổ đăng ký tác nhân
Xác minh rằng dịch vụ này được liệt kê là một máy chủ MCP đã đăng ký trong khu vực cùng với URL điểm cuối và các công cụ có sẵn:
# list registry regional mcp servers
gcloud agent-registry mcp-servers list \
--location=${REGION} \
--project=${PROJ_ID} \
--format="table(
name.basename():label=REGISTRY_ID,
displayName:label=DISPLAY_NAME,
interfaces[0].url:label=ENDPOINT_URL,
tools[].name.list():label=TOOLS
)"
Ví dụ về đầu ra:
REGISTRY_ID DISPLAY_NAME ENDPOINT_URL TOOLS
agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8 mcp.203.0.113.20.sslip.io https://mcp.203.0.113.20.sslip.io/mcp get_sprockets,get_sprocket_by_id
Xem quy cách cấu hình dịch vụ để biết rằng dịch vụ này đăng ký chính xác các định nghĩa công cụ, giản đồ đầu vào và chú thích hành vi cho từng công cụ:
# describe mcp server tool specs
gcloud agent-registry services describe ${MCP_NAME} \
--location=${REGION} \
--project=${PROJ_ID} \
--format="yaml(mcpServerSpec.content.tools)"
Đăng ký điểm cuối OAuth
Để cho phép phần phụ trợ Gemini Enterprise DataConnector (đóng vai trò là ứng dụng OAuth trong quy trình uỷ quyền) gửi các yêu cầu POST đến máy chủ uỷ quyền Google OAuth 2.0 (https://oauth2.googleapis.com/token) thông qua Agent Gateway, bạn phải đăng ký điểm cuối mã thông báo trong Agent Registry để IAP đánh giá destination.is_registered == true.
Tạo dịch vụ điểm cuối
# create registry service (endpoint)
gcloud agent-registry services create oauth2-googleapis \
--project=${PROJ_ID} \
--location=${REGION} \
--display-name="oauth2.googleapis.com" \
--description="google oauth2 endpoint" \
--endpoint-spec-type=no-spec \
--interfaces=protocolBinding=JSONRPC,url=https://oauth2.googleapis.com
Xác minh việc đăng ký điểm cuối
# list registry regional endpoints
gcloud agent-registry endpoints list \
--project=${PROJ_ID} \
--location=${REGION} \
--flatten="interfaces[]" \
--format="table(
displayName,
name.basename():label=ENDPOINT_ID,
interfaces.url:label=URL
)"
Kết quả đầu ra dự kiến:
DISPLAY_NAME ENDPOINT_ID URL
oauth2.googleapis.com agentregistry-00000000-0000-0000-0012-3456789abcde https://oauth2.googleapis.com
Chính sách truy cập IAM
Vì chính sách truy cập IAM xác định một chính sách cho phép đối với mọi dịch vụ đã đăng ký do danh tính tác nhân core_assistant của ứng dụng Gemini Enterprise yêu cầu, nên không cần thêm các liên kết chính sách IAM để trao đổi mã thông báo OAuth.
- conditions:
iap.googleapis.com:
expression: destination.is_registered == true
description: allow ge assistant to any registered service
effect: ALLOW
Đến đây là kết thúc phần Đăng ký tác nhân... tiếp theo là phần Gemini Enterprise.
8. Gemini Enterprise
Trong phần này, bạn sẽ định cấu hình nhà cung cấp danh tính, giấy phép dùng thử và thông tin đăng nhập của ứng dụng khách OAuth 2.0 của Google Identity, tạo một ứng dụng Gemini Enterprise (${GE_APP_ID}), liên kết lưu lượng truy cập đi ra với Cổng đại lý (${AGW_URI}) và kết nối máy chủ MCP sprockets đã đăng ký làm kho lưu trữ dữ liệu MCP tuỳ chỉnh OAuth 2.0.
Tạo ứng dụng Gemini Enterprise
Phương thức sau đây sử dụng API discoveryengine.googleapis.com để tạo tài nguyên và cấu hình ứng dụng Gemini Enterprise. Để định cấu hình bằng giao diện người dùng Google Cloud Console, hãy xem phần Tạo ứng dụng để biết hướng dẫn.
# create engine (ge app)
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines?engineId=${GE_APP_INIT}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"displayName": "${GE_APP_DISPLAY_NAME}",
"dataStoreIds": [],
"solutionType": "SOLUTION_TYPE_SEARCH",
"industryVertical": "GENERIC",
"appType": "APP_TYPE_INTRANET",
"searchEngineConfig": {
"searchTier": "SEARCH_TIER_ENTERPRISE",
"searchAddOns": [
"SEARCH_ADD_ON_LLM"
]
},
"commonConfig": {
"companyName": "${GE_APP_ORG_NAME}"
},
"observabilityConfig": {
"observabilityEnabled": true,
"sensitiveLoggingEnabled": true
}
}
EOF
Xác minh việc tạo ứng dụng
# fetch engine (ge app) id
export GE_APP_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" -H "X-Goog-User-Project: ${PROJ_ID}" \
| jq -r --arg name "${GE_APP_DISPLAY_NAME}" '.engines[] | select(.displayName==$name) | .name | split("/") | last')
echo "engine (ge app) id: ${GE_APP_ID}"
Xem thông tin chi tiết về công cụ để xem cấu hình đã tạo:
# get engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Bật nhà cung cấp danh tính
Bật Google Identity làm nhà cung cấp dịch vụ danh tính để xác thực người dùng cuối trên ứng dụng Gemini Enterprise.
Phương thức sau đây sử dụng API discoveryengine.googleapis.com để định cấu hình trình cung cấp danh tính ứng dụng Gemini Enterprise. Để định cấu hình bằng giao diện người dùng Google Cloud Console, hãy xem phần Định cấu hình nhà cung cấp danh tính để biết hướng dẫn.
# set identity provider
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"idpConfig": {
"idpType": "GSUITE"
}
}
EOF
Xác minh nhà cung cấp danh tính
# show identity provider
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Đầu ra "idpType": "GSUITE" tương ứng với Google Identity.
(Không bắt buộc) Bật giấy phép dùng thử Gemini Enterprise
Nếu đang sử dụng một dự án đã được cấp giấy phép Gemini Enterprise, bạn có thể bỏ qua bước này. Nếu bạn đang sử dụng một dự án mới mà không có giấy phép, hãy tiếp tục và làm theo các bước sau.
Tạo một tài nguyên cấu hình giấy phép để cấp quyền sử dụng Gemini Enterprise cho người dùng trong 30 ngày. Thao tác này sẽ đặt giấy phép mặc định cho bản dùng thử mới, vì vậy, mọi người dùng đăng nhập đều được tự động cấp một chỗ:
# configure free trial subscription
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs?licenseConfigId=free_trial_gemini" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"subscriptionTier": "SUBSCRIPTION_TIER_SEARCH_AND_ASSISTANT",
"freeTrial": true
}
EOF
Xác minh rằng giấy phép đã được áp dụng
# show license config
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/licenseConfigs/free_trial_gemini" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Kiểm tra "subscriptionTerm": "SUBSCRIPTION_TERM_ONE_MONTH" và "freeTrial": true.
# verify auto-registration enabled on default user store
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/userStores/default_user_store" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
Kiểm tra ../free_trial_gemini" và "enableLicenseAutoRegister": true.
Định cấu hình thông tin xác thực và sự đồng ý theo OAuth 2.0
Để cho phép Gemini Enterprise (Ứng dụng OAuth 2.0) lấy Mã thông báo Bearer OAuth 2.0 do Google uỷ quyền cho người dùng và thay mặt bạn trình bày mã thông báo đó cho mcp-sprocketsMáy chủ tài nguyên, hãy định cấu hình màn hình xin phép OAuth của Nền tảng xác thực của Google và tạo một mã ứng dụng OAuth 2.0 cho ứng dụng web trong dự án của bạn.
1. Định cấu hình màn hình xin phép bằng OAuth
In URL trực tiếp của Google Cloud Console cho Google Auth Platform Overview (Tổng quan về Nền tảng xác thực của Google) trong dự án của bạn:
# print google auth platform consent screen url
echo "https://console.cloud.google.com/auth/overview?project=${PROJ_ID}"
- Mở URL trong trình duyệt rồi nhấp vào Bắt đầu (nếu bạn chưa định cấu hình cho dự án của mình).
- Trong phần Thông tin về ứng dụng, hãy đặt Tên ứng dụng thành
mcp-sprockets-oauthrồi chọn địa chỉ email của bạn (${USER_IDENTITY}) làm Email hỗ trợ người dùng, sau đó nhấp vào Tiếp theo. - Trong phần Đối tượng, hãy chọn Nội bộ (nên chọn nếu tài khoản của bạn thuộc một tổ chức Google Workspace) hoặc Bên ngoài (nếu bạn dùng tài khoản cá nhân; nếu bạn chọn Bên ngoài, hãy thêm
${USER_IDENTITY}trong phần **Người dùng kiểm thử đối tượng**), sau đó nhấp vào Tiếp theo. - Nhập địa chỉ email của bạn trong phần Thông tin liên hệ, chấp nhận thoả thuận về chính sách rồi nhấp vào Tạo.
2. Tạo mã ứng dụng khách OAuth 2.0 cho ứng dụng Web
In URL trực tiếp của Google Cloud Console cho trang Clients (Ứng dụng khách):
# print google auth platform clients url
echo "https://console.cloud.google.com/auth/clients?project=${PROJ_ID}"
- Mở URL rồi nhấp vào + Tạo ứng dụng khách.
- Chọn Ứng dụng web làm Loại ứng dụng và đặt Tên thành
ge-mcp-sprockets-client. - Đánh dấu vào hộp Ứng dụng này sẽ được dùng bởi một tác nhân dựa trên AI để chỉ định ứng dụng OAuth cho quy trình công việc của tác nhân AI thay mặt cho người dùng.
- Trong phần URI chuyển hướng được uỷ quyền, hãy nhấp vào + Thêm URI rồi thêm URI gọi lại OAuth của Gemini Enterprise:
https://vertexaisearch.cloud.google.com/oauth-redirect
- Nhấp vào Tạo, sao chép Mã ứng dụng và Khoá bí mật của ứng dụng đã tạo, rồi xuất các khoá này trong phiên shell:
Đặt mã ứng dụng khách OAuth 2.0 và khoá bí mật của ứng dụng khách được tạo ở bước trước:
# set oauth 2.0 client id (paste in id)
export OAUTH_CLIENT_ID="SET_YOUR_OAUTH_CLIENT_ID_HERE"
# set oauth 2.0 client secret (paste in secret)
export OAUTH_CLIENT_SECRET="SET_YOUR_OAUTH_CLIENT_SECRET_HERE"
Kiểm tra xem mã ứng dụng khách đã được đặt hay chưa:
# print oauth 2.0 client id
echo "oauth client id: ${OAUTH_CLIENT_ID}"
Liên kết với Agent Gateway
Việc định tuyến lưu lượng truy cập đi từ Gemini Enterprise thông qua Agent Gateway sẽ thiết lập một ranh giới định tuyến IP tĩnh và thực thi tập trung cho tất cả các lệnh gọi công cụ tác nhân AI:
- Thực thi chính sách tập trung: Agent Gateway hoạt động như một proxy nội tuyến, đánh giá các yêu cầu về công cụ gửi đi dựa trên các chính sách uỷ quyền trước khi lưu lượng truy cập rời khỏi môi trường của tác nhân.
- Đường truyền ra khỏi VPC và Cloud NAT tất định: Việc liên kết Gemini Enterprise với một Cổng tác nhân được định cấu hình bằng
vpcEgress: ALL_TRAFFICđảm bảo các lệnh gọi công cụ được định tuyến thông qua điểm đính kèm mạng PSC và thoát bằng IP tĩnh Cloud NAT đã đặt trước. - Khả năng kiểm tra hợp nhất: Cung cấp nhật ký yêu cầu tập trung và nhật ký kiểm tra trên tất cả các máy chủ MCP được kết nối.
Hãy vá công cụ agentGatewaySetting để bật:
# bind engine (ge app) to agent gateway
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}?updateMask=agentGatewaySetting.defaultEgressAgentGateway.name" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" -H "Content-Type: application/json" \
-d @- <<EOF
{
"agentGatewaySetting": {
"defaultEgressAgentGateway": {
"name": "${AGW_URI}"
}
}
}
EOF
Xác minh mối liên kết Agent Gateway
Truy xuất cấu hình ứng dụng để xác nhận liên kết agentGatewaySetting:
# verify engine (ge app) agent gateway configuration
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name: .name, displayName: .displayName, agentGatewaySetting: .agentGatewaySetting}'
Ví dụ về đầu ra:
{
"name": "projects/[PROJ_NO]/locations/global/collections/default_collection/engines/app-foo-global_[EPOCH]",
"displayName": "foo global app",
"agentGatewaySetting": {
"defaultEgressAgentGateway": {
"name": "projects/[PROJ_ID]/locations/us-central1/agentGateways/agw-foo-us-central1-ata"
}
}
}
Tạo kho lưu trữ dữ liệu máy chủ MCP tuỳ chỉnh
Trong phần này, bạn sẽ kết nối máy chủ mcp-sprockets với Gemini Enterprise bằng cách tạo một kho dữ liệu MCP tuỳ chỉnh OAuth 2.0 được định cấu hình bằng Google Identity (https://accounts.google.com/o/oauth2/v2/auth và https://oauth2.googleapis.com/token).
Khi sử dụng Discovery Engine API, đây là quy trình gồm 2 bước:
- Tạo (
:setUpDataConnector): Tạo tài nguyênCollectionchuyên dụng (${MCP_NAME}-collection-%timestamp), đính kèmDataConnector(custom_mcp) bằngauth_type: "OAUTH"và cung cấpDataStorehỗ trợ (..._mcp_data). - Kích hoạt (
PATCH .../dataConnector?updateMask=actionConfig): Kích hoạt thời gian chạy của thao tác trình kết nối (actionState: "ACTIVE") bằng cách sử dụng thông số kỹ thuật của công cụ Đăng ký tác nhân, các tham số OAuth 2.0 của Google Identity và liên kếtDataStore(dataStoreIds) với Gemini EnterpriseEngine.
# fetch mcp server agent registry resource name
export MCP_REGISTRY_URI=$(gcloud agent-registry mcp-servers list \
--location=${REGION} \
--project=${PROJ_ID} \
--filter="displayName:${MCP_DOMAIN}" \
--format="value(name)")
echo "mcp registry name: ${MCP_REGISTRY_URI}"
echo "mcp url: ${MCP_URL}"
Tạo trình kết nối dữ liệu
# create custom mcp data connector with google identity oauth 2.0 and link to engine
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}:setUpDataConnector" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"collectionId": "${MCP_NAME}-collection-$(date +%s)",
"collectionDisplayName": "${MCP_NAME}-collection",
"dataConnector": {
"dataSource": "custom_mcp",
"dataSourceVersion": 1,
"params": {
"oauth_access_token": "unused"
},
"refreshInterval": "86400s",
"entities": [
{
"entityName": "mcp_data"
}
],
"connectorModes": [
"FEDERATED"
],
"actionConfig": {
"isActionConfigured": true,
"createBapConnection": true,
"actionParams": {
"auth_type": "OAUTH",
"instance_uri": "${MCP_URL}",
"auth_uri": "https://accounts.google.com/o/oauth2/v2/auth",
"auth_uri_params": "&access_type=offline&prompt=consent",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "${OAUTH_CLIENT_ID}",
"client_secret": "${OAUTH_CLIENT_SECRET}",
"scopes": "openid email profile",
"client_secret_basic_override": true,
"mcp_server_source": "REGISTRY_MCP",
"registry_mcp_server_name": "${MCP_REGISTRY_URI}",
"mcp_agent_instructions": "MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: Always invoke get_sprockets or get_sprocket_by_id for any question about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, material, stock levels, unit prices, authenticated_user, or egress_source_ip verification.",
"use_agent_gateway_egress": true,
"agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
}
}
}
}
EOF
Xác minh việc tạo trình kết nối dữ liệu
# fetch collection id
export GE_COLLECTION_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq -r --arg dname "${MCP_NAME}-collection" '.collections[] | select(.displayName == $dname) | .name | split("/") | last' | head -n 1)
echo "ge collection id: ${GE_COLLECTION_ID}"
Kiểm tra xem trường "registry_mcp_server_name" có được điền sẵn bằng UUID của Sổ đăng ký tác nhân cho máy chủ MCP hay không và "auth_type" là OAUTH:
# show data connector details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/dataConnector" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name, state, actionState, connectorModes, bapConfig, auth_type: .actionConfig.actionParams.auth_type, registry_mcp_server_name: .actionConfig.actionParams.registry_mcp_server_name}'
Xem mục đăng ký máy chủ MCP trong giao diện người dùng Google Cloud Console:
echo "mcp server registry page url: https://console.cloud.google.com/agent-platform/agent-registry/mcp-servers/${REGION}/${MCP_REGISTRY_URI##*/}/overview?project=${PROJ_ID}"
Kích hoạt trình kết nối dữ liệu
# activate and bind data connector with google identity oauth 2.0
curl -s -X PATCH "https://discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector?updateMask=actionConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"name": "projects/${PROJ_ID}/locations/global/collections/${GE_COLLECTION_ID}/dataConnector",
"actionConfig": {
"isActionConfigured": true,
"createBapConnection": true,
"actionParams": {
"auth_type": "OAUTH",
"instance_uri": "${MCP_URL}",
"auth_uri": "https://accounts.google.com/o/oauth2/v2/auth",
"auth_uri_params": "&access_type=offline&prompt=consent",
"token_uri": "https://oauth2.googleapis.com/token",
"client_id": "${OAUTH_CLIENT_ID}",
"client_secret": "${OAUTH_CLIENT_SECRET}",
"scopes": "openid email profile",
"client_secret_basic_override": true,
"mcp_server_source": "REGISTRY_MCP",
"registry_mcp_server_name": "${MCP_REGISTRY_URI}",
"mcp_agent_instructions": "MANDATORY SPROCKETS INVENTORY & CATALOG AGENT: Always invoke get_sprockets or get_sprocket_by_id for any question about sprockets, inventory catalog listings, sprocket IDs (SPK-101 through SPK-105), ANSI models (ANSI-40, ANSI-60, ANSI-80), tooth counts, pitch, material, stock levels, unit prices, authenticated_user, or egress_source_ip verification.",
"use_agent_gateway_egress": true,
"agent_gateway_engine": "projects/${PROJ_ID}/locations/global/collections/default_collection/engines/${GE_APP_ID}"
}
}
}
EOF
Xác minh các mối liên kết máy chủ MCP tuỳ chỉnh
# show engine (ge app) details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq '{name: .name, dataStoreIds: .dataStoreIds, agentGatewaySetting: .agentGatewaySetting}'
Kiểm tra kho dữ liệu được liên kết "dataStoreIds": ["mcp-sprockets-collection-[EPOCH]_mcp_data"].
# show collection details
curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
| jq --arg app "${GE_APP_ID}" '.collections[] | select(.dataConnector.actionConfig.actionParams.agent_gateway_engine // "" | endswith($app)) | .dataConnector | {name: .name, state: .state, actionState: .actionState, connectorModes: .connectorModes, auth_type: .actionConfig.actionParams.auth_type}'
Kiểm tra "state": "ACTIVE" và "auth_type": "OAUTH".
Thao tác đối với công cụ
Khi kiểm tra kho dữ liệu mcp-sprockets-collection trong trang tổng quan Gemini Enterprise, bạn sẽ nhận thấy rằng thẻ Actions (Hành động) không được dùng và nút ↻ Reload custom actions (Tải lại hành động tuỳ chỉnh) bị vô hiệu hoá. Đây là hành vi dự kiến.
Xem trang thông tin chi tiết về kho dữ liệu trong giao diện người dùng Google Cloud Console:
echo "data store details page url: https://console.cloud.google.com/gemini-enterprise/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}/connector/details?project=${PROJ_ID}"
Tuỳ thuộc vào cách bạn kết nối máy chủ MCP tuỳ chỉnh với Gemini Enterprise, quá trình khám phá và quản trị công cụ sẽ được xử lý theo một trong hai cách sau:
- MCP tuỳ chỉnh trực tiếp (
BYO_MCPquy trình): Khi bạn định cấu hình một máy chủ MCP tuỳ chỉnh ngay trong Gemini Enterprise mà không cần Agent Registry, kho dữ liệu sẽ tự quản lý danh mục công cụ (connectorModes: ["FEDERATED", "ACTIONS"]). Bạn phải mở thẻ Hành động, nhấp vào ↻ Tải lại các hành động tuỳ chỉnh để tìm nạp giản đồtools/listvà bật hoặc tắt từng công cụ (addvàsubtract) theo cách thủ công trong giao diện người dùng. - Nhập Sổ đăng ký tác nhân (
REGISTRY_MCPquy trình được dùng trong lớp học lập trình này): Khi bạn nhập một máy chủ MCP từ Sổ đăng ký tác nhân, Sổ đăng ký tác nhân sẽ đóng vai trò là nguồn thông tin chính xác cho điểm cuối MCP, siêu dữ liệu giao diện và danh mục công cụ (connectorModes: ["FEDERATED"]). Gemini Enterprise tự động bật các công cụ MCP đã đăng ký trong thời gian chạy thông qua chế độ cài đặt Cổng tác nhân của công cụ mà không yêu cầu bạn tải lại hoặc bật/tắt các thao tác theo cách thủ công trong giao diện người dùng kho dữ liệu.
Đến đây là kết thúc phần Gemini Enterprise... tiếp theo là phần Xác thực.
9. Xác thực
Trong phần này, bạn sẽ hoàn tất quy trình đồng ý một lần của người dùng Google OAuth 2.0, gọi các công cụ MCP trên máy chủ mcp-sprockets bên ngoài từ Gemini Enterprise và xác minh rằng máy chủ MCP bên ngoài đã xác thực cả IP tĩnh Cloud NAT được đặt trước (egress_source_ip) và danh tính Google OAuth 2.0 (authenticated_user).
Quyền truy cập của người dùng
Tạo URL cho ứng dụng web Gemini Enterprise:
# fetch app user url
export GE_WIDGET_ID=$(curl -s "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/widgetConfigs/default_search_widget_config" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
| jq -r '.configId')
export GE_APP_USER_URL="https://vertexaisearch.cloud.google.com/home/cid/${GE_WIDGET_ID}"
echo "app user url: ${GE_APP_USER_URL}"
Hoàn tất quy trình xin phép bằng OAuth
Trước khi truy vấn tác nhân, bạn phải hoàn tất quy trình đồng ý OAuth 2.0 một lần để cấp cho Gemini Enterprise quyền lấy mã truy cập cho danh tính Google của bạn (${USER_IDENTITY}). Điều này cho phép Gemini Enterprise xác thực các lệnh gọi công cụ đi ra thông qua Agent Gateway để máy chủ mcp-sprockets bên ngoài có thể xác minh danh tính của bạn trên mọi yêu cầu.
- Mở
${GE_APP_USER_URL}trong trình duyệt rồi nhấp vào Bắt đầu. - Trong hộp trò chuyện, hãy nhấp vào biểu tượng Trình kết nối (biểu tượng mảnh ghép) rồi nhấp vào Uỷ quyền bên cạnh
mcp-sprockets-collection. - Một cửa sổ mới sẽ xuất hiện, nhắc bạn Chọn một tài khoản để tiếp tục
mcp-sprockets-oauth(tên ứng dụng trên màn hình xin phép bằng OAuth mà bạn đã định cấu hình). Tại đó, hãy chọn tài khoản người dùng của bạn (${USER_IDENTITY}). - Trên màn hình xin phép bằng OAuth của Google, hãy xem xét các quyền được yêu cầu cho phép Google (Nhà cung cấp danh tính) chia sẻ danh tính người dùng của bạn (
openid,email,profile) vớimcp-sprockets-oauth, sau đó nhấp vào Tiếp tục. - Nhấp lại vào biểu tượng Trình kết nối và xác minh rằng nút bật/tắt cho
mcp-sprockets-collectionđã được bật, xác nhận rằng quá trình uỷ quyền đã thành công.
Kiểm thử các câu hỏi cho tác nhân
Kiểm thử giao diện người dùng của cuộc trò chuyện với Trợ lý
Gửi truy vấn kiểm thử sau trong cuộc trò chuyện:
look up sprocket SPK-105 and confirm the model, material, unit_price, authenticated_user, and egress_source_ip
Thử đặt một câu hỏi thứ hai trong cuộc trò chuyện:
list all sprockets in the inventory catalog and report the authenticated_user and egress_source_ip
Xác minh rằng trợ lý trả về câu trả lời chính xác và hiển thị một huy hiệu trích dẫn hành động có tính tương tác.
Ví dụ: "Sprocket Lookup SPK-105 (5s)Agent Gateway" bên dưới mỗi câu trả lời xác nhận rằng công cụ đã được thực thi.
Xem trợ lý trả về thông số kỹ thuật của bánh răng cùng với "authenticated_user" khớp ${USER_IDENTITY} và "egress_source_ip" khớp với ${NAT_EXT_IP} bạn đã đặt trước.
Các bài kiểm thử API streamAssist của Trợ lý
Sau khi tài khoản người dùng của bạn đã uỷ quyền cho trình kết nối OAuth 2.0, bạn cũng có thể gọi API default_assistant:streamAssist trực tiếp từ CLI và xác minh rằng máy chủ mcp-sprockets bên ngoài trả về cả địa chỉ IP tĩnh Cloud NAT (${NAT_EXT_IP}) và danh tính Google OAuth 2.0 đã xác minh (${USER_IDENTITY}):
Gửi truy vấn kiểm thử sau:
# query engine (ge app) streamAssist
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/assistants/default_assistant:streamAssist" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF | jq -r '.[].answer.replies[]?.groundedContent?.content?.text // empty'
{
"query": {
"text": "look up sprocket SPK-103 and confirm the model, material, unit_price, authenticated_user, and egress_source_ip"
},
"toolsSpec": {
"vertexAiSearchSpec": {
"dataStoreSpecs": [
{
"dataStore": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/dataStores/${GE_COLLECTION_ID}_mcp_data"
}
]
}
}
}
EOF
Ví dụ về đầu ra:
Here are the details for sprocket SPK-103 from the inventory catalog:
- Model: ANSI-60-16T
- Material: 304 Stainless Steel
- Unit Price: $42.00
- Authenticated User (Google OAuth 2.0): user@example.com
- Egress Source IP (Cloud NAT): 203.0.113.10
Hãy thử một cụm từ tìm kiếm khác:
# query engine (ge app) streamAssist
curl -s -X POST "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}/assistants/default_assistant:streamAssist" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d @- <<EOF | jq -r '.[].answer.replies[]?.groundedContent?.content?.text // empty'
{
"query": {
"text": "find a sprocket model i can get for under \$20 and report the details, authenticated_user, and egress_source_ip"
},
"toolsSpec": {
"vertexAiSearchSpec": {
"dataStoreSpecs": [
{
"dataStore": "projects/${PROJ_NO}/locations/${GE_LOCATION}/collections/default_collection/dataStores/${GE_COLLECTION_ID}_mcp_data"
}
]
}
}
}
EOF
Kiểm tra nhật ký trong Cloud Logging
Xác minh rằng Gemini Enterprise đã định tuyến các lệnh gọi công cụ thông qua Agent Gateway, tệp đính kèm mạng PSC và Cloud NAT bằng cách kiểm tra nhật ký trong Cloud Logging.
Xác minh nhật ký Cổng của tác nhân
Xác nhận rằng Agent Gateway đã chặn yêu cầu, phân giải mục tiêu trong Agent Registry, đánh giá chính sách uỷ quyền và chuyển tiếp lệnh gọi công cụ:
# show agent gateway logs
gcloud logging read \
"resource.type=networkservices.googleapis.com/Gateway
AND resource.labels.location=${REGION}" \
--project=${PROJ_ID} \
--limit=8 \
--format="table(
timestamp.date('', tz=LOCAL):label=TIMESTAMP,
httpRequest.status:label=STATUS,
httpRequest.serverIp:label=SERVER_IP,
jsonPayload.agentGatewayInfo.mcpInfo.method:label=MCP_METHOD,
jsonPayload.agentGatewayInfo.mcpInfo.parameter:label=TOOL,
jsonPayload.authzPolicyInfo.result:label=AUTHZ,
jsonPayload.agentGatewayInfo.agentRegistryResource.basename():label=REGISTRY_MCP
)"
Ví dụ về đầu ra:
TIMESTAMP STATUS SERVER_IP MCP_METHOD TOOL AUTHZ REGISTRY_MCP
YYYY-MM-DDTHH:MM:SS.ZZZ 200 203.0.113.20:443 tools/call get_sprocket_by_id ALLOWED agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ 200 203.0.113.20:443 tools/list ALLOWED agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ 202 203.0.113.20:443 notifications/initialized ALLOWED agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
YYYY-MM-DDTHH:MM:SS.ZZZ 200 203.0.113.20:443 initialize ALLOWED agentregistry-00000000-0000-0000-5c39-1f6e542bb2b8
Xác minh rằng đầu ra chứa:
STATUS:200(thực thi thành công) và202(bắt taynotifications/initialized).SERVER_IP: Cổng và địa chỉ IP của máy chủ MCP bên ngoài (${MCP_EXT_IP}:443).MCP_METHODvàTOOL: Trình tự giao thức MCP (initialize,notifications/initialized,tools/listvàtools/callvớiget_sprocket_by_id).AUTHZ:ALLOWED(Cho phép uỷ quyền IAP).REGISTRY_MCP: Mã nhận dạng tài nguyên đã phân giải của Sổ đăng ký tác nhân (agentregistry-...).
Xác minh nhật ký Cloud NAT
Xác nhận rằng Cloud NAT đã dịch kết nối đi từ IP đính kèm mạng PSC của Cổng đại lý (10.10.10.2) sang địa chỉ IPv4 tĩnh bên ngoài được đặt trước (${NAT_EXT_IP}) khi kết nối với ${MCP_EXT_IP}:443:
# show cloud nat logs
gcloud logging read \
"resource.type=nat_gateway
AND resource.labels.gateway_name=nat-${SLUG}-${REGION}
AND jsonPayload.connection.dest_ip=${MCP_EXT_IP}" \
--project=${PROJ_ID} \
--limit=8 \
--format="table(
timestamp.date('', tz=LOCAL):label=TIMESTAMP,
jsonPayload.allocation_status:label=ALLOCATION_STATUS,
jsonPayload.connection.src_ip:label=SRC_IP,
jsonPayload.connection.nat_ip:label=NAT_IP,
jsonPayload.connection.dest_ip:label=DEST_IP,
jsonPayload.connection.dest_port:label=PORT
)"
Ví dụ về đầu ra:
TIMESTAMP ALLOCATION_STATUS SRC_IP NAT_IP DEST_IP PORT
YYYY-MM-DDTHH:MM:SS.ZZZ OK 10.10.10.2 203.0.113.10 203.0.113.20 443
Xác minh nhật ký tường lửa
Xác nhận rằng chính sách tường lửa nội bộ (fw-policy-${SLUG}-internal) cho phép lưu lượng truy cập đầu ra từ Agent Gateway đến đích đến trên Internet:
# show firewall policy logs (internal)
gcloud logging read \
"logName:compute.googleapis.com%2Ffirewall
AND jsonPayload.rule_details.reference:fw-policy-${SLUG}-internal" \
--project=${PROJ_ID} \
--limit=8 \
--format="table(
timestamp.date('', tz=LOCAL):label=TIMESTAMP,
jsonPayload.connection.src_ip:label=SRC_IP,
jsonPayload.connection.dest_ip:label=DEST_IP,
jsonPayload.connection.dest_port:label=PORT,
jsonPayload.vpc.vpc_name:label=VPC_NETWORK,
jsonPayload.rule_details.reference.basename():label=POLICY,
jsonPayload.rule_details.priority:label=RULE,
jsonPayload.rule_details.direction:label=DIRECTION,
jsonPayload.disposition:label=DISPOSITION
)"
Xác nhận rằng chính sách tường lửa bên ngoài (fw-policy-${SLUG}-external) cho phép lưu lượng truy cập vào máy chủ MCP từ địa chỉ IP NAT công khai của mạng nội bộ:
# show firewall policy logs (external)
gcloud logging read \
"logName:compute.googleapis.com%2Ffirewall
AND jsonPayload.rule_details.reference:fw-policy-${SLUG}-external" \
--project=${PROJ_ID} \
--limit=8 \
--format="table(
timestamp.date('', tz=LOCAL):label=TIMESTAMP,
jsonPayload.connection.src_ip:label=SRC_IP,
jsonPayload.connection.dest_ip:label=DEST_IP,
jsonPayload.connection.dest_port:label=PORT,
jsonPayload.vpc.vpc_name:label=VPC_NETWORK,
jsonPayload.rule_details.reference.basename():label=POLICY,
jsonPayload.rule_details.priority:label=RULE,
jsonPayload.rule_details.direction:label=DIRECTION,
jsonPayload.disposition:label=DISPOSITION
)"
Đến đây là kết thúc phần xác thực... tiếp theo là phần Dọn dẹp.
10. Dọn dẹp
Làm theo các bước sau để xoá các tài nguyên và cấu hình đã tạo trong phòng thí nghiệm này.
Xoá các thành phần của Gemini Enterprise
# delete gemini enterprise engine (app)
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/default_collection/engines/${GE_APP_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
# delete custom mcp collection, data connector, and backing data store
curl -s -X DELETE "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1alpha/projects/${PROJ_ID}/locations/${GE_LOCATION}/collections/${GE_COLLECTION_ID}" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}"
# reset identity provider configuration
curl -s -X PATCH "https://${GE_LOCATION}-discoveryengine.googleapis.com/v1/projects/${PROJ_ID}/locations/${GE_LOCATION}/aclConfig" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
-H "X-Goog-User-Project: ${PROJ_ID}" \
-H "Content-Type: application/json" \
-d '{"idpConfig":{"idpType":"IDP_TYPE_UNSPECIFIED"}}'
Để xoá thông tin đăng nhập của ứng dụng OAuth 2.0 (ge-mcp-sprockets-client), hãy mở trang Ứng dụng Google Auth Platform rồi nhấp vào biểu tượng Xoá (thùng rác) bên cạnh ge-mcp-sprockets-client:
# print google auth platform clients url
echo "https://console.cloud.google.com/auth/clients?project=${PROJ_ID}"
Xoá máy chủ MCP và các thành phần của Sổ đăng ký tác nhân
# delete external mcp server vm
gcloud -q compute instances delete vm-${MCP_NAME} --zone=${ZONE}
# delete agent registry mcp service
gcloud -q agent-registry services delete ${MCP_NAME} --location=${REGION}
# delete agent registry oauth2 endpoint
gcloud -q agent-registry services delete oauth2-googleapis --location=${REGION}
Xoá các thành phần Cổng của tác nhân
# delete gateway authz policy and iap service extension
gcloud -q network-security authz-policies delete ${AGW_NAME}-authz-policy-iap \
--location=${REGION}
gcloud -q service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-iap \
--location=${REGION}
# delete agent gateway and connectivity template
gcloud -q network-services agent-gateways delete ${AGW_NAME} \
--location=${REGION}
gcloud -q network-services agent-connectivity-templates delete act-${AGW_NAME} \
--location=${REGION}
# delete iam unified access policy binding and access policy
gcloud -q iam policy-bindings delete uap-bind-${SLUG} \
--location=global \
--project=${PROJ_ID}
gcloud -q iam access-policies delete uap-policy-${SLUG} \
--location=global \
--project=${PROJ_ID}
Xoá các thành phần tường lửa
# delete network firewall policy associations
gcloud -q compute network-firewall-policies associations delete \
--name=fw-policy-bind-${SLUG}-internal \
--firewall-policy=fw-policy-${SLUG}-internal \
--global-firewall-policy
gcloud -q compute network-firewall-policies associations delete \
--name=fw-policy-bind-${SLUG}-external \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy
# delete custom firewall policy rules
gcloud -q compute network-firewall-policies rules delete 1001 \
--firewall-policy=fw-policy-${SLUG}-internal \
--global-firewall-policy
gcloud -q compute network-firewall-policies rules delete 2003 \
--firewall-policy=fw-policy-${SLUG}-external \
--global-firewall-policy
# delete network firewall policies
gcloud -q compute network-firewall-policies delete fw-policy-${SLUG}-internal \
--global
gcloud -q compute network-firewall-policies delete fw-policy-${SLUG}-external \
--global
Xoá các thành phần mạng
# delete cloud nat gateway and cloud router
gcloud -q compute routers nats delete nat-${SLUG}-${REGION} \
--router=cr-nat-${SLUG}-${REGION} \
--region=${REGION}
gcloud -q compute routers delete cr-nat-${SLUG}-${REGION} \
--region=${REGION}
# delete psc network attachment
gcloud -q compute network-attachments delete psc-na-${REGION}-agw \
--region=${REGION}
# delete subnets
gcloud -q compute networks subnets delete subnet-${REGION}-agw \
--region=${REGION}
gcloud -q compute networks subnets delete subnet-${REGION}-mcp \
--region=${REGION}
# delete reserved static external ip addresses
gcloud -q compute addresses delete ip-${SLUG}-nat ip-${SLUG}-mcp \
--region=${REGION}
# delete internal and external vpc networks
gcloud -q compute networks delete \
vnet-${SLUG}-internal \
vnet-${SLUG}-external
Xoá các chế độ ghi đè chính sách của tổ chức và tệp cục bộ
# delete project-level organization policy overrides
for policy in \
discoveryengine.managed.disableCustomMcpServerConnector \
discoveryengine.managed.allowedEgressFqdns \
discoveryengine.managed.allowedDataSources \
iam.managed.disableAccessPolicyBinding \
compute.vmExternalIpAccess; do
gcloud -q org-policies delete ${policy} --project=${PROJ_ID} 2>/dev/null || true
done
# remove local project files
rm -rf cfg
Đến đây là kết thúc công việc dọn dẹp... tiếp theo là phần Kết luận!
11. Kết luận
Xin chúc mừng! Bạn đã xây dựng một cấu trúc toàn diện cho phép ứng dụng Gemini Enterprise khám phá và gọi các công cụ một cách an toàn trên máy chủ MCP tuỳ chỉnh được bảo vệ bằng OAuth 2.0 và có IP bên ngoài trong danh sách cho phép:
- Lưu lượng truy cập đi ra từ VPC có IP tĩnh (
ALL_TRAFFICvà Cloud NAT): Định tuyến tất cả lưu lượng truy cập đi ra từ Agent Gateway thông qua một tệp đính kèm mạng PSC (10.10.10.2) và dịch các yêu cầu liên quan đến Internet sang một địa chỉ IPv4 bên ngoài tĩnh được đặt trước (${NAT_EXT_IP}) bằng Cloud NAT. - Máy chủ tài nguyên và sổ đăng ký tác nhân MCP OAuth 2.0: Triển khai một máy chủ FastMCP HTTP có thể truyền trực tuyến bên ngoài (
mcp-sprockets) được bảo vệ bằng danh sách cho phép tường lửa IP nguồn nghiêm ngặt (${NAT_EXT_IP}/32) và quy trình xác minh Google OAuth 2.0tokeninfo, đồng thời đăng ký giản đồ công cụ và điểm cuối của máy chủ (get_sprocketsvàget_sprocket_by_id) trong Sổ đăng ký tác nhân. - Tích hợp và quản trị OAuth 2.0 của Gemini Enterprise: Cung cấp một ứng dụng Gemini Enterprise, liên kết lưu lượng truy cập công cụ đi ra với Agent Gateway, đính kèm máy chủ MCP đã đăng ký làm trình kết nối dữ liệu OAuth 2.0
REGISTRY_MCPvà xác minh cảegress_source_ipvàauthenticated_usercùng với số liệu đo từ xa Cloud Logging.

Cosmopup cho rằng Codelabs là một công cụ tuyệt vời!
Tiếp theo là gì?
- Hãy xem tài liệu về Nền tảng Tác nhân Gemini Enterprise để biết các tính năng nâng cao và hướng dẫn.
- Định cấu hình các biện pháp bảo vệ Model Armor trên Agent Gateway để tăng cường độ an toàn và bảo mật cho AI.
- Khám phá Chính sách quản trị ngữ nghĩa để thực thi các quy tắc kinh doanh và việc tuân thủ đối với các câu hỏi bằng ngôn ngữ tự nhiên.
Bạn có thể thoải mái đưa ra ý kiến nhận xét, câu hỏi hoặc nội dung chỉnh sửa bằng cách sử dụng biểu mẫu phản hồi này.
Cảm ơn bạn!