איסוף יומנים של Google App Engine

גרסת המנתח: 3.0

נתמך ב:

במסמך הזה מוסבר איך להטמיע יומנים של Google App Engine ב-Google Security Operations באמצעות Google Cloud Storage V2.

‫Google App Engine היא פלטפורמה מנוהלת ללא שרת (serverless) לבנייה ולפריסה של אפליקציות אינטרנט וממשקי API. מערכת App Engine יוצרת באופן אוטומטי יומני בקשות לבקשות HTTP ויומני אפליקציות מהקוד שלכם. היומנים האלה נשלחים ל-Cloud Logging ואפשר לייצא אותם ל-Cloud Storage כדי להטמיע אותם ב-Google Security Operations.

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

חשוב לוודא שמתקיימות דרישות הסף הבאות:

  • מכונה של Google SecOps
  • פרויקט ב-GCP עם Cloud Storage API מופעל
  • הרשאות ליצירה ולניהול של קטגוריות ב-GCS
  • הרשאות לניהול מדיניות IAM בקטגוריות GCS
  • הרשאות ליצירת sinks ב-Cloud Logging ‏ (roles/logging.configWriter)
  • אפליקציית App Engine פעילה (סביבה רגילה או גמישה)

יצירת קטגוריה של Google Cloud Storage

  1. נכנסים למסוף Google Cloud.
  2. בוחרים פרויקט או יוצרים פרויקט חדש.
  3. בתפריט הניווט, נכנסים ל-Cloud Storage > Buckets.
  4. לוחצים על Create bucket.
  5. מספקים את פרטי ההגדרה הבאים:

    הגדרה ערך
    Name your bucket מזינים שם ייחודי ברמה גלובלית (לדוגמה, appengine-logs-export)
    סוג המיקום בוחרים לפי הצרכים (אזור, שני אזורים, מספר אזורים)
    Location בוחרים את המיקום (לדוגמה, us-central1).
    סוג האחסון (storage class) רגיל (מומלץ ליומנים שנכנסים אליהם לעיתים קרובות)
    בקרת גישה אחיד (מומלץ)
    כלי הגנה אופציונלי: הפעלת ניהול גרסאות של אובייקטים או מדיניות שמירת נתונים
  6. לוחצים על יצירה.

הגדרת Cloud Logging לייצוא יומני App Engine ל-GCS

ב-Cloud Logging, רשומות ביומן מנותבות ליעדים נתמכים, כולל קטגוריות של Cloud Storage, באמצעות כיורים ביומן. לזהות הכותב של יעד הנתונים נדרש התפקיד 'יצירת אובייקטים של אחסון' (roles/storage.objectCreator) בקטגוריית היעד.

יצירת sink ב-Cloud Logging

  1. במסוף Google Cloud, נכנסים לדף Logging > Log Router.
  2. לוחצים על Create sink (יצירת יעד).
  3. מזינים את פרטי ההגדרה הבאים:
    • שם יעד: מזינים שם תיאורי (לדוגמה, appengine-to-gcs).
    • תיאור הכיור: תיאור אופציונלי.
  4. לוחצים על הבא.
  5. בקטע Select sink service (בחירת שירות יעד):
    • שירות היעד: בוחרים באפשרות קטגוריה של Cloud Storage.
    • בחירת קטגוריית אחסון של Cloud Storage: בוחרים באפשרות appengine-logs-export מהתפריט הנפתח.
  6. לוחצים על הבא.
  7. בקטע Choose logs to include in sink, מזינים שאילתת סינון כדי לבחור את היומנים של App Engine. סוג המשאב חייב להיות בדיוק "gae_app".

    לכל היומנים של App Engine (יומני בקשות ויומני אפליקציות):

    resource.type="gae_app"
    

    רק עבור יומני בקשות של App Engine:

    resource.type="gae_app"
    logName="projects/PROJECT_ID/logs/appengine.googleapis.com/request_log"
    

    ביומני האפליקציות של App Engine‏ (stdout/stderr):

    resource.type="gae_app"
    (logName="projects/PROJECT_ID/logs/stdout" OR logName="projects/PROJECT_ID/logs/stderr")
    

    מחליפים את PROJECT_ID במזהה הפרויקט ב-GCP.

  8. לוחצים על הבא.

  9. בודקים את ההגדרות ולוחצים על Create sink (יצירת מאגר).

מתן הרשאות לזהות של כותב היעד

