תעבורת נתונים נכנסת מ-Agent Gateway אל Agent Runtime עם הגנה מוגברת על המודל

1. מבוא

ב-Codelab הזה נסביר על ניהול תעבורת הכניסה (ingress) של סוכני AI שמתארחים ב-Agent Runtime באמצעות Agent Gateway.

Agent Gateway שפועל במצב כניסה (client-to-agent) תומך בניהול תקשורת בין לקוחות – משתמשי קצה אנושיים, נציגים במחשב, סביבות פיתוח משולבות (IDE) לקידוד, נציגים עמיתים וכו' – לבין נציגים שמארחים Agent Runtime. השימוש במצב הזה נועד להגן על נציגים מפני מתקפות של החדרת הנחיות נכנסות או תוכן מזיק שנשלח על ידי לקוחות. כל התעבורה הנכנסת מעובדת באמצעות תוספי הרשאה ו-Model Armor כדי לאבטח את נקודת הכניסה לרשת לכל אינטראקציה עם סוכן.

מה תפַתחו

  • Agent Gateway במצב כניסה (client-to-agent)
  • תוסף הרשאות של הגנה מוגברת על המודל
  • סוכן Agent Runtime ADK עם זהות סוכן
  • נתוני קבצים ב-Cloud Storage שנשלחו לסוכן באמצעות MCP
  • תבניות של Model Armor לסינון הנחיות ותשובות של LLM
  • תבניות של Sensitive Data Protection לביטול הזיהוי של נתונים

figure1

איור 1. ארכיטקטורת Codelab

מה לומדים

  • איך פורסים את Agent Gateway כדי לסנן תעבורת נתונים נכנסת (ingress) לסוכן
  • איך מגדירים תוספים להרשאה והאצלת סמכויות של הגנה מוגברת על המודל
  • איך יוצרים ופורסים תבניות מותאמות אישית של הגנה מוגברת על המודל
  • איך יוצרים ופורסים תבניות מותאמות אישית של Sensitive Data Protection
  • איך בודקים ומאמתים מדיניות סינון של מודלים גדולים של שפה

מה צריך

  • פרויקט ב-Google Cloud שהחיוב בו מופעל
  • הרשאות IAM להקצאת שירותי רשת, מערכי נתונים של BigQuery ומשאבים של Agent Platform
  • מעטפת תואמת POSIX‏ (bash או zsh) עם Google Cloud CLI (רכיב gcloud) מותקן
  • כלי שורת פקודה: git,‏ curl,‏ jq (מעבד JSON),‏ Python 3 ו-uv (מנהל חבילות Python)

2. מושגים

כיוון התנועה ותפקידי השער

Agent Gateway פועל כ-proxy של רשת שמודע לסוכן, אבל התפקיד התפעולי שלו משתנה בהתאם לכיוון התנועה:

  • מצב Agent-to-anywhere (יציאה): פועל כפרוקסי ליציאה. כשסוכן קורא לכלים חיצוניים של מסדי נתונים, לשרתי MCP של צד שלישי או לממשקי API, שער היציאה מנהל את גילוי השירות, הניתוב, TLS הדדי (mTLS), הזרקה דינמית של פרטי כניסה של OAuth ובקרת גישה לנקודות קצה.
  • מצב 'לקוח לסוכן' (כניסה): פועל כשער אבטחה בחזית. המטרה העיקרית שלו היא להגן על הכניסה לזמן הריצה של ביצוע הסוכן על ידי יירוט של הנחיות בשפה טבעית שמגיעות וניקוי שלהן לפני שהן מגיעות לקוד של הסוכן או למודלים של AI.

נתיב הכניסה ל-Agent Runtime

בקשות של לקוחות שמיועדות לסוכן שמתארח ב-Agent Runtime מיועדות לנקודת הקצה של aiplatform.googleapis.com API.

POST https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:query

זרם התקשורת הנכנסת הזה לנקודת הקצה של ה-API מייצג את נתיב הכניסה של הלקוח לסוכן.

כדי לאבטח את נתיב הכניסה הזה שמנוהל על ידי Google, ‏ Agent Gateway משולב ישירות עם Google Front End ‏ (GFE) בשכבת התשתית של שרת ה-API. כשפורסים סוכן מנוהל ב-Agent Runtime, ‏ Google קושרת באופן מקורי את מדיניות ההרשאה של שער הכניסה לבקשות לקוח נכנסות בקצה הרשת.

figure2

איור 2. פיקוח על תעבורת נתונים נכנסת באמצעות Agent Gateway אל Agent Runtime

מכיוון שהבדיקה מתבצעת בשכבת החזיתית לפני שהבקשות נכנסות ל-Agent Runtime, הארכיטקטורה הזו לא מוסיפה תקורה של רשת או השהיה פנימית. התשתית של חזית האתר מטפלת בהתאמת קנה המידה באופן אוטומטי, כך שאין צורך לנהל טווחי כתובות IP פנימיים, מאזני עומסים או מסלולי DNS מותאמים אישית.

ניקוי איומים מוטמע באמצעות Model Armor

