Mengumpulkan log Menlo Security Isolation Platform (MSIP)

Didukung di:

Panduan ini menjelaskan cara menyerap log Menlo Security Isolation Platform (MSIP) ke Google SecOps menggunakan Google Cloud Storage.

Pendekatan berfokus isolasi Menlo Security memisahkan penjelajahan web dan pengambilan dokumen antara perangkat pengguna dan Disposable Virtual Container (DVC) yang terisolasi dan jauh dari endpoint. Semua kode berisiko dieksekusi di DVC terisolasi dan tidak pernah mencapai endpoint. Hanya data tampilan yang aman yang dikirim ke browser pengguna. Platform ini menyediakan logging komprehensif untuk akses web, peristiwa audit, keamanan email, pelanggaran DLP, dan aktivitas SMTP.

Sebelum memulai

Pastikan Anda memiliki prasyarat berikut:

  • Instance Google SecOps
  • Akses istimewa ke Portal Admin Menlo Security
  • Izin untuk membuat token API di Menlo Security
  • Project GCP dengan Cloud Storage, Cloud Run, Pub/Sub, dan Cloud Scheduler API yang diaktifkan

Mengonfigurasi akses API Menlo Security

Agar fungsi Cloud Run dapat mengambil log, Anda harus membuat token API dengan izin Log Export API.

Buat token API

  1. Login ke Menlo Security Admin Portal di https://admin.menlosecurity.com.
  2. Buka Settings > Authentication > API Tokens.
  3. Klik Create Token.
  4. Di kolom Token Name, masukkan nama deskriptif (misalnya, Chronicle GCS Integration).
  5. Di bagian Permissions, pilih Log Export API.
  6. Klik Buat atau Simpan.
  7. Salin dan simpan token API yang dibuat dengan aman.

Penting: Token API hanya ditampilkan satu kali. Simpan di lokasi yang aman segera setelah dibuat.

Izin API yang diperlukan

  • Token API memerlukan izin berikut:

    Izin/Cakupan Tingkat Akses Tujuan
    Log Export API Baca Mengambil log dari Menlo Security API

Buat bucket Google Cloud Storage

  1. Buka Konsol Google Cloud.
  2. Pilih project Anda atau buat project baru.
  3. Di menu navigasi, buka Cloud Storage > Buckets.
  4. Klik Create bucket.
  5. Berikan detail konfigurasi berikut:

    Setelan Nilai
    Beri nama bucket Anda Masukkan nama yang unik secara global (misalnya, menlo-security-logs)
    Location type Pilih berdasarkan kebutuhan Anda (Region, Dual-region, Multi-region)
    Location Pilih lokasi (misalnya, us-central1)
    Kelas penyimpanan Standar (direkomendasikan untuk log yang sering diakses)
    Kontrol akses Seragam (direkomendasikan)
    Alat perlindungan Opsional: Aktifkan pembuatan versi objek atau kebijakan retensi
  6. Klik Create.

Buat akun layanan untuk fungsi Cloud Run

Membuat akun layanan

  1. Di Konsol GCP, buka IAM & Admin > Service Accounts.
  2. Klik Create Service Account.
  3. Berikan detail konfigurasi berikut:
    • Nama akun layanan: Masukkan menlo-logs-collector-sa
    • Deskripsi akun layanan: Masukkan Service account for Cloud Run function to collect Menlo Security logs
  4. Klik Create and Continue.
  5. Di bagian Grant this service account access to project, tambahkan peran berikut:
    1. Klik Pilih peran.
    2. Telusuri dan pilih Storage Object Admin.
    3. Klik + Add another role.
    4. Telusuri dan pilih Cloud Run Invoker.
    5. Klik + Add another role.
    6. Telusuri dan pilih Cloud Functions Invoker.
  6. Klik Lanjutkan.
  7. Klik Done.

Memberikan izin IAM pada bucket GCS

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda (menlo-security-logs).
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Tambahkan prinsipal: Masukkan email akun layanan (menlo-logs-collector-sa@PROJECT_ID.iam.gserviceaccount.com)
    • Menetapkan peran: Pilih Storage Object Admin
  6. Klik Simpan.

Membuat topik Pub/Sub

  1. Di Konsol GCP, buka Pub/Sub > Topics.
  2. Klik Create topic.
  3. Berikan detail konfigurasi berikut:
    • ID Topik: Masukkan menlo-logs-trigger
    • Biarkan setelan lainnya sesuai default
  4. Klik Create.