אחרי שיוצרים את הכיור, צריך להקצות לזהות הכותב של הכיור את התפקיד "יצירת אובייקטים של אחסון" בקטגוריית היעד. הזהות של חשבון השירות עם הרשאת הכתיבה נראית בערך כך: serviceAccount:service-123456789012@gcp-sa-logging.iam.gserviceaccount.com

  1. בדף Log Router, מאתרים את ה-sink החדש שנוצר.
  2. לוחצים על סמל התפריט (שלוש נקודות אנכיות) לצד שם הכיור.
  3. בוחרים באפשרות View sink details.
  4. מעתיקים את הזהות של הכותב (כתובת האימייל של חשבון השירות).
  5. עוברים אל Cloud Storage > Buckets.
  6. לוחצים על שם הקטגוריה (appengine-logs-export).
  7. עוברים לכרטיסייה Permissions.
  8. לוחצים על הענקת גישה.
  9. מזינים את פרטי ההגדרה הבאים:
    • הוספת חשבונות משתמשים: מדביקים את זהות הכותב של הכיור (כתובת האימייל של חשבון השירות).
    • הקצאת תפקידים: בוחרים באפשרות יצירת אובייקטים של אחסון.
  10. לוחצים על Save.

אחזור חשבון השירות של Google SecOps

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

הגדרה של פיד ב-Google SecOps להטמעה של יומנים מ-App Engine

  1. עוברים אל SIEM Settings > Feeds.
  2. לוחצים על הוספת פיד חדש.
  3. לוחצים על הגדרת פיד יחיד.
  4. בשדה שם הפיד, מזינים שם לפיד (לדוגמה, App Engine Logs).
  5. בוחרים באפשרות Google Cloud Storage V2 בתור סוג המקור.
  6. בוחרים באפשרות GCP_APP_ENGINE בתור Log type.

  7. לוחצים על Get Service Account (קבלת חשבון שירות).

  8. תוצג כתובת אימייל ייחודית של חשבון שירות, לדוגמה:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  9. מעתיקים את כתובת האימייל הזו. תשתמשו בו בשלב הבא.

  10. לוחצים על הבא.

  11. מציינים ערכים לפרמטרים הבאים של הקלט:

    • כתובת ה-URL של קטגוריית האחסון: מזינים את ה-URI של קטגוריית GCS עם נתיב הקידומת:

      gs://appengine-logs-export/
      

      ב-Cloud Logging, קובצי היומן שמיוצאים מאורגנים בהיררכיות של ספריות לפי סוג היומן והתאריך. סוג היומן יכול להיות שם מורכב כמו appengine.googleapis.com/request_log. הקבצים מחולקים למקטעים ונקראים לפי תקופות (לדוגמה, 08:00:00_08:59:59_S0.json).

    • אפשרות למחיקת המקור: בוחרים את אפשרות המחיקה לפי ההעדפה שלכם:

      • אף פעם: לא נמחקים קבצים אחרי ההעברה (מומלץ לבדיקות).
      • מחיקת קבצים שהועברו: מחיקת קבצים אחרי שהם הועברו בהצלחה.
      • מחיקת קבצים שהועברו וספריות ריקות: מחיקת קבצים וספריות ריקות אחרי שההעברה מסתיימת.
    • גיל מקסימלי של קובץ: כולל קבצים ששונו במספר הימים האחרונים. ברירת המחדל היא 180 ימים.

    • מרחב השמות של הנכס: מרחב השמות של הנכס.

    • תוויות הטמעה: התווית שתתווסף לאירועים מהפיד הזה.

  12. לוחצים על הבא.

  13. בודקים את ההגדרות של הפיד החדש במסך סיום ולוחצים על שליחה.

הקצאת הרשאות IAM לחשבון השירות של Google SecOps

חשבון השירות של Google SecOps צריך את התפקיד צפייה באובייקט אחסון בקטגוריית GCS.

  1. נכנסים לדף Cloud Storage > Buckets.
  2. לוחצים על שם הקטגוריה (appengine-logs-export).
  3. עוברים לכרטיסייה Permissions.
  4. לוחצים על הענקת גישה.
  5. מזינים את פרטי ההגדרה הבאים:
    • Add principals (הוספת חשבונות משתמשים): מדביקים את כתובת האימייל של חשבון השירות של Google SecOps.
    • הקצאת תפקידים: בוחרים באפשרות צפייה באובייקט אחסון.
  6. לוחצים על Save.