הערכת פרטי הכניסה של מי שמבצע את הקריאה ואכיפת בקרת הגישה של IAM (roles/aiplatform.user) מתבצעות באופן מקורי על ידי רמת האירוח של aiplatform API. שער הכניסה עצמו לא מבצע אימות זהות, אלא מתמקד באבטחת תוכן באמצעות תוספי הרשאות שהוגדרו עם פרופיל CONTENT_AUTHZ. השער פועל כנקודת אכיפת מדיניות מוטמעת, ומיירט את ההנחיות בשפה טבעית בזמן ההעברה שלהן לפני שהן מגיעות ללולאת חשיבה רציונלית של סוכן ה-AI או למודל ה-LLM הבסיסי.

כשבקשת משתמש נכנסת מגיעה לשירות הקצה הקדמי, שער הרשת יוזם קריאה של ext_proc (עיבוד חיצוני) לשירות הרחבת ההרשאות של Model Armor באזור, שמעביר את הקריאה בסטרימינג אל מישור הנתונים של Model Armor. ‫Model Armor פועל כחומת אש בשפה טבעית, ומעריך את הטקסט בהשוואה לתבניות פעילות כדי לסרוק סיכונים שקשורים לבטיחות ולאבטחה:

  • החדרת פרומפטים עקיפה וניסיונות לפריצת המודל
  • כתובות URL זדוניות, שפה רעילה או תוכן לא בטוח
  • דליפת פרטים אישיים מזהים (PII) ונתונים רגישים

אם התבנית כוללת מסננים של Sensitive Data Protection‏ (SDP), ‏ הגנה מוגברת על המודל מבצע קריאה נוספת של gRPC לשירות Cloud SDP. ‫Cloud SDP בודק את המטען הייעודי (payload) באמצעות התבנית שצוינה, מבצע את כל הפעולות הנדרשות לביטול הזיהוי או לצנזורה, ומחזיר את התוצאה המחוטאת בחזרה לשרשרת כדי להעביר אותה בצורה בטוחה.

אם מזוהה הפרת מדיניות או התאמה לנתונים רגישים שלא עברו צנזורה, השער חוסם את מטען הנתונים או מצנזר אותו בקצה לפני שהוא נכנס לסביבת זמן הריצה. כתוצאה מכך, אפליקציית סוכן ה-AI הפועלת נשארת מוגנת ולעולם לא מעבדת מטען ייעודי (payload) זדוני או לא מצונזר.

סיימנו את החלק של ההסברים... עכשיו נעבור לקטע הגדרה.

3. הגדרה

התפקידים שצריך ב-IAM

כדי ליצור את המשאבים ב-Codelab הזה, צריך את התפקידים הבאים:

קטגוריה

תפקיד IAM נדרש (מזהה)

תיאור

ניהול API

roles/serviceusage.serviceUsageAdmin

הפעלת שירותי Google Cloud API

נטוורקינג ושער

roles/networkservices.admin

הקצאת Agent Gateway

תוספים לשירותים

roles/serviceextensions.admin

הגדרת תוספי ניתוב

אבטחת רשתות

roles/networksecurity.admin

פריסת מדיניות הרשאות

Sensitive Data Protection

roles/dlp.admin

ניהול תבניות של בדיקת SDP והסרת פרטים מזהים

הגנה מוגברת על המודל

roles/modelarmor.admin

יצירה וניהול של תבניות בטיחות

Agent Platform

roles/aiplatform.admin

פריסת עומסי עבודה של Agent Runtime

Cloud Storage

roles/storage.admin

ניהול פריסה ודלי נתוני לקוחות

ניהול IAM

roles/resourcemanager.projectIamAdmin

קישור הרשאות ברמת הפרויקט לזהות הסוכן

יומנים וביקורת

roles/logging.viewer

בדיקת עקבות ויומני ביקורת

אפשר גם להשתמש בתפקיד בסיסי רחב כמו roles/admin או בתפקיד מדור קודם כמו roles/owner.

גישה לפרויקט

בשיעור Codelab הזה משתמשים בפרויקט אחד ב-Google Cloud. בשלבי ההגדרה נעשה שימוש בפקודות של gcloud CLI ושל מעטפת Linux.

כדי להתחיל, ניגשים לשורת הפקודה של הפרויקט בענן ב-Google Cloud:

הגדרת מזהה הפרויקט

gcloud config set project SET_YOUR_PROJECT_ID_HERE

אימות הסשן

# login to gcloud cli
gcloud auth login
# login for gcloud api
gcloud auth application-default login

הגדרת סביבת מעטפת

