Mengumpulkan log Akamai Cloud Monitor

Didukung di:

Dokumen ini menjelaskan cara menyerap log Akamai Cloud Monitor (Load Balancer, Traffic Shaper, ADC) ke Google Security Operations menggunakan Google Cloud Storage. Akamai mengirimkan peristiwa JSON ke endpoint HTTPS Anda; penerima API Gateway + Cloud Function menulis peristiwa ke GCS (JSONL, gz). Parser mengubah log JSON menjadi UDM. Fungsi ini mengekstrak kolom dari payload JSON, melakukan konversi jenis data, mengganti nama kolom agar sesuai dengan skema UDM, dan menangani logika tertentu untuk kolom kustom dan pembuatan URL. Hal ini juga menggabungkan penanganan error dan logika bersyarat berdasarkan keberadaan kolom.

Sebelum memulai

Pastikan Anda memiliki prasyarat berikut:

  • Instance Google SecOps
  • Project GCP dengan Cloud Storage API diaktifkan
  • Izin untuk membuat dan mengelola bucket GCS
  • Izin untuk mengelola kebijakan IAM di bucket GCS
  • Izin untuk membuat Cloud Functions, topik Pub/Sub, dan API Gateway
  • Akses istimewa ke Akamai Control Center dan Property Manager

Membuat bucket Google Cloud Storage

  1. Buka Google Cloud Console.
  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, akamai-cloud-monitor)
    Location type Pilih berdasarkan kebutuhan Anda (Region, Dual-region, Multi-region)
    Lokasi Pilih lokasi (misalnya, us-central1)
    Kelas penyimpanan Standar (direkomendasikan untuk log yang sering diakses)
    Access control Seragam (direkomendasikan)
    Alat perlindungan Opsional: Aktifkan pembuatan versi objek atau kebijakan retensi
  6. Klik Buat.

Mengumpulkan detail konfigurasi Akamai Cloud Monitor

Anda akan memerlukan informasi berikut dari Akamai Control Center:

  • Nama properti di Pengelola Properti
  • Set data Cloud Monitor yang diperlukan untuk dikumpulkan
  • Token rahasia bersama opsional untuk autentikasi webhook

Buat akun layanan untuk Cloud Function

Cloud Function memerlukan akun layanan dengan izin untuk menulis ke bucket GCS.

Membuat akun layanan

  1. Di GCP Console, buka IAM & Admin > Service Accounts.
  2. Klik Create Service Account.
  3. Berikan detail konfigurasi berikut:
    • Nama akun layanan: Masukkan akamai-cloud-monitor-sa.
    • Deskripsi akun layanan: Masukkan Service account for Cloud Function to collect Akamai Cloud Monitor logs.
  4. Klik Create and Continue.
  5. Di bagian Berikan akun layanan ini akses ke project:
    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 Selesai.

Peran ini diperlukan untuk:

  • Storage Object Admin: Menulis log ke bucket GCS dan mengelola file status
  • Cloud Run Invoker: Mengizinkan Pub/Sub memanggil fungsi
  • Cloud Functions Invoker: Mengizinkan pemanggilan fungsi

Memberikan izin IAM pada bucket GCS

Beri akun layanan izin tulis di bucket GCS:

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

Membuat Cloud Function untuk menerima log Akamai

Cloud Function menerima permintaan POST HTTP dari Akamai Cloud Monitor dan menulis log ke GCS.

  1. Di GCP Console, buka Cloud Functions.
  2. Klik Create function.
  3. Berikan detail konfigurasi berikut:

    Setelan Nilai
    Lingkungan Pilih generasi ke-2
    Nama fungsi akamai-cloud-monitor-receiver
    Wilayah Pilih region yang cocok dengan bucket GCS Anda (misalnya, us-central1)
  4. Di bagian Pemicu:

    • Jenis pemicu: Pilih HTTPS.
    • Authentication: Pilih Allow unauthenticated invocations (Akamai akan mengirim permintaan yang tidak diautentikasi).
  5. Klik Simpan untuk menyimpan konfigurasi pemicu.

  6. Perluas Runtime, build, connections and security settings.

  7. Di bagian Runtime:

    • Memori yang dialokasikan: Pilih 512 MiB.
    • Waktu tunggu: Masukkan 600 detik (10 menit).
    • Runtime service account: Pilih akun layanan (akamai-cloud-monitor-sa).
  8. Di bagian Runtime environment variables, klik + Add variable untuk setiap variabel:

    Nama Variabel Nilai Contoh
    GCS_BUCKET akamai-cloud-monitor
    GCS_PREFIX akamai/cloud-monitor/json
    INGEST_TOKEN random-shared-secret (opsional)
  9. Klik Berikutnya untuk melanjutkan ke editor kode.

  10. Di dropdown Runtime, pilih Python 3.12.