Membuat fungsi Cloud Run untuk mengumpulkan log

  1. Di Konsol GCP, buka Cloud Run.
  2. Klik Create service.
  3. Pilih Function (gunakan editor inline untuk membuat fungsi).
  4. Di bagian Konfigurasi, berikan detail konfigurasi berikut:

    Setelan Nilai
    Nama layanan menlo-logs-collector
    Region Pilih region yang cocok dengan bucket GCS Anda (misalnya, us-central1)
    Runtime Pilih Python 3.12 atau yang lebih baru
  5. Di bagian Pemicu (opsional):

    1. Klik + Tambahkan pemicu.
    2. Pilih Cloud Pub/Sub.
    3. Di Select a Cloud Pub/Sub topic, pilih menlo-logs-trigger.
    4. Klik Simpan.
  6. Di bagian Authentication:

    1. Pilih Wajibkan autentikasi.
    2. Periksa Identity and Access Management (IAM).
  7. Scroll ke bawah dan luaskan Containers, Networking, Security.

  8. Buka tab Security:

    • Akun layanan: Pilih menlo-logs-collector-sa
  9. Buka tab Containers:

    1. Klik Variables & Secrets.
    2. Klik + Tambahkan variabel untuk setiap variabel lingkungan:
    Nama Variabel Nilai Contoh Deskripsi
    GCS_BUCKET menlo-security-logs Nama bucket GCS
    GCS_PREFIX menlo-logs Awalan untuk file log
    STATE_KEY menlo-logs/state.json Jalur file status
    MENLO_API_TOKEN your-menlo-api-token Token API Menlo Security
    MENLO_API_HOST logs.menlosecurity.com Host API Menlo Security
    MENLO_LOG_TYPES web,audit,email,dlp Jenis log yang dipisahkan koma
    LOOKBACK_HOURS 1 Periode lihat balik awal
  10. Di bagian Variables & Secrets, scroll ke bawah ke Requests:

    • Waktu tunggu permintaan: Masukkan 600 detik (10 menit)
  11. Buka tab Setelan:

    • Di bagian Referensi:
      • Memori: Pilih 512 MiB atau lebih tinggi
      • CPU: Pilih 1
  12. Di bagian Penskalaan revisi:

    • Minimum number of instances: Masukkan 0
    • Maximum number of instances: Masukkan 100
  13. Klik Create.

  14. Tunggu hingga layanan dibuat (1-2 menit).

  15. Setelah layanan dibuat, editor kode inline akan terbuka secara otomatis.

