איסוף יומנים של PingIDM (לשעבר ForgeRock OpenIDM)
גרסת המנתח: 4.0
במסמך הזה מוסבר איך להטמיע יומני PingIDM (לשעבר ForgeRock OpenIDM) ב-Google Security Operations באמצעות Google Cloud Storage V2.
PingIDM היא פלטפורמה לניהול זהויות שמאפשרת הקצאת משתמשים, סנכרון, ניהול סיסמאות וניהול הרשאות גישה. הוא מתעד אירועים במחזור החיים של הזהות, ניסיונות אימות, פעולות התאמה ושינויים בהגדרות ביומני ביקורת שאפשר לגשת אליהם דרך REST.
לפני שמתחילים
ודאו שיש לכם את הדרישות המוקדמות הבאות:
- מופע של Google SecOps.
- פרויקט ב-GCP עם Cloud Storage API מופעל.
- הרשאות ליצירה ולניהול של קטגוריות GCS וכללי מדיניות IAM.
- הרשאות ליצירת שירותי Cloud Run, נושאי Pub/Sub ומשימות ב-Cloud Scheduler.
- גישה עם הרשאות לאדמין למכונה של ForgeRock OpenIDM או PingIDM.
יצירת קטגוריה של Google Cloud Storage
- נכנסים למסוף Google Cloud.
- בוחרים את הפרויקט או יוצרים פרויקט חדש.
- בתפריט הניווט, עוברים אל Cloud Storage > Buckets.
- לוחצים על Create bucket.
ממלאים את פרטי ההגדרה הבאים:
הגדרה ערך Name your bucket מזינים שם ייחודי גלובלי (למשל, forgerock-openidm-audit-logs)סוג המיקום בוחרים לפי הצרכים (אזור, שני אזורים, מספר אזורים) Location בוחרים את המיקום (למשל, us-central1)סוג אחסון (storage class) Standard (מומלץ ליומנים שניגשים אליהם לעיתים קרובות) בקרת גישה Uniform (מומלץ) כלי הגנה אופציונלי: הפעלת ניהול גרסאות של אובייקטים או מדיניות שמירת נתונים לוחצים על יצירה.
איסוף פרטי הכניסה של ForgeRock OpenIDM
קבלת כתובת ה-URL הבסיסית של ForgeRock OpenIDM
- נכנסים למכונה של ForgeRock OpenIDM או PingIDM.
- שימו לב לכתובת ה-URL הבסיסית מסרגל הכתובות של הדפדפן.
- פורמט:
https://openidm.example.com - אל תכללו לוכסנים בסוף או נתיבים כמו
/admin.
- פורמט:
קבלת פרטי כניסה של אדמין
- משיגים פרטי כניסה של אדמין למכונה של ForgeRock OpenIDM.
- מה צריך:
- שם משתמש: שם משתמש אדמין (למשל,
openidm-admin) - סיסמה: סיסמת אדמין
- שם משתמש: שם משתמש אדמין (למשל,
אימות ההרשאות
- נכנסים ל-ForgeRock OpenIDM.
- עוברים אל Configure (הגדרה) > System Preferences (העדפות מערכת) > Audit (ביקורת).
- אם אתם יכולים לראות את הגדרות הביקורת ואת הנושאים, יש לכם את ההרשאות הנדרשות.
- אם האפשרות הזו לא מופיעה, פנו לאדמין כדי לקבל הרשאות קריאה של ביקורת.
בדיקת הגישה ל-API
לפני שממשיכים בתהליך השילוב, בודקים את פרטי הכניסה:
# Replace with your actual credentials OPENIDM_BASE_URL="[https://openidm.example.com](https://openidm.example.com)" OPENIDM_USERNAME="openidm-admin" OPENIDM_PASSWORD="your-admin-password" # Test API access to authentication audit topic curl -v \ -H "X-OpenIDM-Username: ${OPENIDM_USERNAME}" \ -H "X-OpenIDM-Password: ${OPENIDM_PASSWORD}" \ -H "Accept-API-Version: resource=1.0" \ -H "Accept: application/json" \ "${OPENIDM_BASE_URL}/openidm/audit/authentication?_queryFilter=true&_pageSize=1"
התגובה הצפויה: HTTP 200 עם JSON שמכיל אירועי ביקורת.
יצירת חשבון שירות לפונקציית Cloud Run
לפונקציית Cloud Run נדרש חשבון שירות עם הרשאות כתיבה בקטגוריית GCS, וצריך להפעיל אותה באמצעות Pub/Sub.
יצירת חשבון שירות
- במסוף GCP, נכנסים לדף IAM & Admin > Service Accounts.
- לוחצים על Create Service Account.
- מזינים את פרטי ההגדרה הבאים:
- שם חשבון השירות:
forgerock-openidm-collector-sa - תיאור חשבון השירות:
Service account for Cloud Run function to collect ForgeRock OpenIDM logs
- שם חשבון השירות:
- לוחצים על יצירה והמשך.
- בקטע Grant this service account access to project, מוסיפים את התפקידים הבאים:
- אדמין של אובייקט אחסון: כדי לכתוב יומנים בקטגוריית GCS ולנהל קובצי תמונת מצב.
- Cloud Run Invoker: כדי לאפשר ל-Pub/Sub להפעיל את הפונקציה.
- Cloud Functions Invoker: כדי לאפשר הפעלה של פונקציות.
- לוחצים על המשך ואז על סיום.
הענקת הרשאות IAM בקטגוריית GCS
- עוברים אל Cloud Storage > Buckets.
- לוחצים על שם הקטגוריה (למשל,
forgerock-openidm-audit-logs). - עוברים לכרטיסייה Permissions.
- לוחצים על הענקת גישה.
- מזינים את פרטי ההגדרה הבאים:
- הוספת חשבונות משתמשים: מזינים את כתובת האימייל של חשבון השירות (למשל,
forgerock-openidm-collector-sa@PROJECT_ID.iam.gserviceaccount.com). - הקצאת תפקידים: בוחרים באפשרות אדמין של אובייקטים באחסון.
- הוספת חשבונות משתמשים: מזינים את כתובת האימייל של חשבון השירות (למשל,
- לוחצים על Save.
יצירת נושא Pub/Sub
- במסוף GCP, נכנסים לדף Pub/Sub > Topics.
- לוחצים על Create topic.
- מזינים את פרטי ההגדרה הבאים:
- מזהה הנושא:
forgerock-openidm-trigger - משאירים את ההגדרות האחרות כברירת מחדל.
- מזהה הנושא:
- לוחצים על יצירה.
יצירת פונקציית Cloud Run לאיסוף יומנים
- במסוף GCP, נכנסים ל-Cloud Run.
- לוחצים על Create service.
- בוחרים באפשרות Function (שימוש בעורך ישיר כדי ליצור פונקציה).
בקטע Configure, מזינים את פרטי ההגדרה הבאים:
הגדרה ערך שם השירות forgerock-openidm-collectorאזור בוחרים את האזור שתואם לקטגוריית GCS (למשל, us-central1)זמן ריצה בוחרים באפשרות Python 3.12 או גרסה עדכנית יותר. בקטע טריגר:
- לוחצים על + הוספת טריגר.
- בוחרים באפשרות Cloud Pub/Sub.
- בקטע Select a Cloud Pub/Sub topic, בוחרים את
forgerock-openidm-trigger. - לוחצים על Save.
בקטע אימות:
- לוחצים על דרישת אימות.
- בודקים את ניהול הזהויות והרשאות הגישה (IAM).
גוללים למטה ומרחיבים את הקטע Containers, Networking, Security.
עוברים לכרטיסייה אבטחה:
- חשבון שירות: בוחרים באפשרות
forgerock-openidm-collector-sa.
- חשבון שירות: בוחרים באפשרות
עוברים לכרטיסייה מאגרי תגים:
- לוחצים על Variables & Secrets.
- לוחצים על + Add variable לכל משתנה סביבה:
שם משתנה ערך לדוגמה תיאור GCS_BUCKETforgerock-openidm-audit-logsשם הקטגוריה ב-GCS GCS_PREFIXopenidmקידומת לקובצי יומן STATE_KEYopenidm/state.jsonנתיב קובץ תמונת המצב OPENIDM_BASE_URLhttps://openidm.example.comכתובת ה-URL הבסיסית של OpenIDM OPENIDM_USERNAMEopenidm-adminשם המשתמש של האדמין ב-OpenIDM OPENIDM_PASSWORDyour-admin-passwordסיסמת אדמין ב-OpenIDM AUDIT_TOPICSaccess,activity,authentication,config,syncנושאים מופרדים בפסיקים PAGE_SIZE100רשומות בכל דף MAX_PAGES50מספר הדפים המקסימלי לכל נושא בקטע בקשות:
- Request timeout:
600שניות.
- Request timeout:
עוברים לכרטיסייה הגדרות:
- משאבים: זיכרון בנפח 512 MiB, מעבד (CPU) אחד (1).
לוחצים על יצירה. אחרי שיוצרים את השירות, עורך הקוד המוטבע נפתח.
הוספת קוד פונקציה
- בשדה Entry point, מזינים main.
יוצרים שני קבצים בכלי לעריכת טקסט:
- main.py:
import functions_framework from google.cloud import storage import json import os import urllib3 from datetime import datetime, timezone # Initialize HTTP client with timeouts http = urllib3.PoolManager( timeout=urllib3.Timeout(connect=5.0, read=30.0), retries=False, ) # Initialize Storage client storage_client = storage.Client() # Environment variables GCS_BUCKET = os.environ.get('GCS_BUCKET') GCS_PREFIX = os.environ.get('GCS_PREFIX', 'openidm') STATE_KEY = os.environ.get('STATE_KEY', 'openidm/state.json') OPENIDM_BASE_URL = os.environ.get('OPENIDM_BASE_URL') OPENIDM_USERNAME = os.environ.get('OPENIDM_USERNAME') OPENIDM_PASSWORD = os.environ.get('OPENIDM_PASSWORD') AUDIT_TOPICS = os.environ.get('AUDIT_TOPICS', 'access,activity,authentication,config,sync').split(',') PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '100')) MAX_PAGES = int(os.environ.get('MAX_PAGES', '50')) @functions_framework.cloud_event def main(cloud_event): """ Cloud Run function triggered by Pub/Sub to fetch ForgeRock OpenIDM logs and write to GCS. """ if not all([GCS_BUCKET, OPENIDM_BASE_URL, OPENIDM_USERNAME, OPENIDM_PASSWORD]): print('Error: Missing required environment variables') return try: bucket = storage_client.bucket(GCS_BUCKET) state = load_state(bucket, STATE_KEY) all_events = [] for topic in AUDIT_TOPICS: topic = topic.strip() print(f"Fetching audit logs for topic: {topic}") events = fetch_audit_logs(topic, state.get(topic, {})) all_events.extend(events) if events: latest_timestamp = max(e.get('timestamp', '') for e in events) state[topic] = { 'last_timestamp': latest_timestamp, 'last_run': datetime.now(timezone.utc).isoformat(), 'events_count': len(events) } if all_events: write_to_gcs(bucket, all_events) save_state(bucket, STATE_KEY, state) print(f"Successfully processed {len(all_events)} audit events") else: print("No new audit events to process") except Exception as e: print(f'Error processing logs: {str(e)}') raise def load_state(bucket, key): try: blob = bucket.blob(key) if blob.exists(): return json.loads(blob.download_as_text()) except Exception as e: print(f"Warning: Could not load state: {e}") return {} def save_state(bucket, key, state): try: blob = bucket.blob(key) blob.upload_from_string(json.dumps(state, indent=2), content_type='application/json') except Exception as e: print(f"Warning: Could not save state: {e}") def fetch_audit_logs(topic, topic_state): base_url = OPENIDM_BASE_URL.rstrip('/') all_events = [] last_timestamp = topic_state.get('last_timestamp') query_filter = 'true' if not last_timestamp else f'timestamp gt "{last_timestamp}"' page_offset = 0 page_count = 0 while page_count < MAX_PAGES: try: url = f"{base_url}/openidm/audit/{topic}" params = { '_queryFilter': query_filter, '_pageSize': str(PAGE_SIZE), '_pagedResultsOffset': str(page_offset), '_sortKeys': 'timestamp' } headers = { 'X-OpenIDM-Username': OPENIDM_USERNAME, 'X-OpenIDM-Password': OPENIDM_PASSWORD, 'Accept-API-Version': 'resource=1.0', 'Accept': 'application/json' } response = http.request('GET', url, fields=params, headers=headers) if response.status != 200: print(f"API error for topic {topic}: {response.status}") break data = json.loads(response.data.decode('utf-8')) events = data.get('result', []) if not events: break all_events.extend(events) page_offset += PAGE_SIZE page_count += 1 if len(events) < PAGE_SIZE: break except Exception as e: print(f"Error for topic {topic}: {str(e)}") break return all_events def write_to_gcs(bucket, events): timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S') filename = f"{GCS_PREFIX}/openidm_audit_{timestamp}.json" ndjson_content = '\n'.join([json.dumps(event) for event in events]) bucket.blob(filename).upload_from_string(ndjson_content, content_type='application/x-ndjson')- requirements.txt:
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0לוחצים על Deploy. הפריסה נמשכת 2-3 דקות.
יצירת משימה ב-Cloud Scheduler
- במסוף GCP, נכנסים ל-Cloud Scheduler.
- לוחצים על Create Job.
ממלאים את פרטי ההגדרה הבאים:
הגדרה ערך שם forgerock-openidm-collector-hourlyאזור בוחרים את אותו אזור כמו של פונקציית Cloud Run. תדירות 0 * * * *(כל שעה)אזור זמן בחירת אזור זמן (מומלץ לבחור ב-UTC) סוג היעד Pub/Sub נושא forgerock-openidm-triggerגוף ההודעה {}לוחצים על יצירה.
אפשרויות לתדירות התזמון
| תדירות | ביטוי Cron | תרחיש לדוגמה |
|---|---|---|
| כל 5 דקות | */5 * * * * |
נפח גבוה, זמן אחזור נמוך |
| כל שעה | 0 * * * * |
רגיל (מומלץ) |
| יומי | 0 0 * * * |
איסוף באצ'ים |
בדיקת השילוב
- ב-Cloud Scheduler, לוחצים על Force run במשימה.
- מאמתים את ההרצה ביומני Cloud Run. מחפשים את:
Successfully processed X audit events. - מוודאים שקובץ
jsonחדש קיים בקטגוריה של Cloud Storage בתיקייהopenidm/.
אחזור של חשבון השירות של Google SecOps
הגדרת פיד ב-Google SecOps
- עוברים אל הגדרות > ניהול נתונים > פידים. אם אתם משתמשים בפלטפורמה של SIEM בלבד, עוברים אל הגדרות > פידים.
- לוחצים על הוספת פיד חדש > הגדרת פיד יחיד.
- שם הפיד:
ForgeRock OpenIDM Audit Logs. - סוג המקור: Google Cloud Storage V2.
- סוג היומן: FORGEROCK_OPENIDM.
- לוחצים על Get Service Account (קבלת חשבון שירות) ומעתיקים את כתובת האימייל שמופיעה (למשל,
chronicle-12345...). - לוחצים על הבא.
- כתובת ה-URL של קטגוריית האחסון:
gs://forgerock-openidm-audit-logs/openidm/. - אפשרות מחיקת מקור: בוחרים לפי ההעדפה (למשל, אף פעם).
- לוחצים על הבא, בודקים את הפרטים ולוחצים על שליחה.
מתן הרשאות IAM
- עוברים אל Cloud Storage > Buckets.
- בוחרים את הקטגוריה ולוחצים על הכרטיסייה Permissions.
- לוחצים על הענקת גישה.
- הוספת חשבונות משתמשים: מדביקים את כתובת האימייל של חשבון השירות של Google SecOps.
- הקצאת תפקידים: בוחרים באפשרות צפייה באובייקטים באחסון.
- לוחצים על Save.
טבלת מיפוי UDM
| שדה ביומן | מיפוי UDM | Logic (פונקציה לוגית) |
|---|---|---|
fluenttag_label, topic_label, context_roles_label |
additional.fields |
צמדי מפתח/ערך להקשר. |
Via |
intermediary.hostname |
שם המארח של שרת ה-proxy או הגורם המתווך. |
x_forwarded_ip, caller.callerIps |
intermediary.ip |
כתובת ה-IP של המתווך. |
timestamp |
metadata.event_timestamp |
חותמת הזמן של האירוע. |
transactionId |
metadata.product_deployment_id |
מזהה עסקה ייחודי. |
eventName |
metadata.product_event_type |
שם האירוע מ-ForgeRock. |
_id |
metadata.product_log_id |
מזהה יומן ייחודי. |
request_method |
network.http.method |
שיטת ה-HTTP שבה נעשה שימוש. |
response.statusCode |
network.http.response_code |
קוד סטטוס של HTTP. |
user_agent |
network.http.user_agent |
תיאור מלא של סוכן המשתמש. |
client.ip, context.ipAddress |
principal.ip |
כתובת ה-IP של המקור של המשתמש. |
userId, principalData.0 |
principal.user.userid |
המזהה של המשתמש שביצע את הפעולה. |
security_action |
security_result.action |
התקבלה החלטה בנושא אבטחה. |
level |
security_result.severity |
רמת החומרה הממופה. |
server.ip |
target.ip |
כתובת ה-IP של מערכת היעד. |
http.request.path |
target.url |
כתובת URL או נתיב של יעד. |
| לא רלוונטי | metadata.product_name |
מגדירים את ForgeRock OpenIDM. |
| לא רלוונטי | metadata.vendor_name |
מגדירים את ForgeRock. |
elapsed_time" and "X-Content-Type-Options |
additional.fields |
מופה מיומן השינויים |
trackingIds.0 |
metadata.product_log_id |
מופה מיומן השינויים |
context.userRolesProperty", "context.authenticationId", and "context.authenticationIdProperty |
principal.user.attribute.roles |
מופה מיומן השינויים |
context.component", "context.moduleId", and "context.queryId |
principal.resource.attribute.labels |
מופה מיומן השינויים |
context.roles", "_normalized.fieldNames", and "_eventId |
additional.fields |
מופה מיומן השינויים |
יומן שינויים
הצגת יומן השינויים של המנתח הזה
הבעיה עדיין לא נפתרה? קבלת תשובות מחברי הקהילה וממומחי Google SecOps.