Menambahkan kode fungsi

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

    • File pertama: main.py:
    import os
    import json
    import gzip
    import io
    import uuid
    import datetime as dt
    from google.cloud import storage
    import functions_framework
    
    GCS_BUCKET = os.environ.get("GCS_BUCKET")
    GCS_PREFIX = os.environ.get("GCS_PREFIX", "akamai/cloud-monitor/json").strip("/") + "/"
    INGEST_TOKEN = os.environ.get("INGEST_TOKEN")  # optional shared secret
    
    storage_client = storage.Client()
    
    def _write_jsonl_gz(objs: list) -> str:
        """Write JSON objects to GCS as gzipped JSONL."""
        timestamp = dt.datetime.utcnow()
        key = f"{timestamp:%Y/%m/%d}/akamai-cloud-monitor-{uuid.uuid4()}.json.gz"
    
        buf = io.BytesIO()
        with gzip.GzipFile(fileobj=buf, mode="w") as gz:
            for o in objs:
                gz.write((json.dumps(o, separators=(",", ":")) + "\n").encode())
        buf.seek(0)
    
        bucket = storage_client.bucket(GCS_BUCKET)
        blob = bucket.blob(f"{GCS_PREFIX}{key}")
        blob.upload_from_file(buf, content_type="application/json", content_encoding="gzip")
    
        return f"gs://{GCS_BUCKET}/{GCS_PREFIX}{key}"
    
    def _parse_records_from_request(request) -> list:
        """Parse JSON records from HTTP request body."""
        body = request.get_data(as_text=True)
    
        if not body:
            return []
    
        try:
            data = json.loads(body)
        except Exception:
            # Accept line-delimited JSON as pass-through
            try:
                return [json.loads(line) for line in body.splitlines() if line.strip()]
            except Exception:
                return []
    
        if isinstance(data, list):
            return data
        if isinstance(data, dict):
            return [data]
        return []
    
    @functions_framework.http
    def main(request):
        """
        Cloud Function HTTP handler for Akamai Cloud Monitor logs.
    
        Args:
            request: Flask request object
    
        Returns:
            Tuple of (response_body, status_code, headers)
        """
        # Optional shared-secret verification via query parameter (?token=...)
        if INGEST_TOKEN:
            token = request.args.get("token")
            if token != INGEST_TOKEN:
                return ("Forbidden", 403)
    
        records = _parse_records_from_request(request)
    
        if not records:
            return ("No content", 204)
    
        try:
            gcs_key = _write_jsonl_gz(records)
    
            response = {
                "ok": True,
                "gcs_key": gcs_key,
                "count": len(records)
            }
    
            return (json.dumps(response), 200, {"Content-Type": "application/json"})
    
        except Exception as e:
            print(f"Error writing to GCS: {str(e)}")
            return (f"Internal server error: {str(e)}", 500)
    
    • File kedua: requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    
  3. Klik Deploy untuk men-deploy fungsi.

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

  5. Setelah deployment, buka tab Pemicu dan salin URL Pemicu. Anda akan menggunakan URL ini dalam konfigurasi Akamai.

Mengonfigurasi Akamai Cloud Monitor untuk mengirimkan log

  1. Login ke Akamai Control Center.
  2. Buka Properti Anda di Pengelola Properti.
  3. Klik Tambahkan Aturan > pilih Pengelolaan Cloud.
  4. Tambahkan Cloud Monitor Instrumentation dan pilih Dataset yang diperlukan.
  5. Tambahkan Pengiriman Data Cloud Monitor.
  6. Berikan detail konfigurasi berikut:

    • Nama Host Pengiriman: Masukkan nama host dari URL pemicu Cloud Function Anda (misalnya, us-central1-your-project.cloudfunctions.net).
    • Jalur URL Pengiriman: Masukkan jalur dari URL pemicu Cloud Function Anda ditambah token kueri opsional:

      • Tanpa token: /akamai-cloud-monitor-receiver
      • Dengan token: /akamai-cloud-monitor-receiver?token=<INGEST_TOKEN>

      • Ganti <INGEST_TOKEN> dengan nilai yang Anda tetapkan di variabel lingkungan Cloud Function.

  7. Klik Simpan.

  8. Klik Aktifkan untuk mengaktifkan versi properti.

