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

במאמר הזה מוסבר איך לקשר בין יומני חיטוי של Model Armor לבין יומני פלטפורמה ופרקי זמן של מעקב ב-Gemini Enterprise ב-Cloud Logging. במאמר מוסבר על מנגנוני הקורלציה של זרימות תעבורת נתונים מלקוח לסוכן (תעבורת נתונים נכנסת (ingress)) ומסוכן לכל מקום (תעבורת נתונים יוצאת (egress)), מפורטים התנאים המוקדמים ליצירת יומן מעקב ומסופקות הוראות מפורטות ודוגמאות קוד להצטרפות לרשומות ביומן האלה בפייפליין לעיבוד יומנים.

כשבודקים טווח מעקב או רשומה ביומן של Model Armor, יכול להיות שיהיה צורך לאתר את הרשומות התואמות ב-Cloud Logging כדי לקבל את ההקשר המלא של הבקשה. לדוגמה:

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

איך מתבצעת קורלציה של יומנים

‫הגנה מוגברת על המודל יכול לסנן פרומפטים ותשובות בנקודות התקשורת הבאות ב-Gemini Enterprise:

  • תעבורה מלקוח לסוכן (ingress): כשמשתמש שולח פרומפט לעוזר Gemini Enterprise, ‏ Gemini Enterprise קורא ישירות לממשקי ה-API של הגנה מוגברת על המודל. יומני הפלטפורמה של הגנה מוגברת על המודל (SanitizeOperation) לא מכילים ישירות שדות של OpenTelemetry‏ (trace) או של spanId. כדי ליצור קורלציה בין היומנים האלה לבין זהויות משתמשים ולעקוב אחרי טווחים, צריך לבצע log join בצינור לעיבוד יומנים או בניהול אבטחת מידע ואירועים (SIEM) באמצעות טוקן הסשן.

  • תנועה מסוג Agent-to-Anywhere (יוצאת): כשסוכן מתקשר עם כלי חיצוני, שרת Model Context Protocol‏ (MCP) או מודל שפה גדול (LLM) חיצוני, התנועה מנותבת דרך Agent Gateway ו-Secure Web Proxy. בשיחות יוצאות, כשמופעלת מדידה באמצעות OpenTelemetry, היומנים של Model Armor SanitizeOperation מכילים את השדות trace ו-spanId ישירות. אפשר לסנן יומנים ישירות ולהציג את טווחי המעקב ב-Cloud Trace או ב-Agent Registry.

סיכום של מנגנוני קורלציה

Flow נתיב וניתוב מעקב ביומן של הגנה מוגברת על המודל שיטת הקורלציה
לקוח לסוכן (תנועה נכנסת) קריאה ישירה ל-API מ-Gemini Enterprise אל Model Armor המאפיינים trace ו-spanId לא מאוכלסים. רישום הצטרפות באמצעות אסימון הסשן מ-client_correlation_id ומ-assistToken
Agent-to-Anywhere (יציאה) הניתוב מתבצע דרך Agent Gateway ו-Secure Web Proxy השדות trace וspanId יאוכלסו. התאמה ישירה בtrace מזהה ובבדיקת יחידה לוגית למעקב של יומן מעקב

לפני שמתחילים

לפני שמתחילים להשוות בין יומני Model Armor לבין יומני Gemini Enterprise, צריך לבצע את השלבים הבאים:

  1. הפעלת הגנה מוגברת על המודל ב-Gemini Enterprise.
  2. כדי ליצור הקשר של מעקב ולהציג את פרטי המעקב ביומנים של Gemini Enterprise ושל הגנה מוגברת על המודל, מפעילים את האפשרות Enable instrumentation of OpenTelemetry traces and logs (הפעלת מכשור של מעקבים ויומנים של OpenTelemetry) וגם את האפשרות Enable logging of prompt inputs and response outputs (הפעלת רישום ביומן של קלט הנחיות ופלט תגובות) בהגדרות הנראות. הוראות מפורטות מופיעות במאמר בנושא הפעלת הגדרות של יכולת תצפית.
  3. כדי לסנן תעבורת נתונים יוצאת (egress), מגדירים את Model Armor ב-Agent Gateway.

התפקידים הנדרשים

כדי לקבל את ההרשאות שדרושות להצגה ולשיוך של יומנים ופרקי זמן של מעקב, צריך לבקש מהאדמין להקצות לכם את תפקידי ה-IAM הבאים בפרויקט:

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

יכול להיות שאפשר לקבל את ההרשאות הנדרשות גם באמצעות תפקידים בהתאמה אישית או תפקידים מוגדרים מראש.

מידע על תפקידים נוספים שאולי תצטרכו מופיע במאמרים בקרת גישה ל-Trace ובקרת גישה ל-Cloud Logging.

התאמה בין יומנים של לקוח לסוכן (תנועה נכנסת)

