איסוף יומנים של Keycloak

נתמך ב:

במאמר הזה מוסבר איך להגדיר את Keycloak כדי לשלוח יומנים ל-Google Security Operations באמצעות ווּבּהוּקים.

‫Keycloak הוא פתרון קוד פתוח לניהול זהויות והרשאות גישה (IAM) שמספק יכולות של כניסה יחידה (SSO), איחוד משתמשים, תיווך זהויות וכניסה באמצעות חשבונות ברשתות חברתיות. הוא תומך בפרוטוקולים OpenID Connect,‏ OAuth 2.0 ו-SAML 2.0, ועוקב אחרי אירועי משתמשים (התחברות, התנתקות, הרשמה, שינוי סיסמה) ואירועי אדמין (פעולות ניהול של משתמשים, לקוחות, תחומים ותפקידים) לצורך ביקורת אבטחה.

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

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

  • מופע של Google SecOps
  • מופע פעיל של Keycloak (מומלצת גרסה 20 ואילך)
  • גישת אדמין למסוף Admin של Keycloak
  • גישה למערכת הקבצים או למאגר של שרת Keycloak כדי לפרוס תוספים
  • גישה למסוף Google Cloud (ליצירת מפתח API)

יצירת פיד של webhook ב-Google SecOps

יצירת הפיד

  1. עוברים אל SIEM Settings > Feeds (הגדרות SIEM > פידים).
  2. לוחצים על הוספת פיד חדש.
  3. בדף הבא, לוחצים על הגדרת פיד יחיד.
  4. בשדה שם הפיד, מזינים שם לפיד (לדוגמה, Keycloak Events).
  5. בוחרים באפשרות Webhook בתור סוג המקור.
  6. בוחרים באפשרות Keycloak בתור סוג היומן.
  7. לוחצים על הבא.
  8. מציינים ערכים לפרמטרים הבאים של הקלט:
    • תו מפריד לפיצול (אופציונלי): מזינים \n כדי לפצל אירועים מרובי שורות (כל בקשת POST של webhook מכילה אירוע יחיד, כך שאפשר להשאיר את השדה הזה ריק).
    • מרחב שמות של נכס: מרחב השמות של הנכס
    • תוויות להוספה: התווית שתתווסף לאירועים מהפיד הזה
  9. לוחצים על הבא.
  10. בודקים את ההגדרות של הפיד החדש במסך סיום ולוחצים על שליחה.

יצירה ושמירה של מפתח סודי

אחרי שיוצרים את הפיד, צריך ליצור מפתח סודי לאימות:

  1. בדף הפרטים של הפיד, לוחצים על יצירת מפתח סודי.
  2. בתיבת דו-שיח מוצג המפתח הסודי.
  3. מעתיקים ושומרים את המפתח הסודי באופן מאובטח.

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

קבלת כתובת ה-URL של נקודת הקצה של הפיד

  1. עוברים לכרטיסייה פרטים של הפיד.
  2. בקטע Endpoint Information, מעתיקים את Feed endpoint URL.
  3. הפורמט של כתובת ה-URL הוא:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    או

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  4. שומרים את כתובת ה-URL הזו כדי לבצע את השלבים הבאים.

  5. לוחצים על סיום.

יצירת מפתח Google Cloud API

כדי לבצע אימות ב-Chronicle, צריך מפתח API. יוצרים מפתח API מוגבל במסוף Google Cloud.

יצירת מפתח API

  1. נכנסים אל הדף Credentials במסוף Google Cloud.
  2. בוחרים את הפרויקט (הפרויקט שמשויך למופע Chronicle).
  3. לוחצים על Create credentials > API key.
  4. מפתח API נוצר ומוצג בתיבת דו-שיח.
  5. לוחצים על Edit API key כדי להגביל את המפתח.

הגבלת מפתח ה-API

  1. בדף ההגדרות API key:
    • שם: מזינים שם תיאורי (לדוגמה, Chronicle Webhook API Key)
  2. בקטע API restrictions (הגבלות על API):
    1. בוחרים באפשרות הגבלת המקש.
    2. בתפריט הנפתח Select APIs (בחירת ממשקי API), מחפשים ובוחרים באפשרות Google SecOps API (או Chronicle API).
  3. לוחצים על Save.
  4. מעתיקים את הערך של מפתח ה-API מהשדה מפתח ה-API בחלק העליון של הדף.
  5. שומרים את מפתח ה-API בצורה מאובטחת.