Mengambil akun layanan Google SecOps

Google SecOps menggunakan akun layanan unik untuk membaca data dari bucket GCS Anda. Anda harus memberi akun layanan ini akses ke bucket Anda.

Dapatkan email akun layanan

  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, Akamai Cloud Monitor - GCS).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Akamai Cloud Monitor sebagai Log type.
  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.

Memberikan izin IAM ke akun layanan Google SecOps

Akun layanan Google SecOps memerlukan peran Storage Object Viewer di bucket GCS Anda.

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda.
  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.

Mengonfigurasi feed di Google SecOps untuk menyerap log Akamai Cloud Monitor

  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, Akamai Cloud Monitor - GCS).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Akamai Cloud Monitor sebagai Log type.
  7. Klik Berikutnya.
  8. Tentukan nilai untuk parameter input berikut:

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

      gs://akamai-cloud-monitor/akamai/cloud-monitor/json/
      
      • Ganti:

        • akamai-cloud-monitor: Nama bucket GCS Anda.
        • akamai/cloud-monitor/json: Jalur awalan tempat log disimpan (harus cocok dengan GCS_PREFIX di Cloud Function).
    • 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. Defaultnya adalah 180 hari.

    • Namespace aset: akamai.cloud_monitor

    • Label penyerapan: Label ditambahkan ke semua peristiwa dari feed ini (misalnya, source=akamai_cloud_monitor, format=json).

  9. Klik Berikutnya.

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

Log Contoh Akamai Cloud Monitor yang Didukung

  • JSON:

    {
      "UA": "-",
      "accLang": "-",
      "bytes": "3929",
      "cacheStatus": "1",
      "cliIP": "0.0.0.0",
      "cookie": "-",
      "cp": "848064",
      "customField": "-",
      "dnsLookupTimeMSec": "-",
      "errorCode": "-",
      "maxAgeSec": "31536000",
      "objSize": "3929",
      "overheadBytes": "240",
      "proto": "HTTPS",
      "queryStr": "-",
      "range": "-",
      "referer": "-",
      "reqEndTimeMSec": "4",
      "reqHost": "www.example.com",
      "reqId": "1ce83c03",
      "reqMethod": "GET",
      "reqPath": "assets/images/placeholder-tagline.png",
      "reqPort": "443",
      "reqTimeSec": "1622470405.760",
      "rspContentLen": "3929",
      "rspContentType": "image/png",
      "statusCode": "200",
      "tlsOverheadTimeMSec": "0",
      "tlsVersion": "TLSv1.2",
      "totalBytes": "4599",
      "transferTimeMSec": "0",
      "turnAroundTimeMSec": "0",
      "uncompressedSize": "-",
      "version": "1",
      "xForwardedFor": "-"
    }
    

Tabel Pemetaan UDM

