איסוף יומנים של 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) בקטגוריית היעד.

יצירת יעד ב-Cloud Logging

  1. ב-מסוף Google Cloud, עוברים אל רישום ביומן > 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, מאתרים את היעד החדש שנוצר.
  2. לוחצים על סמל התפריט (שלוש נקודות אנכיות) לצד שם היעד.
  3. בוחרים באפשרות הצגת פרטים של יעד.
  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 (הגדרות SIEM > פידים).
  2. לוחצים על הוספת פיד חדש.
  3. לוחצים על הגדרת פיד יחיד.
  4. בשדה שם הפיד, מזינים שם לפיד (לדוגמה, App Engine Logs).
  5. בוחרים באפשרות Google Cloud Storage V2 בתור סוג המקור.
  6. בוחרים באפשרות GCP_APP_ENGINE בתור סוג היומן.

  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. הקבצים מחולקים לשברי קבצים (shard) והשם שלהם כולל תקופות זמן (לדוגמה, 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) השם שונה מ-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 התוצאות ממוזגות מ-security_result
resource.labels.forwarding_rule_name security_result.rule_labels מוזג עם rule_label שמכיל את המפתח forwarding_rule_name ואת הערך מהשדה
severity security_result.severity הערך מוגדר כ-severity אם יש התאמה ל-(?i)ERROR|CRITICAL, ‏ INFORMATIONAL אם יש התאמה ל-(?i)INFO, ‏ MEDIUM אם יש התאמה ל-(?i)WARN, ‏ LOW אם יש התאמה ל-(?i)DEBUG, אחרת UNKNOWN_SEVERITY
jsonPayload.statusDetails security_result.summary הערך הועתק ישירות
יעד יעד השם שונה מהשם של היעד אם הוא לא ריק
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.