# set custom var for slug (eg, "foo") and region preference
export SLUG="foo"
export REGION="us-central1"
echo ${SLUG}
echo ${REGION}
# create project vars (automatic)
export PROJ_ID=$(gcloud config list --format="value(core.project)")
export PROJ_NO=$(gcloud projects describe ${PROJ_ID} --format="value(projectNumber)")
export ORG_ID=$(gcloud projects get-ancestors ${PROJ_ID} --format="value(id)" | tail -n 1)
export USER_IDENTITY=$(gcloud config get-value account)
echo ${PROJ_ID}
echo ${PROJ_NO}
echo ${ORG_ID}
echo ${USER_IDENTITY}
# create resource vars (automatic)
export AGW_NAME="agw-${SLUG}-${REGION}-cta"
export AGW_URI="projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
export RE_AGENT_NAME="agent-crm"
export RE_AGENT_ID_SET="principalSet://agents.global.org-${ORG_ID}.system.id.goog/attribute.platformContainer/aiplatform/projects/${PROJ_NO}"
export STAGING_BUCKET="agent-staging-${PROJ_NO}"
export DATA_BUCKET="customer-data-${PROJ_NO}"
export MCP_URL="https://storage.mtls.googleapis.com/storage/mcp"
echo ${AGW_NAME}
echo ${AGW_URI}
echo ${RE_AGENT_NAME}
echo ${RE_AGENT_ID_SET}
echo ${STAGING_BUCKET}
echo ${DATA_BUCKET}
echo ${MCP_URL}
# create local dir for config files
mkdir -p cfg

אם אתם מריצים התקנה בניהול עצמי של ה-SDK של Google Cloud (כלומר, מחוץ ל-Cloud Shell), אתם צריכים לעדכן את הרכיבים לגרסה האחרונה.

# update gcloud cli
gcloud components update

הפעלת שירותי API

# enable google apis (agent platform bundle, part 1)
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 \
  iamconnectors.googleapis.com \
  iap.googleapis.com \
  logging.googleapis.com \
  modelarmor.googleapis.com \
  monitoring.googleapis.com \
  networksecurity.googleapis.com \
  networkservices.googleapis.com \
  notebooks.googleapis.com \
  observability.googleapis.com
# enable google apis (agent platform bundle, part 2)
gcloud services enable \
  securitycenter.googleapis.com \
  saasservicemgmt.googleapis.com \
  storage.googleapis.com \
  telemetry.googleapis.com \
  texttospeech.googleapis.com
# enable google apis (all the rest)
gcloud services enable \
  dlp.googleapis.com

כאן מסתיים החלק של ההגדרה… עכשיו נעבור לקטע שער.

4. שער

פריסה של Agent Gateway בניהול Google שפועל במצב לקוח לסוכן (CLIENT_TO_AGENT). בשונה משערי דואר יוצא שדורשים שיוכים ל-Agent Registry כדי לנתב שיחות יוצאות, שער דואר נכנס נקשר ישירות בשכבת החזית כדי לשמש כנקודת אכיפה מוטמעת להנחיות נכנסות שמיועדות ל-Agent Runtime.

מדיניות יציאה מתחילה לרוב במצב DRY_RUN בשכבת השער, אבל ניהול תוכן של תנועה נכנסת (CONTENT_AUTHZ) מופעל ישירות במצב אכיפה. במקום זאת, אפשר לשלוט בפירוט ברישום ביומן או בחסימה פעילה באמצעות תבניות הגנה מוגברת על המודל ספציפיות.

יצירת שער

# create agent gateway config file
cat > cfg/${AGW_NAME}.yaml <<EOF
name: ${AGW_NAME}
protocols:
  - MCP
googleManaged:
  governedAccessPath: CLIENT_TO_AGENT
EOF
# import agent gateway config file (create gateway)
gcloud network-services agent-gateways import ${AGW_NAME} \
  --source="cfg/${AGW_NAME}.yaml" \
  --location=${REGION}

אימות השער

# list agent gateways (in region)
gcloud network-services agent-gateways list --location=${REGION}
# show agent gateway details (verify deployment state)
gcloud network-services agent-gateways describe ${AGW_NAME} --location=${REGION}

כאן מסתיים החלק שקשור לשער... עכשיו נעבור לקטע הגנה מוגברת על המודל.

5. הגנה מוגברת על המודל

תבניות SDP

יוצרים תבנית של בדיקה והסרת פרטים מזהים (de-identification) ב-Sensitive Data Protection ‏(SDP) לשימוש בתבנית התגובה של Model Armor. ההגדרה הזו מסמנת מספרי ביטוח לאומי בארה"ב (SSN) לצורך צנזורה.

יצירת תבנית בדיקה

תבנית הבדיקה מזהה מידע אישי רגיש (US_SOCIAL_SECURITY_NUMBER) בנתונים.

# create inspect template
curl -fsS -X POST "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" \
  -d @- << EOF
{
  "templateId": "agw-ssn-inspect-template",
  "inspectTemplate": {
    "displayName": "ssn inspect template",
    "inspectConfig": {
      "infoTypes": [
        { "name": "US_SOCIAL_SECURITY_NUMBER" }
      ],
      "minLikelihood": "POSSIBLE"
    }
  }
}
EOF

יצירת תבנית לביטול הזיהוי

תבנית הסרת פרטי הזיהוי מציינת את השינוי שיש להחיל על מספרי הביטוח הלאומי שנמצאו על ידי תבנית הבדיקה. במקרה הזה, הפעולה היא החלפת מספר תעודת הזהות בסוג המידע.

# create de-identify template
curl -fsS -X POST "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" \
  -d @- << EOF
{
  "templateId": "agw-ssn-redaction-template",
  "deidentifyTemplate": {
    "displayName": "SSN Redaction Template",
    "deidentifyConfig": {
      "infoTypeTransformations": {
        "transformations": [{
          "primitiveTransformation": { "replaceWithInfoTypeConfig": {} }
        }]
      }
    }
  }
}
EOF