הסבר על מבנה היומן של App Engine

‫App Engine שולח באופן אוטומטי גם יומני בקשות וגם יומני אפליקציות ל-Cloud Logging. ‫App Engine מפיק באופן אוטומטי יומנים של בקשות שנשלחות לאפליקציה, כך שאין צורך לכתוב יומנים של בקשות. בקטע הזה מוסבר איך לכתוב יומני אפליקציות.

ביומני הבקשות של App Engine יש רשומות ביומן שמכילות שדות protoPayload שמחזיקים אובייקטים מסוג RequestLog עם @type ‏'type.googleapis.com/google.appengine.logging.v1.RequestLog'. סוג המשאב הוא gae_app.

כברירת מחדל, מטען היומן הוא מחרוזת טקסט שמאוחסנת בשדה textPayload של רשומת היומן. המחרוזות מופיעות כהודעות ב-Logs Explorer ומשויכות לשירות ולגרסה של App Engine שהפיקו אותן.

כדי לכתוב יומנים מובְנים, כותבים יומנים בצורה של שורה אחת של JSON שעבר סריאליזציה. כשמספקים יומן מובנה כמילון JSON, חלק מהשדות המיוחדים מוסרים מ-jsonPayload ונכתבים בשדה התואם ב-LogEntry שנוצר. לדוגמה, אם קובץ ה-JSON כולל מאפיין חומרה, הוא יוסר מ-jsonPayload ויופיע במקום זאת כחומרה של רשומת היומן.

מגבלות ידועות

כשמנתבים יומנים מ-sink ביומן ל-Cloud Storage, היעד ב-Cloud Storage מכיל רק יומני בקשות. ‫App Engine כותב את יומני האפליקציות בתיקיות שונות.

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

בסביבה הגמישה ב-App Engine, הרישום מתבצע באופן אוטומטי. עם זאת, היומנים נאספים בפורמט שונה. היומנים לא יקובצו לפי בקשות, והיומנים מ-stdout ומ-stderr ייאספו בנפרד.

טבלת מיפוי UDM