אינטראקציה אחת של StreamAssist יוצרת שלוש רשומות שונות ביומן ב-Cloud Logging:

  • יומן של ניקוי נתונים ב-Model Armor (SanitizeOperation):
    • משאב במעקב: modelarmor.googleapis.com/SanitizeOperation
    • מאפיינים: מכיל את פסק הדין המפורט של הסניטציה וממצאי הבטיחות (כמו צנזורה של פרטים אישיים מזהים, התאמות של מסנני אתיקה של בינה מלאכותית או זיהוי של הזרקת הנחיות), אבל לא מכיל הקשר של מעקב או זהות של משתמש קצה.
    • מפתח קורלציה: labels."modelarmor.googleapis.com/client_correlation_id"
  • יומן של Gemini Enterprise StreamAssist‏ (consumed_api):
    • משאב במעקב: consumed_api
    • מאפיינים: מכיל את זהות משתמש הקצה (userIamPrincipal), את פרטי המעקב (trace ו-spanId) ואת טוקן הסשן (response.assistToken).
    • מפתח קורלציה: jsonPayload.response.assistToken
  • Gemini Enterprise ModelArmorAudit Log (Agent):
    • Monitored Resource: discoveryengine.googleapis.com/Agent where jsonPayload.logMetadata.methodName is ModelArmorAudit.
    • מאפיינים: משקפים את התוצאה של החיטוי ברמה הגבוהה, ומכילים את ההקשר של המעקב (trace ו-spanId), אבל לא מכילים ממצאים מפורטים או מזהי קורלציה.
    • מפתח קורלציה: trace

מפתח איחוד (join) של קורלציה

יומני החיטוי של Model Armor כוללים תווית client_correlation_id עם מבנה מופרד באמצעות קו אנכי. הקטע השלישי של התווית הזו הוא טוקן סשן בקידוד Base64URL שתואם לשדה assistToken שמתועד ביומן consumed_api עבור StreamAssist.

התווית client_correlation_id היא בפורמט הבא:

AS|ASSISTANT_RESOURCE|SESSION_TOKEN

מזהה הקורלציה כולל את הערכים הבאים:

  • ASSISTANT_RESOURCE: שם המשאב המלא של משאב Gemini Enterprise‏ Assistant בפורמט הבא:
    projects/PROJECT/locations/LOCATION/collections/COLLECTION/engines/ENGINE/assistants/ASSISTANT
  • SESSION_TOKEN: טוקן לסשן הייחודי שתואם ל-assistToken ביומן consumed_api אחרי שהריפוד של base64url עבר נירמול.

לוגיקה של התאמה

כדי לבצע קורלציה בין רשומה ביומן של ניקוי נתונים באמצעות Model Armor לבין יומנים של Gemini Enterprise StreamAssist, צריך להטמיע את לוגיקת ההתאמה הבאה בצינור לעיבוד יומנים:

  1. שולפים את טוקן הסשן מהערך הגנה מוגברת על המודל:

    1. מאתרים את האובייקט labels ברשומה הגנה מוגברת על המודל.
    2. אחזור הערך של התווית modelarmor.googleapis.com/client_correlation_id.
    3. מפצלים את הערך של התווית באמצעות התו | (|).
    4. מחפשים את הפלח השלישי, שמייצג את אסימון הסשן בקידוד base64url.
  2. חילוץ הערך assistToken מהרשומות StreamAssist: לכל רשומה ביומן StreamAssist consumed_api של מועמד, פועלים לפי השלבים הבאים:

    1. מאתרים את אובייקט jsonPayload.
    2. מחפשים את הערך של הטוקן בשדה response.assistToken.
  3. נרמול האסימונים והשוואה ביניהם: כדי להשוות בין האסימונים, צריך לנרמל את שני מחרוזות האסימונים:

    1. החלפה של כל המקפים (-) בסימני פלוס (+).
    2. מחליפים את כל התווים של קו תחתון (_) בקו נטוי (/).
    3. מסירים את כל סימני השווה (=) בסוף.
    4. אם הטוקנים שעברו נורמליזציה תואמים, מתבצעת קורלציה בין רשומות היומן.
  4. חילוץ הנתונים המתאימים: אם נמצאה התאמה, מחלצים את השדות הבאים מהרשומות התואמות:

    • זהות IAM של המשתמש: השדה userIamPrincipal מהרשומה StreamAssist
    • Trace ID: השדה trace מהרשומה StreamAssist
    • Span ID: השדה spanId מהרשומה StreamAssist
    • ההחלטה לגבי הסרת מידע אישי: השדה sanitizationVerdict בקטע jsonPayload.sanitizationResult ברשומה של הגנה מוגברת על המודל

דוגמה למתאם ב-Python

בסקריפט Python הבא מוצגות דוגמאות לשאילתות ב-Cloud Logging לגבי יומנים של הגנה מוגברת על המודל ו-Gemini Enterprise, לביצוע נורמליזציה של אסימונים והתאמה שלהם, ולפלט של הרשומות שבוצעה לגביהן קורלציה:

#!/usr/bin/env python3
from datetime import datetime, timedelta, timezone
from google.cloud import logging

# Google Cloud project ID
PROJECT_ID = "YOUR_PROJECT_ID"