אימות תבניות SDP

# get (describe) inspect template
curl -fsS -X GET "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" | jq
# get (describe) de-identify template
curl -fsS -X GET "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "x-goog-user-project: ${PROJ_ID}" | jq

תבניות של הגנה מוגברת על המודל

נקודת הקצה שמוגדרת כברירת מחדל ל-Model Armor API היא גלובלית (modelarmor.googleapis.com). עם זאת, משאבי Model Armor לתבניות ולמנועי הערכה מותאמים לאזורים גיאוגרפיים ספציפיים. ה-REP (פרוקסי של נקודת קצה אזורית) או נקודת קצה ל-API אזורית של הגנה מוגברת על המודל ב-Google Cloud היא https://modelarmor.${LOCATION}.rep.googleapis.com/.

כברירת מחדל, כשמריצים את הפקודה gcloud model-armor ..., ה-CLI מנסה לשלוח בקשות API לנקודת הקצה הגלובלית הרגילה (https://modelarmor.googleapis.com/). דריסת נקודת קצה ל-API משמשת להפניה אוטומטית של כל בקשות ה-HTTP של ה-SDK/CLI עבור הגנה מוגברת על המודל ישירות ל-API ברמה האזורית rep.googleapis.com, שבה התבניות האלה שמוגבלות למיקום נוצרות, מאוחסנות ונשלחות.

הגדרת שינוי ברירת המחדל של ה-API

# set api endpoint override per location
gcloud config set api_endpoint_overrides/modelarmor "https://modelarmor.${REGION}.rep.googleapis.com/"

אימות של שינוי ברירת המחדל של ה-API

# view api overrides on active gcloud config
gcloud config list api_endpoint_overrides/

יצירת תבנית של מסנן בקשות

יוצרים תבנית של מסנן בקשות כדי לחסום דברי שטנה, הטרדה, תוכן מיני בוטה והתקפות של הזרקת URI. הרישום ביומן יופעל כדי לתעד מידע מפורט על אירועים שקשורים לאכיפת המדיניות. בנוסף, מוגדרים קודים והודעות שגיאה מותאמים אישית למקרים שבהם בקשה נחסמת.

# create model armor template (request)
gcloud beta model-armor templates create ${AGW_NAME}-modar-req-template \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --rai-settings-filters='[
    { "filterType": "HATE_SPEECH", "confidenceLevel": "MEDIUM_AND_ABOVE" },
    { "filterType": "HARASSMENT", "confidenceLevel": "MEDIUM_AND_ABOVE" },
    { "filterType": "SEXUALLY_EXPLICIT", "confidenceLevel": "MEDIUM_AND_ABOVE" }
  ]' \
  --pi-and-jailbreak-filter-settings-enforcement=enabled \
  --pi-and-jailbreak-filter-settings-confidence-level=medium-and-above \
  --template-metadata-enforcement-type=INSPECT_AND_BLOCK \
  --malicious-uri-filter-settings-enforcement=enabled \
  --template-metadata-custom-llm-response-safety-error-code=798 \
  --template-metadata-custom-llm-response-safety-error-message="ahoy! model response blocked by content filter :(" \
  --template-metadata-custom-prompt-safety-error-code=799 \
  --template-metadata-custom-prompt-safety-error-message="ahoy! the request was blocked by ye content filter... so rephrase the prompt and try again!" \
  --template-metadata-ignore-partial-invocation-failures \
  --template-metadata-log-operations \
  --template-metadata-log-sanitize-operations

יצירת תבנית של מסנן תגובות

יוצרים תבנית של מסנן תשובות כדי לחסום את אותו תוכן כמו בתבנית של מסנן הבקשות. ה-DLP מוגדר בשלב התגובה כדי להסיר את הפרטים המזהים של מספרי הביטוח הלאומי בהודעות שחוזרות מהסוכן אל הלקוח.

# create model armor template (response)
gcloud beta model-armor templates create ${AGW_NAME}-modar-resp-template \
  --project=${PROJ_ID} \
  --location=${REGION} \
  --rai-settings-filters='[
      { "filterType": "HATE_SPEECH", "confidenceLevel": "MEDIUM_AND_ABOVE" },
      { "filterType": "HARASSMENT", "confidenceLevel": "MEDIUM_AND_ABOVE" },
      { "filterType": "SEXUALLY_EXPLICIT", "confidenceLevel": "MEDIUM_AND_ABOVE" }
  ]' \
  --malicious-uri-filter-settings-enforcement=enabled \
  --advanced-config-inspect-template=projects/${PROJ_ID}/locations/${REGION}/inspectTemplates/agw-ssn-inspect-template \
  --advanced-config-deidentify-template=projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates/agw-ssn-redaction-template \
  --template-metadata-enforcement-type=INSPECT_AND_BLOCK \
  --template-metadata-custom-llm-response-safety-error-code=798 \
  --template-metadata-custom-llm-response-safety-error-message="ahoy! model response blocked by content filter :(" \
  --template-metadata-custom-prompt-safety-error-code=799 \
  --template-metadata-custom-prompt-safety-error-message="ahoy! the request was blocked by ye content filter... so rephrase the prompt and try again!" \
  --template-metadata-ignore-partial-invocation-failures \
  --template-metadata-log-operations \
  --template-metadata-log-sanitize-operations