Kolom Log Pemetaan UDM Logika
accLang network.http.user_agent Dipetakan secara langsung jika bukan "-" atau string kosong.
kota principal.location.city Dipetakan secara langsung jika bukan "-" atau string kosong.
cliIP principal.ip Dipetakan secara langsung jika bukan string kosong.
country principal.location.country_or_region Dipetakan secara langsung jika bukan "-" atau string kosong.
cp additional.fields Dipetakan sebagai pasangan nilai kunci dengan kunci "cp".
customField about.ip, about.labels, src.ip Diuraikan sebagai pasangan nilai kunci. Penanganan khusus untuk "eIp" dan "pIp" untuk dipetakan ke src.ip dan about.ip. Kunci lainnya dipetakan sebagai label dalam about.
errorCode security_result.summary, security_result.severity Jika ada, menetapkan security_result.severity ke "ERROR" dan memetakan nilai ke security_result.summary.
geo.city principal.location.city Dipetakan secara langsung jika kota adalah "-" atau string kosong.
geo.country principal.location.country_or_region Dipetakan secara langsung jika negara adalah "-" atau string kosong.
geo.lat principal.location.region_latitude Dipetakan secara langsung, dikonversi menjadi float.
geo.long principal.location.region_longitude Dipetakan secara langsung, dikonversi menjadi float.
geo.region principal.location.state Dipetakan secara langsung.
id metadata.product_log_id Dipetakan secara langsung jika bukan string kosong.
message.cliIP principal.ip Dipetakan secara langsung jika cliIP adalah string kosong.
message.fwdHost principal.hostname Dipetakan secara langsung.
message.reqHost target.hostname, target.url Digunakan untuk membuat target.url dan mengekstrak target.hostname.
message.reqLen network.sent_bytes Dipetakan secara langsung, dikonversi menjadi bilangan bulat tidak bertanda jika totalBytes kosong atau "-".
message.reqMethod network.http.method Dipetakan secara langsung jika reqMethod adalah string kosong.
message.reqPath target.url Ditambahkan ke target.url.
message.reqPort target.port Dipetakan secara langsung, dikonversi menjadi bilangan bulat jika reqPort adalah string kosong.
message.respLen network.received_bytes Dipetakan secara langsung, dikonversi menjadi bilangan bulat tidak bertanda.
message.sslVer network.tls.version Dipetakan secara langsung.
message.status network.http.response_code Dipetakan secara langsung, dikonversi menjadi bilangan bulat jika statusCode kosong atau "-".
message.UA network.http.user_agent Dipetakan secara langsung jika UA adalah "-" atau string kosong.
network.asnum additional.fields Dipetakan sebagai pasangan nilai kunci dengan kunci "asnum".
network.edgeIP intermediary.ip Dipetakan secara langsung.
network.network additional.fields Dipetakan sebagai pasangan nilai kunci dengan kunci "network".
network.networkType additional.fields Dipetakan sebagai pasangan nilai kunci dengan kunci "networkType".
proto network.application_protocol Digunakan untuk menentukan network.application_protocol.
queryStr target.url Ditambahkan ke target.url jika bukan "-" atau string kosong.
perujuk network.http.referral_url, about.hostname Dipetakan secara langsung jika bukan "-". Nama host yang diekstrak dipetakan ke about.hostname.
reqHost target.hostname, target.url Digunakan untuk membuat target.url dan mengekstrak target.hostname.
reqId metadata.product_log_id, network.session_id Dipetakan secara langsung jika id adalah string kosong. Juga dipetakan ke network.session_id.
reqMethod network.http.method Dipetakan secara langsung jika bukan string kosong.
reqPath target.url Ditambahkan ke target.url jika bukan "-".
reqPort target.port Dipetakan langsung, dikonversi menjadi bilangan bulat.
reqTimeSec metadata.event_timestamp, timestamp Digunakan untuk menyetel stempel waktu peristiwa.
mulai metadata.event_timestamp, timestamp Digunakan untuk menyetel stempel waktu peristiwa jika reqTimeSec adalah string kosong.
statusCode network.http.response_code Dipetakan secara langsung, dikonversi menjadi bilangan bulat jika bukan "-" atau string kosong.
tlsVersion network.tls.version Dipetakan secara langsung.
totalBytes network.sent_bytes Dipetakan secara langsung, dikonversi menjadi bilangan bulat tidak bertanda jika tidak kosong atau "-".
jenis metadata.product_event_type Dipetakan secara langsung.
UA network.http.user_agent Dipetakan secara langsung jika bukan "-" atau string kosong.
versi metadata.product_version Dipetakan secara langsung.
xForwardedFor principal.ip Dipetakan secara langsung jika bukan "-" atau string kosong.
(Logika Parser) metadata.vendor_name Ditetapkan ke "Akamai".
(Logika Parser) metadata.product_name Setel ke "Cloud Monitor".
(Logika Parser) metadata.event_type Disetel ke "NETWORK_HTTP".
(Logika Parser) metadata.product_version Ditetapkan ke "2" jika versi adalah string kosong.
(Logika Parser) metadata.log_type Tetapkan ke "AKAMAI_CLOUD_MONITOR".
(Logika Parser) network.application_protocol Ditentukan dari proto atau message.proto. Disetel ke "HTTPS" jika salah satunya berisi "HTTPS" (tidak peka huruf besar/kecil), "HTTP" jika tidak.
(Logika Parser) security_result.severity Ditetapkan ke "INFORMATIONAL" jika errorCode adalah "-" atau string kosong.
(Logika Parser) target.url Dibuat dari protokol, reqHost (atau message.reqHost), reqPath (atau message.reqPath), dan queryStr.

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