שדה ביומן מיפוי UDM היגיון
jsonPayload.logger, taskTypeName, jsonPayload.@type, jsonPayload.backendTargetProjectNumber, jsonPayload.cacheDecision, resource.labels.version_id, resource.labels.module_id, logName, spanId, trace, protoPayload.@type, labels.clone_id, operation.producer additional.fields מיזוג עם תוויות של מפתח/ערך שנוצרו מכל שדה
מטא-נתונים מטא-נתונים שם חדש במקום מטא-נתונים
receiveTimestamp metadata.collected_timestamp נותח באמצעות מסנן תאריכים עם RFC 3339
metadata.event_type הערך הוא USER_LOGIN אם יש has_principal,‏ has_target,‏ has_principal_user;‏ NETWORK_CONNECTION אם יש has_principal ו-has_target;‏ USER_UNCATEGORIZED אם אין has_principal ויש has_target;‏ STATUS_UPDATE אם יש has_principal;‏ USER_UNCATEGORIZED אם יש has_principal_user; אחרת, הערך הוא GENERIC_EVENT.
metadata.extensions.auth.type צריך להגדיר את הערך "AUTHTYPE_UNSPECIFIED" אם יש has_principal, ‏ has_target, ‏ has_principal_user
insertId metadata.product_log_id הערך הועתק ישירות
httpRequest.requestMethod,protoPayload.method network.http.method הערך מ-httpRequest.requestMethod אם הוא לא ריק, אחרת הערך מ-protoPayload.method
httpRequest.userAgent network.http.parsed_user_agent ההמרה ל-parseduseragent בוצעה
httpRequest.status network.http.response_code הומר למחרוזת ואז למספר שלם
httpRequest.userAgent network.http.user_agent הערך הועתק ישירות
httpRequest.responseSize network.received_bytes הומר ל-uinteger
httpRequest.requestSize network.sent_bytes הומר ל-uinteger
משתמש (principal) משתמש (principal) השם שונה מהשם הראשי אם הוא לא ריק
protoPayload.host principal.asset.hostname הערך הועתק ישירות
httpRequest.serverIp, protoPayload.ip principal.asset.ip מוזג עם server_ip מ-httpRequest.serverIp או מ-protoPayload.ip
protoPayload.host principal.hostname הערך הועתק ישירות
httpRequest.serverIp, protoPayload.ip principal.ip מוזג עם server_ip מ-httpRequest.serverIp או מ-protoPayload.ip
protoPayload.appId principal.resource.attribute.labels מוזג עם התווית appId_label שמכילה את המפתח appId ואת הערך מהשדה
requestUser principal.user.email_addresses מוזג עם requestUser אם יש התאמה לתבנית האימייל
security_result security_result Merged from security_result
resource.labels.forwarding_rule_name security_result.rule_labels מוזג עם rule_label שמכיל את המפתח "forwarding_rule_name" ואת הערך מהשדה
severity security_result.severity מוגדר לערך חומרה אם יש התאמה ל-‎ (?i)ERROR|CRITICAL, ‏ INFORMATIONAL אם יש התאמה ל-‎ (?i)INFO, ‏ MEDIUM אם יש התאמה ל-‎ (?i)WARN, ‏ LOW אם יש התאמה ל-‎ (?i)DEBUG, אחרת UNKNOWN_SEVERITY
jsonPayload.statusDetails security_result.summary הערך הועתק ישירות
יעד target השם החדש הוא target אם הוא לא ריק
resource.labels.backend_service_name target.application הערך הועתק ישירות
httpRequest.remoteIp, jsonPayload.remoteIp target.asset.ip מוזג עם remote_ip שחולץ מ-httpRequest.remoteIp או מ-jsonPayload.remoteIp
resource.labels.project_id target.cloud.project.name הערך הועתק ישירות
httpRequest.remoteIp, jsonPayload.remoteIp target.ip מוזג עם remote_ip שחולץ מ-httpRequest.remoteIp או מ-jsonPayload.remoteIp
resource.labels.zone target.resource.attribute.cloud.availability_zone הערך הועתק ישירות
resource.labels.target_proxy_name, resource.labels.url_map_name target.resource.attribute.labels ממוזג עם תוויות מכל מקור
resource.type target.resource.type הערך הועתק ישירות
httpRequest.requestUrl target.url הערך הועתק ישירות
metadata.product_name מגדירים את הערך "GCP_APP_ENGINE"
metadata.vendor_name מגדירים את הערך "GCP"
protoPayload.requestMetadata.callerIp event.idm.read_only_udm.principal.ip מופה מיומן השינויים
protoPayload.requestMetadata.callerIp event.idm.read_only_udm.principal.asset.ip מופה מיומן השינויים
protoPayload.authenticationInfo.principalEmail event.idm.read_only_udm.principal.user.email_addresses מופה מיומן השינויים
protoPayload.methodName event.idm.read_only_udm.metadata.product_event_type מופה מיומן השינויים
protoPayload.resourceName event.idm.read_only_udm.target.resource.name מופה מיומן השינויים
protoPayload.serviceName event.idm.read_only_udm.target.application מופה מיומן השינויים
protoPayload.resourceLocation.currentLocations event.idm.read_only_udm.target.resource.attribute.labels מופה מיומן השינויים
protoPayload.authenticationInfo.oauthInfo.oauthClientId event.idm.read_only_udm.principal.resource.attribute.labels מופה מיומן השינויים
protoPayload.requestMetadata.requestAttributes.time event.idm.read_only_udm.additional.fields מופה מיומן השינויים
operation.first event.idm.read_only_udm.additional.fields מופה מיומן השינויים
protoPayload.serviceData.updateService.request.updateMask event.idm.read_only_udm.additional.fields מופה מיומן השינויים
operation.id event.idm.read_only_udm.additional.fields מופה מיומן השינויים
protoPayload.authenticationInfo.serviceAccountKeyName event.idm.read_only_udm.additional.fields מופה מיומן השינויים
protoPayload.authorizationInfo.permission event.idm.read_only_udm.security_result.rule_name מופה מיומן השינויים
protoPayload.authorizationInfo.permissionType event.idm.read_only_udm.security_result.description מופה מיומן השינויים
protoPayload.authorizationInfo.granted event.idm.read_only_udm.security_result.action מופה מיומן השינויים
protoPayload.@type" , "labels.clone_id" and "operation.producer additional.labels מופה מיומן השינויים

יומן שינויים

צפייה ביומן השינויים של המנתח הזה

הבעיה עדיין לא נפתרה? קבלת תשובות מחברי הקהילה וממומחי Google SecOps.