אימות תבניות של הגנה מוגברת על המודל

# list model armor templates
gcloud model-armor templates list --location=${REGION}
# show request filter template details
gcloud model-armor templates describe ${AGW_NAME}-modar-req-template --location=${REGION}
# show response filter template details
gcloud model-armor templates describe ${AGW_NAME}-modar-resp-template --location=${REGION}

הרשאות IAM

‫הגנה מוגברת על המודל מבצע קריאות ל-API כדי להפעיל את שירות Sensitive Data Protection‏ (SDP). נותנים לזהות השירות של Model Armor הרשאות IAM להשתמש בתבניות של SDP לבדיקה ולהסרת פרטים מזהים.

קישור מדיניות IAM ל-Sensitive Data Protection

# grant dlp (sdp) user role to the model armor service identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-modelarmor.iam.gserviceaccount.com" \
  --role="roles/dlp.user"

אימות הרשאות IAM

# show iam policy for all dlp (sdp) roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.role:roles/dlp" \
  --format="table(bindings.role:label=ROLE, bindings.members:label=PRINCIPAL_IDENTITY)"

כאן מסתיים החלק של Model Armor… עכשיו נעבור לקטע הרשאה.

6. אישור

הרשאות IAM

כדי לבדוק תעבורת נתונים מוטמעת באמצעות הגנה מוגברת על המודל, לסוכן השירות של Service Extensions ‏ (DEP) נדרשים קישורי IAM מפורשים (גם בין משאבים באותו פרויקט):

  • ‫roles/modelarmor.calloutUser ו-roles/serviceusage.serviceUsageConsumer: ההרשאות שניתנו בפרויקט השער כדי לאפשר קריאות לזיהוי תכונות בתוך השורה.
  • ‫roles/modelarmor.user: הרשאה שניתנת בפרויקט התבנית כדי לאפשר גישה לתבניות של Model Armor והערכה שלהן.

קישור מדיניות IAM ל-Model Armor

# grant model armor callout user role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/modelarmor.calloutUser"

# grant service usage consumer role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/serviceusage.serviceUsageConsumer"

# grant model armor user role to dep (service extension) service agent
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/modelarmor.user"

אימות הרשאות IAM

# show iam policy on project for dep (service extension) service agent
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --format="table(bindings.members:label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"

תוסף הרשאה

הגדרת תוסף ההרשאה של Agent Gateway מגדירה את הגדרות השילוב שיחולו על תעבורת הנתונים הנכנסת והיוצאת. ההגדרה מגדירה את שירות העיבוד החיצוני (service) שמפנה אל Model Armor API האזורי, ומקשרת לתבניות הספציפיות של הבקשה והתגובה באמצעות שדה המטא-נתונים model_armor_settings.

יצירת תוסף הרשאה

# create authz extension config file (enforced mode)
cat > cfg/${AGW_NAME}-svc-ext-authz-modar.yaml <<EOF
name: ${AGW_NAME}-svc-ext-authz-modar
service: modelarmor.${REGION}.rep.googleapis.com
metadata:
  model_armor_settings: '[
    {
      "request_template_id": "projects/${PROJ_ID}/locations/${REGION}/templates/${AGW_NAME}-modar-req-template",
      "response_template_id": "projects/${PROJ_ID}/locations/${REGION}/templates/${AGW_NAME}-modar-resp-template"
    }
  ]'
failOpen: true
timeout: 5s
EOF

ייבוא תוסף הרשאות

# import authz extension file
gcloud service-extensions authz-extensions import ${AGW_NAME}-svc-ext-authz-modar \
  --source=cfg/${AGW_NAME}-svc-ext-authz-modar.yaml \
  --location=${REGION}

אימות תוסף ההרשאה

# list authz extensions
gcloud service-extensions authz-extensions list --location=${REGION}
# show authz extension details
gcloud service-extensions authz-extensions describe ${AGW_NAME}-svc-ext-authz-modar \
  --location=${REGION}

מדיניות הרשאה

מדיניות ההרשאות משתמשת בפרופילי מדיניות כדי לקבוע את סוג ההערכה שמבוצעת. פרופילים מבוססי-בקשות (REQUEST_AUTHZ) מעריכים כותרות HTTP, אבל בהגדרה הזו נעשה שימוש בפרופיל הרשאה מבוסס-תוכן (CONTENT_AUTHZ) כדי לקשור את התוסף הגנה מוגברת על המודל לשער לצורך בדיקה מעמיקה של מטען ייעודי (payload).

יצירת מדיניות הרשאות

# create authz policy config file (attach dry-run authz extension)
cat > cfg/${AGW_NAME}-authz-policy-modar.yaml <<EOF
name: ${AGW_NAME}-authz-policy-modar
target:
  resources:
    - "projects/${PROJ_ID}/locations/${REGION}/agentGateways/${AGW_NAME}"