הפעלת אחסון אירועים ב-Keycloak

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

הפעלת אירועים של משתמשים

  1. נכנסים למסוף Admin של Keycloak.
  2. בוחרים את מקבץ שרתי המשחק (Realm) שרוצים לעקוב אחריו מהתפריט הנפתח של מקבץ שרתי המשחק (Realm) בפינה הימנית העליונה.
  3. עוברים אל Realm Settings > Events.
  4. לוחצים על כרטיסיית המשנה הגדרות אירועים של משתמשים.
  5. מפעילים את המתג שמירת אירועים.
  6. מגדירים את תקופת התפוגה (מומלץ להגדיר 7 ימים לפחות).
  7. לוחצים על Save.

הפעלת אירועי אדמין

  1. בכרטיסייה אירועים, בוחרים בכרטיסיית המשנה הגדרות אירועים של אדמין.
  2. מפעילים את המתג שמירת אירועים.
  3. מפעילים את המתג Include representation כדי לתעד פרטים מלאים של אובייקטים שהשתנו.
  4. מגדירים את תקופת התפוגה (מומלץ להגדיר 7 ימים לפחות).
  5. לוחצים על Save.

התקנה של התוסף webhook רכיב event listener

‫Keycloak לא כולל רכיב event listener מקורי של webhook. מתקינים את התוסף keycloak-events מ-Phase Two (p2-inc) כדי להפעיל את השליחה של תגובות לפעולות מאתר אחר (webhook).

הורדה ופריסה של התוסף

  1. מורידים את קובץ ה-JAR של הגרסה האחרונה מדף הגרסאות של keycloak-events ב-Maven Central או יוצרים אותו מהמקור:

    git clone https://github.com/p2-inc/keycloak-events.git
    cd keycloak-events
    mvn clean install
    
  2. מעתיקים את קובץ ה-JAR שמתקבל לספרייה providers של Keycloak:

    cp target/keycloak-events-*.jar /opt/keycloak/providers/
    
  3. בונים מחדש את Keycloak ומפעילים אותו מחדש:

    /opt/keycloak/bin/kc.sh build
    /opt/keycloak/bin/kc.sh start
    

הפעלת רכיב ה-event listener של ה-webhook

  1. נכנסים למסוף Admin של Keycloak.
  2. בוחרים את התחום הרצוי מהתפריט הנפתח של התחומים.
  3. עוברים אל Realm Settings > Events.
  4. בתפריט הנפתח Event listeners (מאזינים לאירועים), בוחרים באפשרות ext-event-webhook.
  5. לוחצים על Save.

הגדרת webhook ב-Keycloak

הרכבת ה-webhook URL

  • משלבים את כתובת ה-URL של נקודת הקצה של Chronicle ואת מפתח ה-API:

    <ENDPOINT_URL>?key=<API_KEY>
    
  • לדוגמה:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...
    

יצירת מינוי ל-webhook באמצעות API בארכיטקטורת REST של Keycloak

התוסף keycloak-events מספק נקודות קצה של REST לניהול מינויים של webhook. משתמשים ב-Keycloak Admin API בארכיטקטורת REST כדי ליצור webhook.