Menambahkan kode fungsi

  1. Masukkan main di kolom Entry point.
  2. Di editor kode inline, buat dua file:

    • main.py:
    import functions_framework
    from google.cloud import storage
    import os
    import json
    import urllib3
    import time
    import uuid
    from datetime import datetime, timezone, timedelta
    
    http = urllib3.PoolManager(
      timeout=urllib3.Timeout(connect=5.0, read=60.0),
      retries=False,
    )
    
    storage_client = storage.Client()
    
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'menlo-logs')
    STATE_KEY = os.environ.get('STATE_KEY', 'menlo-logs/state.json')
    API_TOKEN = os.environ.get('MENLO_API_TOKEN')
    API_HOST = os.environ.get('MENLO_API_HOST', 'logs.menlosecurity.com')
    LOG_TYPES = os.environ.get('MENLO_LOG_TYPES', 'web').split(',')
    LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '1'))
    
    @functions_framework.cloud_event
    def main(cloud_event):
      if not all([GCS_BUCKET, API_TOKEN, API_HOST]):
        print('Error: Missing required environment variables')
        return
    
      try:
        bucket = storage_client.bucket(GCS_BUCKET)
        state = load_state(bucket)
        now = datetime.now(timezone.utc).replace(microsecond=0)
    
        if isinstance(state, dict) and state.get('last_event_time'):
          try:
            last_val = state['last_event_time']
            if last_val.endswith('Z'):
              last_val = last_val[:-1] + '+00:00'
            last_time = datetime.fromisoformat(last_val)
            last_time = last_time - timedelta(minutes=2)
          except Exception as e:
            print(f"Warning: Could not parse last_event_time: {e}")
            last_time = now - timedelta(hours=LOOKBACK_HOURS)
        else:
          last_time = now - timedelta(hours=LOOKBACK_HOURS)
    
        print(f"Fetching logs from {last_time.isoformat()} to {now.isoformat()}")
    
        total = 0
        newest_time = None
    
        for log_type in LOG_TYPES:
          log_type = log_type.strip()
          print(f"Fetching {log_type} logs...")
          events = fetch_logs(log_type, API_TOKEN, API_HOST, last_time, now)
    
          if events:
            object_key = f"{GCS_PREFIX}/{now:%Y/%m/%d}/menlo-{log_type}-{uuid.uuid4()}.ndjson"
            blob = bucket.blob(object_key)
    
            ndjson = '\n'.join(
              [json.dumps(ev, ensure_ascii=False) for ev in events]
            ) + '\n'
            blob.upload_from_string(ndjson, content_type='application/x-ndjson')
    
            print(f"Uploaded {len(events)} {log_type} events to gs://{GCS_BUCKET}/{object_key}")
            total += len(events)
    
            for ev in events:
              ev_time = ev.get('timestamp') or ev.get('time') or ev.get('created_at')
              if ev_time and (newest_time is None or str(ev_time) > str(newest_time)):
                newest_time = str(ev_time)
          else:
            print(f"No {log_type} events found")
    
        save_state(bucket, newest_time if newest_time else now.isoformat())
        print(f"Successfully processed {total} total events")
    
      except Exception as e:
        print(f'Error processing logs: {str(e)}')
        raise
    
    def fetch_logs(log_type, token, api_host, start, end):
      url = f"https://{api_host}/api/v1/logs/{log_type}"
      headers = {
        'Authorization': f'Token {token}',
        'Accept': 'application/json',
      }
      params = {
        'start': start.strftime('%Y-%m-%dT%H:%M:%SZ'),
        'end': end.strftime('%Y-%m-%dT%H:%M:%SZ'),
      }
      query = '&'.join(f'{k}={v}' for k, v in params.items())
      full_url = f'{url}?{query}'
    
      all_events = []
      backoff = 1.0
    
      while full_url:
        response = http.request('GET', full_url, headers=headers)
    
        if response.status == 429:
          retry_after = int(response.headers.get('Retry-After', str(int(backoff))))
          print(f"Rate limited. Waiting {retry_after}s...")
          time.sleep(retry_after)
          backoff = min(backoff * 2, 60.0)
          continue
    
        if response.status != 200:
          print(f"API error {response.status}: {response.data.decode('utf-8')}")
          break
    
        backoff = 1.0
        data = json.loads(response.data.decode('utf-8'))
        events = data if isinstance(data, list) else data.get('events', data.get('data', []))
        all_events.extend(events)
    
        full_url = data.get('next') if isinstance(data, dict) else None
    
      print(f"Total {log_type} events fetched: {len(all_events)}")
      return all_events
    
    def load_state(bucket):
      try:
        blob = bucket.blob(STATE_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, last_event_time_iso):
      try:
        state = {
          'last_event_time': last_event_time_iso,
          'last_run': datetime.now(timezone.utc).isoformat()
        }
        blob = bucket.blob(STATE_KEY)
        blob.upload_from_string(
          json.dumps(state, indent=2),
          content_type='application/json'
        )
        print(f"Saved state: last_event_time={last_event_time_iso}")
      except Exception as e:
        print(f"Warning: Could not save state: {e}")
    
    • requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    urllib3>=2.0.0
    
  3. Klik Deploy untuk menyimpan dan men-deploy fungsi.

  4. Tunggu hingga deployment selesai (2-3 menit).

Buat tugas Cloud Scheduler

  1. Di Konsol GCP, buka Cloud Scheduler.
  2. Klik Create Job.
  3. Berikan detail konfigurasi berikut:

    Setelan Nilai
    Nama menlo-logs-collector-hourly
    Region Pilih region yang sama dengan fungsi Cloud Run
    Frekuensi 0 * * * * (setiap jam, tepat pada waktunya)
    Zona Waktu Pilih zona waktu (UTC direkomendasikan)
    Jenis target Pub/Sub
    Topik Pilih menlo-logs-trigger
    Isi pesan {} (objek JSON kosong)
  4. Klik Create.