policyProfile: CONTENT_AUTHZ
action: CUSTOM
customProvider:
  authzExtension:
    resources:
      - "projects/${PROJ_ID}/locations/${REGION}/authzExtensions/${AGW_NAME}-svc-ext-authz-modar"
EOF

ייבוא מדיניות הרשאות

# import authz policy config file (enable authz policy)
gcloud beta network-security authz-policies import ${AGW_NAME}-authz-policy-modar \
  --source=cfg/${AGW_NAME}-authz-policy-modar.yaml \
  --location=${REGION}

אימות מדיניות ההרשאה

# list authz policies
gcloud beta network-security authz-policies list --location=${REGION}
# show authz policy details
gcloud beta network-security authz-policies describe ${AGW_NAME}-authz-policy-modar \
  --location=${REGION}

כאן מסתיים החלק של ההרשאה… עכשיו עוברים לקטע Codebase.

7. בסיס קוד

קוד הסוכן ונתוני הקבצים שמשמשים ב-Codelab הזה מתעדכנים במאגר GitHub של Google Cloud. בשלבים הבאים יבוצע שיבוט של המאגר באופן מקומי, העתקה של הקבצים הדרושים למבנה של ספריית העבודה הנוכחית, ולאחר מכן ניקוי של קבצים זמניים.

אחזור פריטי מידע שנוצרים בתהליך פיתוח (Artifact) מרחוק

# clone remote repository to temp local dir
git clone https://github.com/GoogleCloudPlatform/cloud-networking-solutions.git ./temp_agw_cuj_arun_ingress_modar
# copy agent runtime and endpoint definitions to working project dir
cp -r temp_agw_cuj_arun_ingress_modar/codelabs/agw-cuj-arun-ingress-modar/agent-crm ./agent-crm
# remove temporary directory
rm -rf temp_agw_cuj_arun_ingress_modar

Agent Runtime משתמש בקטגוריית אחסון לצורך העלאה, בנייה ופריסה של קוד אפליקציית הסוכן הארוז ושל ארטיפקטים של התלות שלו.

יצירת קטגוריית אחסון להעברה זמנית

# create storage bucket
gcloud storage buckets create gs://${STAGING_BUCKET} --location=${REGION}

אימות של קטגוריית אחסון

# list storage buckets
gcloud storage buckets list --format="value(storage_url)"

עד כאן החלק שקשור לבסיס הקוד... עכשיו נעבור לקטע נתוני לקוחות ב-GCS.

נתוני לקוח

יוצרים קטגוריה של Cloud Storage לאחסון נתוני הלקוחות. הסוכן יקרא ישירות באמצעות ספריית הלקוח הרגילה של Google Cloud, ויקרא לנקודת הקצה של Cloud Storage MCP.

יצירת קטגוריית אחסון לנתוני לקוחות

# create storage bucket
gcloud storage buckets create gs://${DATA_BUCKET} --location=${REGION}

אימות של קטגוריית אחסון

# list storage buckets
gcloud storage buckets list --format="value(storage_url)"

העלאה של נתוני לקוחות