שלב 1: קבלת אסימון גישה

  • שולחים בקשה לטוקן גישה מ-Keycloak באמצעות חשבון אדמין:

    TOKEN=$(curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/master/protocol/openid-connect/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      --data-urlencode "grant_type=password" \
      --data-urlencode "client_id=admin-cli" \
      --data-urlencode "username=<ADMIN_USERNAME>" \
      --data-urlencode "password=<ADMIN_PASSWORD>" \
      | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')
    

מחליפים את מה שכתוב בשדות הבאים:

  • <KEYCLOAK_HOST>: שם המארח והיציאה של שרת Keycloak (לדוגמה, keycloak.example.com:8443)
  • <ADMIN_USERNAME>: שם המשתמש של האדמין ב-Keycloak
  • <ADMIN_PASSWORD>: סיסמת האדמין של Keycloak

שלב 2: יצירת ה-webhook

  • שולחים בקשת POST כדי ליצור את המינוי ל-webhook עבור התחום היעד:

    curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{
        "enabled": "true",
        "url": "<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>",
        "secret": "<WEBHOOK_HMAC_SECRET>",
        "eventTypes": ["*"]
      }'
    

מחליפים את מה שכתוב בשדות הבאים:

  • <KEYCLOAK_HOST>: שם המארח של שרת Keycloak
  • <REALM_NAME>: השם של התחום למעקב (לדוגמה, master או my-realm)
  • <ENDPOINT_URL>: כתובת ה-URL של נקודת הקצה של הפיד של Chronicle שהועתקה קודם
  • <API_KEY>: מפתח Google Cloud API שנוצר קודם
  • <SECRET_KEY>: מפתח הסוד של ה-webhook ב-Chronicle שנוצר קודם
  • <WEBHOOK_HMAC_SECRET>: מחרוזת סודית שרירותית לחתימת מטען ייעודי (payload) של webhook באמצעות HMAC (לדוגמה, mySecretKey123)

שלב 3: מאמתים את ה-webhook

  • כדי לוודא שה-webhook נוצר, מציגים רשימה של כל ה-webhook-ים בתחום:

    curl -sS -X GET "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Accept: application/json"
    

התשובה מחזירה רשימה של אובייקטים של webhook. מוודאים שרכיב ה-Webhook מופיע עם הסמל "enabled": "true" וכתובת ה-URL הנכונה.

סוגי אירועים של Webhook

בשדה eventTypes אפשר להזין מערך של ביטויים כדי לסנן את האירועים שנשלחים:

  • * — שליחת כל האירועים (מומלץ לשילוב עם SIEM)
  • access.* – שליחת כל אירועי הגישה
  • admin.* — שליחת כל אירועי האדמין
  • admin.USER-* – שליחת כל האירועים שקשורים למשתמשים לאדמין
  • admin-USER-CREATE — שליחה רק של אירועי אדמין שקשורים ליצירת משתמשים

פורמט המטען הייעודי (payload) של webhook

  • ה-webhook שולח אירועים כבקשות HTTP POST עם מטען ייעודי (payload) מסוג JSON. מטען ייעודי (payload) של אירוע משתמש לדוגמה:

    {
      "id": "987865-1a2b-3c4d-9876-654321abc",
      "time": 1767799710612,
      "type": "LOGIN",
      "realmId": "12345abcde-1a2b-4d3c-9876-abcd456",
      "clientId": "account-console",
      "userId": "abcd456-1234-5678-abc9-987gfed654",
      "sessionId": "efghij-9876-abcd-456-11223344",
      "ipAddress": "203.0.113.45",
      "details": {
        "auth_method": "openid-connect",
        "auth_type": "code",
        "redirect_uri": "https://app.example.com/callback",
        "consent": "no_consent_required",
        "username": "jdoe"
      }
    }
    

התנהגות של ניסיון חוזר של webhook

התוסף משתמש בהשהיה מעריכית לפני ניסיון חוזר (exponential backoff) אוטומטית לניסיונות חוזרים כשמתקבלת תגובה שאינה 2xx:

פרמטר ערך ברירת המחדל תיאור
backoffInitialInterval ‫500 אלפיות השנייה מרווח הזמן הראשוני לניסיון חוזר
backoffMaxElapsedTime ‫900,000 אלפיות השנייה (15 דקות) משך הזמן המקסימלי הכולל לביצוע ניסיון חוזר
backoffMaxInterval ‫180,000 אלפיות השנייה (3 דקות) המרווח המקסימלי בין ניסיונות חוזרים
backoffMultiplier 5 מכפיל לכל מרווח זמן בין ניסיונות חוזרים
backoffRandomizationFactor ‫0.5 גורם אקראיות לשינוי קצב העברת הנתונים

הפניה לשיטות אימות

פידים של webhook ב-Chronicle תומכים בכמה שיטות אימות. בוחרים את השיטה שהספק תומך בה.

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

  • פורמט הבקשה:

    POST <ENDPOINT_URL> HTTP/1.1
    Content-Type: application/json
    x-goog-chronicle-auth: <API_KEY>
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

היתרונות:

  • מפתח ה-API והסוד לא מוצגים בכתובת ה-URL
  • מאובטח יותר (הכותרות לא מתועדות ביומני הגישה של שרת האינטרנט)
  • השיטה המועדפת אם הספק תומך בה

שיטה 2: פרמטרים של שאילתה

אם הספק לא תומך בכותרות מותאמות אישית, צריך לצרף את פרטי הכניסה לכתובת ה-URL.

  • פורמט כתובת ה-URL:

    <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>
    
  • לדוגמה:

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate?key=AIzaSyD...&secret=abcd1234...
    
  • פורמט הבקשה:

    POST <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY> HTTP/1.1
    Content-Type: application/json
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

חסרונות:

  • פרטי הכניסה גלויים בכתובת ה-URL
  • יכול להיות שיירשם ביומני הגישה של שרת האינטרנט
  • פחות מאובטח מכותרות

שיטה 3: היברידית (כתובת URL + כותרת)

חלק מההגדרות משתמשות במפתח API בכתובת ה-URL ובמפתח סודי בכותרת.

  • פורמט הבקשה:

    POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1
    Content-Type: application/json
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

שמות של כותרות אימות

מערכת Chronicle מקבלת את שמות הכותרות הבאים לאימות:

למפתח API:

  • x-goog-chronicle-auth (מומלץ)
  • X-Goog-Chronicle-Auth (case-insensitive)

למפתח סודי:

  • x-chronicle-auth (מומלץ)
  • X-Chronicle-Auth (case-insensitive)

מגבלות ושיטות מומלצות לשימוש ב-Webhook

מגבלות על בקשות

הגבלה ערך
גודל בקשה מקסימלי ‫4MB
מספר QPS מקסימלי (שאילתות לשנייה) 15,000
זמן קצוב לתפוגה של בקשה ‫30 שניות
התנהגות של ניסיון חוזר אוטומטי עם השהיה מעריכית לפני ניסיון חוזר (exponential backoff)

טבלת מיפוי UDM

שדה היומן מיפוי UDM לוגיקה
payload.client_id additional.fields השדה אוחד עם השדות שנוצרו מ-payload.client_id, ‏ payload.realm_id
payload.realm_id additional.fields
source_timestamp metadata.event_timestamp הניתוח מתבצע באמצעות מסנן תאריכים עם דפוסי ISO8601 ו-yyyy-MM-dd'T'HH:mm:ss.SSSZ
payload.ip_address metadata.event_type הערך הוא STATUS_UPDATE אם payload.ip_address לא ריק, אחרת USER_UNCATEGORIZED אם uuid לא ריק, אחרת GENERIC_EVENT
uuid metadata.event_type
payload.type metadata.product_event_type הערך הועתק ישירות
payload.session_id network.session_id הערך הועתק ישירות
payload.ip_address principal.ip הערך הועתק ישירות
source_metadata.schema principal.resource.attribute.labels התווית אוחדה עם תוויות שנוצרו מ-source_metadata.schema, ‏ source_metadata.table, ‏ source_metadata.is_deleted (הומר למחרוזת), ‏ source_metadata.change_type, ‏ source_metadata.tx_id, ‏ source_metadata.lsn
source_metadata.table principal.resource.attribute.labels
source_metadata.is_deleted principal.resource.attribute.labels
source_metadata.change_type principal.resource.attribute.labels
source_metadata.tx_id principal.resource.attribute.labels
source_metadata.lsn principal.resource.attribute.labels
uuid principal.user.userid הערך הועתק ישירות
אובייקט security_result.detection_fields מוזגו עם תוויות שנוצרו מאובייקט, read_method, payload.id
read_method security_result.detection_fields
payload.id security_result.detection_fields
redirect_uri target.url הערך הועתק ישירות
שם משתמש target.user.userid הערך הועתק ישירות
metadata.product_name metadata.product_name הגדרה כ-KEYCLOAK
metadata.vendor_name metadata.vendor_name הגדרה כ-KEYCLOAK
username" from "details_json target.user.userid מופה מיומן השינויים
redirect_uri" from "details_json target.url מופה מיומן השינויים
realm_id" and "client_id additional.fields מופה מיומן השינויים

שנה רישום

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

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