def correlate_logs(ma_entry, de_consumed_entries):
  """Correlates a Model Armor log entry with StreamAssist logs."""
  # 1. Extract client_correlation_id from Model Armor log labels
  labels = ma_entry.get("labels", {})
  client_corr_id = labels.get(
      "modelarmor.googleapis.com/client_correlation_id", ""
  )
  if not client_corr_id:
    return None

  # 2. Extract session token (3rd pipe-delimited segment)
  parts = client_corr_id.split("|")
  if len(parts) < 3:
    return None
  ma_token = parts[2]

  # 3. Normalize base64url padding for comparison
  ma_token_normalized = ma_token.replace("-", "+").replace("_", "/").rstrip("=")

  # 4. Search for matching assistToken in StreamAssist logs
  for de in de_consumed_entries:
    payload = de.get("jsonPayload", {})
    de_token = payload.get("response", {}).get("assistToken", "")
    de_token_normalized = (
        de_token.replace("-", "+").replace("_", "/").rstrip("=")
    )

    if ma_token_normalized == de_token_normalized:
      return {
          "user": payload.get("userIamPrincipal"),
          "trace": de.get("trace"),
          "span_id": de.get("spanId"),
          "verdict": (
              ma_entry.get("jsonPayload", {})
              .get("sanitizationResult", {})
              .get("sanitizationVerdict")
          ),
      }
  return None


def main():
  # Initialize Google Cloud Logging Client
  print(f"Connecting to Google Cloud Logging (Project: {PROJECT_ID})...")
  client = logging.Client(project=PROJECT_ID)

  # Calculate ISO timestamp for 1 hour ago
  one_hour_ago = (
      datetime.now(timezone.utc) - timedelta(hours=1)
  ).strftime("%Y-%m-%dT%H:%M:%SZ")
  print(f"Filtering logs starting from: {one_hour_ago}")

  # Build log query filters
  ma_filter = f"""
    resource.type="modelarmor.googleapis.com/SanitizeOperation"
    AND timestamp >= "{one_hour_ago}"
    """

  de_filter = f"""
    resource.type="consumed_api"
    AND jsonPayload.response.assistToken:*
    AND timestamp >= "{one_hour_ago}"
    """

  # Fetch Model Armor log entries
  print("Fetching Model Armor log entries...")
  ma_entries = [
      entry.to_api_repr()
      for entry in client.list_entries(filter_=ma_filter, max_results=100)
  ]
  print(f"Found {len(ma_entries)} Model Armor entries.")

  # Fetch Gemini Enterprise log entries
  print("Fetching Gemini Enterprise StreamAssist log entries...")
  de_entries = [
      entry.to_api_repr()
      for entry in client.list_entries(filter_=de_filter, max_results=500)
  ]
  print(f"Found {len(de_entries)} Gemini Enterprise entries.")

  # Perform Correlation
  print("\n================ Correlating Logs ================")
  correlated_results = []
  for ma in ma_entries:
    match = correlate_logs(ma, de_entries)
    if match:
      correlated_results.append(match)
      print(f"  User IAM Principal  : {match['user']}")
      print(f"  Sanitization Verdict: {match['verdict']}")
      print(f"  Trace ID            : {match['trace']}")
      print(f"  Span ID             : {match['span_id']}")
      print("-" * 50)

  print(f"\nDone. Total Correlated Records: {len(correlated_results)}")


if __name__ == "__main__":
  main()

התאמה בין יומנים של Agent-to-Anywhere (יציאה) לבין טווחים של מעקב

כשסוכן מבצע קריאות לכלים (כמו אינטראקציה עם שרת MCP או עם ממשקי API חיצוניים) שמוגנים על ידי Agent Gateway ו-Model Armor, הבקשה היא חלק מהתנועה של Agent-to-Anywhere.

כשמפעילים את המכשיר OpenTelemetry באפליקציה, רשומות היומן שמתקבלות SanitizeOperation כוללות באופן אוטומטי את השדות trace ו-spanId.

סינון יומני תעבורה יוצאת ב-Cloud Logging

כדי למצוא את כל יומני החיטוי של הגנה מוגברת על המודל שמשויכים ליומן מעקב ספציפי ב-Cloud Logging, משתמשים במסנן השאילתות הבא:

resource.type="modelarmor.googleapis.com/SanitizeOperation"
trace="TRACE_ID"

מחליפים את TRACE_ID במזהה המעקב מאינטראקציית הסוכן.

מידע נוסף זמין במאמר הצגה וניתוח של רשומות ביומן.

צפייה בטווחים של פרטי ההעברה

ב-Trace או ב-Agent Registry, אפשר לראות את גרף הביצוע ואת צירי הזמן של האינטראקציה עם הסוכן. ‫Model Armor יוצר את טווחי הטקסט הבאים:

  • יחידה לוגית למעקב של ההורה: apply_guardrail "Google Cloud Model Armor"
  • טווחים של ילדים: Request Path ו-Response Path

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

המאמרים הבאים