# copy local data to bucket
gcloud storage cp -r ./agent-crm/data/* gs://${DATA_BUCKET}/

אימות נתוני הלקוחות

# list bucket objects
gcloud storage ls gs://${DATA_BUCKET}/ --long

בזה מסתיים החלק בנושא נתוני לקוחות ב-GCS... עכשיו נעבור לקטע בנושא סוכן ADK.

8. סוכן ADK

סוכן ADK שנפרס ב-Agent Runtime מוגדר עם ההגדרות הבאות בסקריפט הפריסה כדי להשתלב עם Agent Platform:agent-crm

  • ‫"identity_type": types.IdentityType.AGENT_IDENTITY כדי להקצות לסוכן זהות ייחודית של גורם ראשי שמבוססת על SPIFFE
  • ‫"client_to_agent_config": {"agent_gateway": "${AGW_URI}"} כדי להפנות את כל התנועה הנכנסת של הסוכן לנתיב של הערכה ואכיפה של מדיניות שער הסוכן

בנוסף, הסוכן מקבל את כתובת ה-URL של שרת ה-mTLS MCP עבור שרת ה-MCP של Cloud Storage ואת שם קטגוריית הנתונים כדי להפעיל את כלי ה-MCP של GCS באמצעות חיבור מאובטח.

פריסת הסוכן

# deploy agent
uv --directory agent-crm run python3 deploy_agent.py \
  --project=${PROJ_ID} \
  --region=${REGION} \
  --src-dir=./agent \
  --staging-bucket=${STAGING_BUCKET} \
  --display-name="${RE_AGENT_NAME}" \
  --description="agent for customer data" \
  --mcp-server-url="${MCP_URL}" \
  --data-bucket=${DATA_BUCKET} \
  --enable-telemetry \
  --enable-agent-identity \
  --agent-gateway-ingress=${AGW_URI} \
  --allow-token-sharing

אימות הפריסה

אחזור נתונים בסיסיים של פריסה

# fetch agent runtime (reasoning engine) resource id
export RE_ENGINE_ID=$(curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  | jq -r --arg name "${RE_AGENT_NAME}" '.reasoningEngines[] | select(.displayName==$name) | .name | split("/") | last')
echo ${RE_ENGINE_ID}
# fetch agent runtime (reasoning engine) agent identity
export RE_AGENT_IDENTITY=$(gcloud agent-registry agents list \
  --project=${PROJ_ID} --location=${REGION} --filter="displayName=${RE_AGENT_NAME}" \
  --format="value(attributes.'agentregistry.googleapis.com/system/RuntimeIdentity'.principal)")
echo ${RE_AGENT_IDENTITY}

אימות הגדרות השער

# show agent runtime config details (gateway config)
curl -s -X GET "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  | jq '{displayName: .displayName, name: .name, effectiveIdentity: .spec.effectiveIdentity, agentGatewayConfig: .spec.deploymentSpec.agentGatewayConfig}'

הרשאות IAM

קישור מדיניות IAM לזהות הסוכן

# grant mcp tool user role to agent set (all agent runtime agents in project)
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_ID_SET}" \
  --role="roles/mcp.toolUser"
# grant storage object viewer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/storage.objectViewer"

# grant aiplatform user role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/aiplatform.user"

# grant cloudtrace agent role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/cloudtrace.agent"

# grant cloud monitoring metric writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/monitoring.metricWriter"
# grant cloud logging log writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/logging.logWriter"

# grant telemetry writer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/telemetry.writer"

# grant service usage consumer role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/serviceusage.serviceUsageConsumer"

# grant browser role to agent identity
gcloud projects add-iam-policy-binding ${PROJ_ID} \
  --member="${RE_AGENT_IDENTITY}" \
  --role="roles/browser"

אימות הרשאות IAM

# show agent identity roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:${RE_AGENT_IDENTITY}" \
  --format="table(bindings.members.sub('^.*locations/', 'principal://agents.[...]/locations/'):label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"
# show agent set roles on project
gcloud projects get-iam-policy ${PROJ_ID} \
  --flatten="bindings[].members" \
  --filter="bindings.members:${RE_AGENT_ID_SET}" \
  --format="table(bindings.members.sub('^.*platformContainer/', 'principalSet://agents.[...]/'):label=PRINCIPAL_IDENTITY, bindings.role:label=ROLE)"

כאן מסתיים החלק של סוכן ADK… עכשיו נעבור לקטע בדיקה.

9. בדיקה

שליחת שאילתות מ-CLI

בדיקת הנחיה בטוחה

# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
  -d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
  "input": {
    "message": "what are the names of our west customers?",
    "user_id": "test-user"
  }
}
EOF

אמורה להתקבל תגובה כמו… "הלקוחות שלנו במערב הם: דני כהן ומיכל לוי".

בדיקה של טריגר לצנזור

# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1beta1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
  -d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
  "input": {
    "message": "what are ssn's for bob johnson and alice brown?",
    "user_id": "test-user"
  }
}
EOF

בדיקת הנחיה בטוחה אחרת

# post query to agent streamQuery
curl --no-buffer -s -X POST "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}:streamQuery" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" -H "X-Goog-User-Project: ${PROJ_ID}" \
  -d @- <<EOF | jq -r --unbuffered 'if type == "array" then .[] else . end | select(.content.parts != null) | .content.parts[].text // empty'
{
  "input": {
    "message": "what are bob johnson's and alice brown's email addresses?",
    "user_id": "test-user"
  }
}
EOF

יומני ביקורת

צפייה ביומני המעקב

כשמפעילים את הטלמטריה, Agent Runtime מעביר בסטרימינג אירועים מובנים שמייצגים שאילתות של משתמשים, פרמטרים של כלים, תהליכי ביצוע ותוצאות של בחירת מודל.

# show agent runtime (reasoning engine) telemetry and trace logs
gcloud logging read \
  "logName:\"projects/${PROJ_ID}/logs/aiplatform.googleapis.com%2Freasoning_engine_stdout\" AND labels.managed-by=\"reasoning-engine\"" \
  --project=${PROJ_ID} \
  --limit=15 \
  --format="table(
    timestamp.date(format=\"%I:%M:%S %p\", tz=LOCAL):label=TIME,
    trace.basename().sub('^(.{8}).*$', '\\1'):label=TRACE_ID,
    labels.\"event.name\".scope(-1):label=EVENT,
    jsonPayload.content.role:label=ROLE,
    jsonPayload.content.parts[0].text:label=TEXT_CONTENT,
    jsonPayload.content.parts[0].function_call.name:label=TOOL_CALL
  )"

הקבוצה TRACE_ID כוללת את שאילתת המשתמש, קריאות הביניים לכלים והחלטות המודל בציר זמן אחד:

TIME         TRACE_ID  EVENT                  ROLE   TEXT_CONTENT                                     TOOL_CALL
HH:MM:SS PM  3070a1fd  gen_ai.choice          model  Bob Johnson's SSN is 219-45-7895.
                                                     Alice Brown's SSN is 219-45-7896.
HH:MM:SS PM  3070a1fd  gen_ai.user.message    user
HH:MM:SS PM  3070a1fd  gen_ai.user.message    model                                                   read_customer_file
HH:MM:SS PM  3070a1fd  gen_ai.user.message    user
HH:MM:SS PM  3070a1fd  gen_ai.user.message    model                                                   read_customer_file
HH:MM:SS PM  3070a1fd  gen_ai.user.message    user
HH:MM:SS PM  3070a1fd  gen_ai.user.message    model                                                   list_customer_files
HH:MM:SS PM  3070a1fd  gen_ai.user.message    user   what are ssn's for bob johnson and alice brown?
HH:MM:SS PM  3070a1fd  gen_ai.system.message
HH:MM:SS PM  3070a1fd  gen_ai.choice          model                                                   read_customer_file

צפייה ביומני הניקוי של Model Armor

בנתוני היומן האלה אפשר לראות בזמן אמת את האיומים ואת הסרת האיומים שמתבצעים על ידי Model Armor כשהתנועה עוברת דרך Agent Gateway.

# show model armor logs
gcloud logging read \
  "logName:\"projects/${PROJ_ID}/logs/modelarmor.googleapis.com%2Fsanitize_operations\"" \
  --project=${PROJ_ID} \
  --limit=50 \
  --format="table(
    timestamp.date(format=\"%I:%M:%S %p\", tz=LOCAL):label=TIME,
    jsonPayload.sanitizationResult.sanitizationVerdict:label=VERDICT,
    jsonPayload.sanitizationInput.byteItem.byteData.decode(base64).decode(utf-8).sub('\n', ' \\\\\\\\n ').trailoff(123):label=INPUT_DATA
  )"

שימו לב לרשומה ביומן של הבקשה שעברה ניקוי ונחסמה.

TIME         VERDICT                                 INPUT_DATA
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW  Bob Johnson's email address is bob.j@example.com. \n Alice Brown's email address is alice.b...
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW  what are bob johnson's and alice brown's email addresses?
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_BLOCK  6��
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW  what are ssn's for bob johnson and alice brown?
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW  Our west customers are: Bob Johnson and Alice Brown.
HH:MM:SS PM  MODEL_ARMOR_SANITIZATION_VERDICT_ALLOW  what are the names of our west customers?

כאן מסתיים החלק של הבדיקה… עכשיו נעבור אל הקטע ניקוי נתונים.

10. הסרת המשאבים

# remove agent iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/storage.objectViewer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/aiplatform.user"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/cloudtrace.agent"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/monitoring.metricWriter"

# next
# remove more agent and agent set iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/logging.logWriter"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/telemetry.writer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/serviceusage.serviceUsageConsumer"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_IDENTITY}" --role="roles/browser"

# next
# remove rest of iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="${RE_AGENT_ID_SET}" --role="roles/mcp.toolUser"
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} --member="serviceAccount:service-${PROJ_NO}@gcp-sa-modelarmor.iam.gserviceaccount.com" --role="roles/dlp.user"

# next
# delete agent runtime (reasoning engine) agent
curl -s -X DELETE "https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJ_ID}/locations/${REGION}/reasoningEngines/${RE_ENGINE_ID}?force=true" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json"

# next
# delete storage
gcloud -q storage rm --recursive gs://${STAGING_BUCKET}
gcloud -q storage rm --recursive gs://${DATA_BUCKET}

# next
# delete authz resources
gcloud -q beta network-security authz-policies delete ${AGW_NAME}-authz-policy-modar --location=${REGION}

gcloud -q beta service-extensions authz-extensions delete ${AGW_NAME}-svc-ext-authz-modar --location=${REGION} --async

# next
# remove dep (service extensions) service agent iam bindings
gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/modelarmor.calloutUser"

gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/serviceusage.serviceUsageConsumer"

gcloud -q projects remove-iam-policy-binding ${PROJ_ID} \
  --member="serviceAccount:service-${PROJ_NO}@gcp-sa-dep.iam.gserviceaccount.com" \
  --role="roles/modelarmor.user"

# next
# delete model armor templates
gcloud -q model-armor templates delete ${AGW_NAME}-modar-resp-template --location=${REGION}
gcloud -q model-armor templates delete ${AGW_NAME}-modar-req-template --location=${REGION}

# unset model armor api endpoint override
gcloud config unset api_endpoint_overrides/modelarmor

# next
# delete sdp (dlp) templates
curl -fsS -X DELETE "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/deidentifyTemplates/agw-ssn-redaction-template" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "x-goog-user-project: ${PROJ_ID}"

curl -fsS -X DELETE "https://dlp.googleapis.com/v2/projects/${PROJ_ID}/locations/${REGION}/inspectTemplates/agw-ssn-inspect-template" \
  -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "x-goog-user-project: ${PROJ_ID}"

# next
# delete agent gateway ingress
gcloud -q network-services agent-gateways delete ${AGW_NAME} --location=${REGION} --async

# end

כאן מסתיים החלק של ניקוי הנתונים... עכשיו נעבור אל הקטע מסקנה.

11. סיכום

מעולה! הצלחתם לפרוס את Agent Gateway ולנהל את התנועה הנכנסת לסוכן AI.

cosmopup

Cosmopup חושב ש-Codelabs הם מצוינים!

מה השלב הבא?

אתם מוזמנים להשתמש בטופס המשוב הזה כדי לשלוח הערות, שאלות או תיקונים.

תודה!