Menguji integrasi

  1. Di konsol Cloud Scheduler, temukan tugas Anda (menlo-logs-collector-hourly).
  2. Klik Force run untuk memicu tugas secara manual.
  3. Tunggu beberapa detik.
  4. Buka Cloud Run > Services.
  5. Klik menlo-logs-collector.
  6. Klik tab Logs.
  7. Pastikan fungsi berhasil dieksekusi. Cari:

    Fetching logs from YYYY-MM-DDTHH:MM:SS+00:00 to YYYY-MM-DDTHH:MM:SS+00:00
    Fetching web logs...
    Total web events fetched: X
    Uploaded X web events to gs://menlo-security-logs/menlo-logs/YYYY/MM/DD/menlo-web-UUID.ndjson
    Successfully processed X total events
    
  8. Buka Cloud Storage > Buckets.

  9. Klik menlo-security-logs.

  10. Buka folder menlo-logs/.

  11. Pastikan file .ndjson baru dibuat dengan tanggal saat ini.

Jika Anda melihat error dalam log:

  • HTTP 401: Pastikan variabel lingkungan MENLO_API_TOKEN sudah benar
  • HTTP 403: Pastikan token API memiliki izin Log Export API
  • HTTP 429: Pembatasan kecepatan — fungsi akan otomatis mencoba lagi dengan penundaan
  • Variabel lingkungan tidak ada: Pastikan semua variabel yang diperlukan ditetapkan dalam konfigurasi fungsi Cloud Run

Mengambil akun layanan Google SecOps

  1. Buka Setelan SIEM > Feed.
  2. Klik Tambahkan Feed Baru.
  3. Klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, Menlo Security MSIP Logs).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Menlo Security sebagai Jenis log.
  7. Klik Get Service Account. Email akun layanan yang unik akan ditampilkan, misalnya:

    chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com
    
  8. Salin alamat email ini untuk digunakan di langkah berikutnya.

  9. Klik Berikutnya.

  10. Tentukan nilai untuk parameter input berikut:

    • URL bucket penyimpanan: Masukkan URI bucket GCS dengan jalur awalan:

      gs://menlo-security-logs/menlo-logs/
      
    • Opsi penghapusan sumber: Pilih opsi penghapusan sesuai preferensi Anda:

      • Jangan pernah: Tidak pernah menghapus file apa pun setelah transfer (direkomendasikan untuk pengujian).
      • Hapus file yang ditransfer: Menghapus file setelah transfer berhasil.
      • Hapus file yang ditransfer dan direktori kosong: Menghapus file dan direktori kosong setelah transfer berhasil.

      • Usia File Maksimum: Menyertakan file yang diubah dalam beberapa hari terakhir (default adalah 180 hari)

      • Namespace aset: Namespace aset

      • Label penyerapan: Label yang akan diterapkan ke peristiwa dari feed ini

  11. Klik Berikutnya.

  12. Tinjau konfigurasi feed baru Anda di layar Selesaikan, lalu klik Kirim.

Memberikan izin IAM ke akun layanan Google SecOps

  1. Buka Cloud Storage > Buckets.
  2. Klik menlo-security-logs.
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Add principals: Tempel email akun layanan Google SecOps
    • Tetapkan peran: Pilih Storage Object Viewer
  6. Klik Simpan.

Tabel pemetaan UDM

Kolom Log Pemetaan UDM Logika
customer_name intermediary.hostname Tetapkan jika customer_name bukan IP
customer_name intermediary.ip Diekstrak dari customer_name jika IP, atau dari IP xff_ip
xff_ip intermediary.ip
event_data.event_time metadata.event_timestamp Diuraikan menggunakan grok dan filter tanggal
request_type metadata.event_type Logika bersyarat berdasarkan kolom ini
has_principal metadata.event_type
has_top_url metadata.event_type
has_dest metadata.event_type
log_type metadata.log_type Nilai disalin secara langsung
event_data.name metadata.product_event_type Nilai disalin secara langsung
reqId metadata.product_log_id Nilai disalin secara langsung
event_data.version metadata.product_version Nilai disalin secara langsung
event_data.protocol network.application_protocol Dipetakan menggunakan daftar protokol standar
request_type network.http.method Nilai disalin secara langsung
perujuk network.http.referral_url Nilai disalin secara langsung
response_code network.http.response_code Dikonversi ke bilangan bulat
event_data.user-agent network.http.user_agent Nilai disalin secara langsung
full_session_id network.session_id Nilai disalin secara langsung
browser_and_version principal.application Nilai disalin secara langsung
event_data.x-client-ip principal.asset.ip Nilai dari event_data.x-client-ip jika tidak kosong, atau src_ip
src_ip principal.asset.ip
grup principal.group.product_object_id Nilai disalin secara langsung
event_data.x-client-ip principal.ip Nilai dari event_data.x-client-ip jika tidak kosong, atau src_ip
src_ip principal.ip
region principal.location.country_or_region Nilai dari wilayah jika tidak kosong, atau egress_country
egress_country principal.location.country_or_region
region_name principal.location.name Nilai disalin secara langsung
egress_ip principal.nat_ip Nilai disalin secara langsung
event_data.userid principal.user.email_addresses Digabungkan jika cocok dengan regex email
event_data.userid principal.user.userid Nilai disalin secara langsung
event_data.domain security_result.about.administrative_domain Nilai disalin secara langsung
event_data.url security_result.about.url Nilai disalin secara langsung
event_data.pe_action security_result.action Dipetakan ke ALLOW, BLOCK, atau ALLOW_WITH_MODIFICATION
event_data.categories security_result.category_details Digabungkan dari event_data.categories (diekstrak atau langsung) dan casb_cat_name
casb_cat_name security_result.category_details
event_data.risk_score security_result.confidence_details Nilai disalin secara langsung
content-type security_result.detection_fields Digabungkan dari berbagai kolom label
produk security_result.detection_fields
pengamanan cyber security_result.detection_fields
virusDetails security_result.detection_fields
sandboxResult security_result.detection_fields
fullScanResult security_result.detection_fields
tab_id security_result.detection_fields
pe_reason security_result.detection_fields
ua_type security_result.detection_fields
email_isolation_state security_result.detection_fields
document_url security_result.detection_fields
archive_path security_result.detection_fields
casb_app_name security_result.detection_fields
casb_fun_name security_result.detection_fields
casb_org_name security_result.detection_fields
casb_profile_id security_result.detection_fields
casb_profile_name security_result.detection_fields
casb_profile_type security_result.detection_fields
casb_risk_score security_result.detection_fields
connId security_result.detection_fields
origin_country security_result.detection_fields
egress_country security_result.detection_fields
is_casb_ddl security_result.detection_fields
is_iframe security_result.detection_fields
parent_file_id security_result.detection_fields
parent_filename security_result.detection_fields
parent_sha256 security_result.detection_fields
parent_tid security_result.detection_fields
root_file_id security_result.detection_fields
root_filename security_result.detection_fields
root_sha256 security_result.detection_fields
casb_risk_score security_result.risk_score Dikonversi menjadi float
casb_profile_id security_result.rule_id Nilai disalin secara langsung
pe_rulename security_result.rule_name Nilai disalin secara langsung
casb_profile_name security_result.rule_set Nilai disalin secara langsung
casb_profile_type security_result.rule_type Nilai disalin secara langsung
event_data.severity security_result.severity_details Nilai disalin secara langsung
magicName security_result.summary Digabungkan sebagai "%{magicName} adalah %{threats}."
pengamanan cyber security_result.summary
threat_types security_result.threat_name Nilai disalin secara langsung
origin_ip src.ip Nilai disalin secara langsung
origin_country src.location.country_or_region Nilai disalin secara langsung
event_data.dst target.asset.ip Diekstrak dari event_data.dst atau dst menggunakan pola IP grok
dst target.asset.ip
filename target.file.full_path Nilai disalin secara langsung
mimeType target.file.mime_type Nilai disalin secara langsung
sha256 target.file.sha256 Nilai disalin secara langsung
file_size target.file.size Dikonversi ke float lalu uinteger
event_data.dst target.ip Diekstrak dari event_data.dst atau dst menggunakan pola IP grok
dst target.ip
top_url target.url Diekstrak menggunakan pola grok URI
metadata.product_name metadata.product_name Ditetapkan ke "MENLO SECURITY"
metadata.vendor_name metadata.vendor_name Ditetapkan ke "MENLO SECURITY"
region event.idm.read_only_udm.principal.location.country_or_region Dipetakan dari log perubahan
region_name event.idm.read_only_udm.principal.location.name Dipetakan dari log perubahan
src_ip event.idm.read_only_udm.principal.ip dan event.idm.read_only_udm.principal.asset.ip Dipetakan dari log perubahan
groups event.idm.read_only_udm.principal.group.product_object_id Dipetakan dari log perubahan
content-type event.idm.read_only_udm.security_result.detection_fields Dipetakan dari log perubahan
product event.idm.read_only_udm.security_result.detection_fields Dipetakan dari log perubahan
mimeType event.idm.read_only_udm.target.file.mime_type Dipetakan dari log perubahan

Log Perubahan

Melihat Log Perubahan untuk parser ini

Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.