Mengumpulkan log Audit Oracle Cloud Infrastructure

Didukung di:

Dokumen ini menjelaskan cara menyerap log Audit Oracle Cloud Infrastructure (OCI) ke Google Security Operations menggunakan salah satu metode berikut:

  • Metode 1: Cloud Storage: Fungsi OCI menulis log ke bucket Cloud Storage, dan feed Google SecOps membacanya dari bucket.
  • Metode 2: Webhook: Fungsi OCI mengirimkan log langsung ke feed webhook Google SecOps. Metode ini tidak menggunakan bucket Cloud Storage.

Kedua metode ini menggunakan OCI Connector Hub untuk mengirimkan log Audit ke fungsi, karena OCI tidak dapat mengirim log secara langsung ke Cloud Storage atau ke endpoint HTTPS.

Layanan Oracle Cloud Infrastructure Audit secara otomatis mencatat panggilan ke semua endpoint API publik OCI yang didukung sebagai peristiwa log. Semua layanan mendukung logging oleh OCI Audit. Peristiwa log yang dicatat oleh OCI Audit mencakup panggilan API yang dilakukan oleh konsol OCI, CLI, SDK, klien kustom Anda sendiri, atau layanan OCI lainnya.

Sebelum memulai

Pastikan Anda memiliki prasyarat berikut:

  • Instance Google SecOps
  • Akses istimewa ke Konsol Cloud Oracle, dengan izin untuk membuat dan mengelola:
    • Konektor Connector Hub
    • Aplikasi dan fungsi Functions
    • Kebijakan IAM
  • Subnet VCN dengan akses internet untuk Fungsi OCI
  • OCI Cloud Shell atau lingkungan lokal dengan Fn CLI
  • Untuk Metode 1: project Google Cloud dengan Cloud Storage API yang diaktifkan, dan izin untuk membuat bucket Cloud Storage, akun layanan, dan kebijakan Identity and Access Management (IAM) bucket
  • Untuk Metode 2: izin untuk membuat kunci API di project Google Cloud yang ditautkan ke instance Google SecOps Anda

Metode 1: Cloud Storage

Membuat bucket 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
    Memberi nama bucket Anda Masukkan nama yang unik secara global (misalnya, oci-audit-logs-gcs)
    Location type Pilih sesuai kebutuhan Anda (Region, Dual-region, Multi-region)
    Location Pilih lokasi (misalnya, us-central1)
    Storage class Standard (direkomendasikan untuk log yang sering diakses)
    Kontrol akses Seragam (direkomendasikan)
    Alat perlindungan Opsional: Mengaktifkan pembuatan versi objek atau kebijakan retensi
  6. Klik Create.

Mengonfigurasi OCI untuk mengekspor log Audit ke Cloud Storage

Oracle Cloud Infrastructure tidak mendukung ekspor bawaan ke Cloud Storage. Anda menggunakan OCI Service Connector Hub dengan Function untuk meneruskan log Audit ke Cloud Storage.

Membuat fungsi OCI untuk meneruskan log ke Cloud Storage

  1. Login ke Oracle Cloud Console.
  2. Buka Developer Services > Functions > Applications.
  3. Pilih kompartemen tempat Anda ingin membuat aplikasi fungsi.
  4. Klik Create Application.
  5. Berikan detail konfigurasi berikut:
    • Nama: Masukkan audit-logs-to-gcs-app.
    • VCN: Pilih Jaringan Cloud Virtual.
    • Subnets: Pilih subnet dengan akses internet.
  6. Klik Create.
  7. Setelah aplikasi dibuat, klik Getting Started dan ikuti petunjuk untuk menyiapkan lingkungan pengembangan lokal Anda dengan Fn CLI.
  8. Buat direktori fungsi baru di komputer lokal Anda:

    mkdir oci-audit-to-gcs
    cd oci-audit-to-gcs
    
  9. Lakukan inisialisasi fungsi Python:

    fn init --runtime python oci-audit-to-gcs
    cd oci-audit-to-gcs
    
  10. Ganti konten func.py dengan kode berikut:

    import io
    import json
    import logging
    import os
    from fdk import response
    from google.cloud import storage
    from google.oauth2 import service_account
    from datetime import datetime
    
    # Configure logging
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    
    # Environment variables
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'oci-audit-logs')
    GCS_CREDENTIALS_JSON = os.environ.get('GCS_CREDENTIALS_JSON')
    
    def handler(ctx, data: io.BytesIO = None):
        """
        Oracle Cloud Infrastructure Function to forward Audit logs to GCS.
    
        Args:
            ctx: Function context
            data: Input data containing Audit log events
        """
    
        if not all([GCS_BUCKET, GCS_CREDENTIALS_JSON]):
            logger.error('Missing required environment variables: GCS_BUCKET or GCS_CREDENTIALS_JSON')
            return response.Response(
                ctx, response_data=json.dumps({"error": "Missing configuration"}),
                headers={"Content-Type": "application/json"}
            )
    
        try:
            # Parse input data
            body = json.loads(data.getvalue())
            logger.info(f"Received event: {json.dumps(body)}")
    
            # Extract log entries
            log_entries = []
            if isinstance(body, list):
                log_entries = body
            elif isinstance(body, dict):
                # Service Connector Hub sends data in specific format
                if 'data' in body:
                    log_entries = [body['data']] if isinstance(body['data'], dict) else body['data']
                else:
                    log_entries = [body]
    
            if not log_entries:
                logger.info("No log entries to process")
                return response.Response(
                    ctx, response_data=json.dumps({"status": "no_logs"}),
                    headers={"Content-Type": "application/json"}
                )
    
            # Initialize GCS client with service account credentials
            credentials_dict = json.loads(GCS_CREDENTIALS_JSON)
            credentials = service_account.Credentials.from_service_account_info(credentials_dict)
            storage_client = storage.Client(credentials=credentials, project=credentials_dict.get('project_id'))
            bucket = storage_client.bucket(GCS_BUCKET)
    
            # Write logs to GCS as NDJSON
            timestamp = datetime.utcnow().strftime('%Y%m%d_%H%M%S_%f')
            object_key = f"{GCS_PREFIX}/logs_{timestamp}.ndjson"
            blob = bucket.blob(object_key)
    
            ndjson = '\n'.join([json.dumps(entry, ensure_ascii=False) for entry in log_entries]) + '\n'
            blob.upload_from_string(ndjson, content_type='application/x-ndjson')
    
            logger.info(f"Wrote {len(log_entries)} records to gs://{GCS_BUCKET}/{object_key}")
    
            return response.Response(
                ctx, response_data=json.dumps({"status": "success", "records": len(log_entries)}),
                headers={"Content-Type": "application/json"}
            )
    
        except Exception as e:
            logger.error(f'Error processing logs: {str(e)}')
            return response.Response(
                ctx, response_data=json.dumps({"error": str(e)}),
                headers={"Content-Type": "application/json"},
                status_code=500
            )
    

  11. Update requirements.txt dengan dependensi berikut:

    fdk>=0.1.0
    google-cloud-storage>=2.0.0
    google-auth>=2.0.0
    
  12. Deploy fungsi ke OCI:

    fn -v deploy --app audit-logs-to-gcs-app
    
  13. Setelah deployment selesai, catat OCID fungsi. Anda akan menggunakannya pada langkah berikutnya.

Mengonfigurasi variabel lingkungan fungsi

  1. Di Oracle Cloud Console, buka Developer Services > Functions > Applications.
  2. Klik aplikasi (audit-logs-to-gcs-app).
  3. Klik nama fungsi (oci-audit-to-gcs).
  4. Klik Konfigurasi.
  5. Tambahkan variabel konfigurasi berikut:

    Kunci Nilai
    GCS_BUCKET Nama bucket Cloud Storage Anda (misalnya, oci-audit-logs-gcs)
    GCS_PREFIX Awalan untuk file log (misalnya, oci-audit-logs)
    GCS_CREDENTIALS_JSON String JSON dari Google Cloud kunci akun layanan (lihat di bawah)
  6. Klik Simpan perubahan.

Membuat akun layanan Google Cloud untuk fungsi OCI

Fungsi OCI memerlukan akun layanan Google Cloud untuk menulis ke bucket Cloud Storage.

  1. Di Google Cloud konsol, buka IAM & Admin > Service Accounts.
  2. Klik Create Service Account.
  3. Berikan detail konfigurasi berikut:
    • Service account name: Masukkan oci-function-gcs-writer.
    • Service account description: Masukkan Service account for OCI Function to write Audit logs to GCS.
  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.
  6. Klik Lanjutkan.
  7. Klik Done.
  8. Klik email akun layanan yang baru dibuat.
  9. Buka tab Keys.
  10. Klik Add Key > Create new key.
  11. Pilih JSON sebagai jenis kunci.
  12. Klik Create.
  13. File kunci JSON akan didownload ke komputer Anda.
  14. Buka file kunci JSON dan salin seluruh kontennya.
  15. Kembali ke konfigurasi fungsi Konsol Cloud Oracle.
  16. Tempel konten JSON ke dalam variabel konfigurasi GCS_CREDENTIALS_JSON.

Memberikan izin IAM pada bucket Cloud Storage

Beri akun layanan izin tulis di bucket Cloud Storage:

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda (oci-audit-logs-gcs).
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Add principals: Masukkan email akun layanan (oci-function-gcs-writer@PROJECT_ID.iam.gserviceaccount.com).
    • Assign roles: Pilih Storage Object Admin.
  6. Klik Simpan.

Membuat OCI Service Connector Hub

  1. Login ke Oracle Cloud Console.
  2. Buka Observability & Management > Logging > Service Connector Hub.
  3. Pilih kompartemen tempat Anda ingin membuat konektor layanan.
  4. Klik Create Service Connector.
  5. Berikan detail konfigurasi berikut:

    • Informasi Service Connector:

      Setelan Nilai
      Nama Konektor Masukkan audit-logs-to-gcs-connector
      Deskripsi Masukkan Forward OCI Audit logs to Cloud Storage
      Kompartemen Resource Pilih kompartemen
    • Konfigurasi Sumber:

      Setelan Nilai
      Source Pilih Logging
      Kompartemen Pilih kompartemen yang berisi log audit
      Grup Log Pilih _Audit (grup log default untuk log audit)
  6. Klik + Another Log.

  7. Pilih log audit untuk kompartemen Anda (misalnya, _Audit_Include_Subcompartment).

    • Mengonfigurasi Target:

      Setelan Nilai
      Target Pilih Functions
      Kompartemen Fungsi Pilih kompartemen yang berisi fungsi
      Penerapan Fungsi Pilih audit-logs-to-gcs-app
      Fungsi Pilih oci-audit-to-gcs
  8. Buka Configure task (optional) dan biarkan setelan default.

  9. Klik Create.

Membuat kebijakan IAM untuk Service Connector Hub

Service Connector Hub memerlukan izin untuk memanggil fungsi, yang Anda buat sebagai berikut:

  1. Di Oracle Cloud Console, buka Identity & Security > Policies.
  2. Pilih kompartemen tempat Anda membuat Service Connector Hub.
  3. Klik Create Policy.
  4. Berikan detail konfigurasi berikut:
    • Nama: Masukkan service-connector-functions-policy.
    • Deskripsi: Masukkan Allow Service Connector Hub to invoke Functions.
    • Compartment: Pilih kompartemen.
  5. Di bagian Policy Builder, aktifkan Show manual editor.
  6. Masukkan pernyataan kebijakan berikut:

    Allow any-user to use fn-function in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    Allow any-user to use fn-invocation in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    
    • Ganti <compartment-name> dengan nama kompartemen Anda.
  7. Klik Create.

Menguji integrasi

  1. Login ke Oracle Cloud Console.
  2. Lakukan beberapa tindakan yang menghasilkan log audit (misalnya, membuat atau mengubah resource).
  3. Tunggu 2-5 menit hingga log diproses.
  4. Di konsolGoogle Cloud , buka Cloud Storage > Buckets.
  5. Klik nama bucket Anda (oci-audit-logs-gcs).
  6. Buka folder awalan (oci-audit-logs/).
  7. Pastikan file .ndjson baru muncul di bucket.

Mengambil akun layanan Google SecOps

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

Mendapatkan email akun layanan

  1. Buka SIEM Settings > Feeds.
  2. Klik Tambahkan Feed Berita Baru.
  3. Klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, Oracle Cloud Audit Logs).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Oracle Cloud Infrastructure Log Audit 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 dua peran di bucket Cloud Storage Anda: Storage Object Viewer untuk membaca objek log, dan peran level bucket untuk membaca metadata bucket.

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket Anda (oci-audit-logs-gcs).
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Berikan detail konfigurasi berikut:
    • Add principals: Tempel email akun layanan Google SecOps.
    • Assign roles: Pilih kedua peran berikut:
    • Storage Object Viewer: membaca objek log.
    • Storage Legacy Bucket Reader: membaca metadata bucket. Jika Anda memilih opsi penghapusan Delete transferred files and empty directories, pilih Storage Legacy Bucket Writer, yang juga memberikan izin penghapusan.
  6. Klik Simpan.

Mengonfigurasi feed di Google SecOps untuk menyerap log Audit OCI

  1. Buka SIEM Settings > Feeds.
  2. Klik Tambahkan Feed Berita Baru.
  3. Klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, Oracle Cloud Audit Logs).
  5. Pilih Google Cloud Storage V2 sebagai Source type.
  6. Pilih Oracle Cloud Infrastructure Log Audit sebagai Log type.
  7. Klik Berikutnya.
  8. Tentukan nilai untuk parameter input berikut:

    • Storage bucket URL: Masukkan URI bucket Cloud Storage dengan jalur awalan:
    gs://oci-audit-logs-gcs/oci-audit-logs/
    
    • Ganti:

      • oci-audit-logs-gcs: Nama bucket Cloud Storage Anda.
      • oci-audit-logs: Awalan atau jalur opsional tempat log disimpan (biarkan kosong untuk root).

      Contoh:

      • Bucket root: gs://company-logs/
      • Dengan awalan: gs://company-logs/oci-audit-logs/
      • Dengan subfolder: gs://company-logs/oracle/audit/

    • Opsi penghapusan sumber: Pilih opsi penghapusan sesuai preferensi Anda:

      • Jangan pernah menghapus file: Jangan pernah menghapus file dari sumber (direkomendasikan untuk pengujian).
      • Hapus file yang ditransfer dan direktori kosong: Hapus file dan direktori kosong dari sumber setelah pengambilan berhasil diselesaikan.
    • Usia File Maksimum: Sertakan file yang diubah dalam jumlah hari terakhir. Defaultnya adalah 180 hari.

    • Namespace aset: Namespace aset.

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

  9. Klik Berikutnya.

  10. Tinjau konfigurasi feed berita baru Anda di layar Finalize, lalu klik Submit.

Metode 2: Webhook

Dengan metode ini, Connector Hub mengirimkan batch entri log Audit ke Fungsi OCI, dan fungsi tersebut mengirimkannya ke feed webhook Google SecOps melalui HTTPS. Tidak ada bucket Cloud Storage yang terlibat.

Membuat feed webhook di Google SecOps

Membuat feed

  1. Buka SIEM Settings > Feeds.
  2. Klik Tambahkan Feed Berita Baru.
  3. Di halaman berikutnya, klik Konfigurasi satu feed.
  4. Di kolom Nama feed, masukkan nama untuk feed (misalnya, OCI Audit Logs Webhook).
  5. Pilih Webhook sebagai Source type.
  6. Pilih Oracle Cloud Infrastructure Log Audit sebagai Log type.
  7. Klik Berikutnya.
  8. Tentukan nilai untuk parameter input berikut:
    • Pemisah pemisahan: Masukkan \n. Fungsi ini mengirimkan setiap entri log pada barisnya sendiri.
    • Namespace aset: Namespace aset.
    • Label penyerapan: Label yang akan diterapkan ke peristiwa dari feed ini.
  9. Klik Berikutnya.
  10. Tinjau konfigurasi feed berita baru Anda di layar Finalize, lalu klik Submit.

Membuat dan menyimpan kunci rahasia

  1. Di halaman detail feed, klik Buat Kunci Rahasia.
  2. Salin dan simpan kunci rahasia dengan aman.

Mendapatkan URL endpoint feed

  1. Buka tab Detail untuk feed tersebut.
  2. Di bagian Endpoint Information, salin Feed endpoint URL. URL memiliki format berikut:

    https://<REGION>-chronicle.googleapis.com/v1alpha/projects/<PROJECT_NUMBER>/locations/<REGION>/instances/<INSTANCE_ID>/feeds/<FEED_ID>:importPushLogs
    
  3. Klik Done.

Membuat kunci Google Cloud API

  1. Buka halaman Credentials konsolGoogle Cloud .
  2. Pilih project yang ditautkan ke instance Google SecOps Anda.
  3. Klik Create credentials > kunci API.
  4. Klik Edit kunci API untuk membatasi kunci.
  5. Di kolom Name, masukkan nama deskriptif (misalnya, oci-audit-webhook).
  6. Di bagian API restrictions, pilih Restrict key, lalu pilih Chronicle API di daftar Select APIs.
  7. Klik Simpan.
  8. Salin nilai kunci API dan simpan dengan aman.

Membuat Fungsi OCI untuk meneruskan log ke webhook

Membuat aplikasi

  1. Login ke Oracle Cloud Console.
  2. Buka menu navigasi, lalu pilih Developer Services > Functions > Applications.
  3. Pilih kompartemen tempat Anda ingin membuat aplikasi fungsi.
  4. Klik Create Application.
  5. Berikan detail konfigurasi berikut:
    • Nama: Masukkan audit-logs-to-secops-app.
    • VCN: Pilih Jaringan Cloud Virtual.
    • Subnets: Pilih subnet dengan akses internet: subnet publik dengan gateway internet, atau subnet pribadi dengan gateway NAT. Fungsi harus menjangkau endpoint Google SecOps melalui HTTPS (port 443).
  6. Klik Create.

Membuat dan men-deploy fungsi

  1. Setelah aplikasi dibuat, klik Getting Started dan ikuti petunjuk untuk menyiapkan OCI Cloud Shell atau lingkungan pengembangan lokal Anda dengan Fn CLI.
  2. Lakukan inisialisasi fungsi Python:

    fn init --runtime python oci-audit-to-secops
    cd oci-audit-to-secops
    
  3. Ganti konten func.py dengan kode berikut:

    import io
    import json
    import logging
    import os
    import random
    import time
    from email.utils import parsedate_to_datetime
    
    import requests
    from fdk import response
    
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger()
    
    # The webhook accepts at most 4 MB per request and 1 MB per log line.
    # Connector Hub delivers batches of up to 6 MB, so a batch is sent as several
    # requests, each made of whole log entries.
    MAX_REQUEST_BYTES = 3 * 1024 * 1024
    MAX_LINE_BYTES = 1024 * 1024
    
    MAX_ATTEMPTS = 5
    RETRYABLE_STATUS = {429, 500, 502, 503, 504}
    # OCI stops the function at its configured timeout (300 seconds). Stop retrying
    # early enough to fail cleanly so that Connector Hub retries the whole batch.
    DEADLINE_SECONDS = 240
    
    def to_lines(body):
        """Serialize each log entry from the Connector Hub batch as one JSON line."""
        entries = body if isinstance(body, list) else [body]
        lines = []
        for entry in entries:
            line = json.dumps(entry, ensure_ascii=False, separators=(',', ':')).encode('utf-8')
            if len(line) > MAX_LINE_BYTES:
                entry_id = entry.get('id') if isinstance(entry, dict) else None
                logger.error(f'Skipping log entry {entry_id}: {len(line)} bytes exceeds the 1 MB line limit')
                continue
            lines.append(line)
        return lines
    
    def to_requests(lines):
        """Group whole lines into newline-delimited request bodies below MAX_REQUEST_BYTES."""
        chunk, size = [], 0
        for line in lines:
            if chunk and size + len(line) + 1 > MAX_REQUEST_BYTES:
                yield b'\n'.join(chunk), len(chunk)
                chunk, size = [], 0
            chunk.append(line)
            size += len(line) + 1
        if chunk:
            yield b'\n'.join(chunk), len(chunk)
    
    def retry_after_seconds(value):
        """Parse a Retry-After header given either in seconds or as an HTTP date."""
        if not value:
            return None
        try:
            return max(0.0, float(value))
        except ValueError:
            pass
        try:
            return max(0.0, parsedate_to_datetime(value).timestamp() - time.time())
        except (TypeError, ValueError, IndexError, OverflowError):
            return None
    
    def post(session, url, headers, payload, deadline):
        """Send one request, retrying throttling and server errors until the deadline."""
        status, detail = None, ''
        for attempt in range(1, MAX_ATTEMPTS + 1):
            remaining = deadline - time.monotonic()
            if remaining < 5:
                break
            wait = None
            try:
                resp = session.post(url, data=payload, headers=headers, timeout=(10, min(60, remaining)))
            except requests.RequestException as e:
                status, detail = None, str(e)
            else:
                if 200 <= resp.status_code < 300:
                    return
                status, detail = resp.status_code, resp.text[:500]
                if status not in RETRYABLE_STATUS:
                    raise RuntimeError(f'Webhook rejected the request with HTTP {status}: {detail}')
                wait = retry_after_seconds(resp.headers.get('Retry-After'))
            if wait is None:
                wait = min(30, 2 ** attempt) + random.uniform(0, 1)
            if attempt == MAX_ATTEMPTS or time.monotonic() + wait >= deadline:
                break
            logger.warning(f'Attempt {attempt} failed (HTTP {status}): {detail}. Retrying in {wait:.1f} seconds')
            time.sleep(wait)
        raise RuntimeError(f'Webhook request failed (HTTP {status}): {detail}')
    
    def handler(ctx, data: io.BytesIO = None):
        """Forward a Connector Hub batch of OCI Audit log entries to the webhook feed.
    
        Any exception fails the invocation, and Connector Hub then retries the batch.
        """
        deadline = time.monotonic() + DEADLINE_SECONDS
    
        url = os.environ.get('SECOPS_WEBHOOK_URL')
        api_key = os.environ.get('SECOPS_API_KEY')
        secret_key = os.environ.get('SECOPS_SECRET_KEY')
        if not all([url, api_key, secret_key]):
            raise RuntimeError('Missing configuration: SECOPS_WEBHOOK_URL, SECOPS_API_KEY and SECOPS_SECRET_KEY are required')
    
        raw = data.getvalue() if data else b''
        if not raw.strip():
            logger.info('Received an empty batch')
            return response.Response(
                ctx, response_data=json.dumps({'records': 0}),
                headers={'Content-Type': 'application/json'}
            )
    
        lines = to_lines(json.loads(raw))
        headers = {
            'Content-Type': 'application/json',
            'X-goog-api-key': api_key,
            'X-Webhook-Access-Key': secret_key,
        }
    
        sent = 0
        with requests.Session() as session:
            for payload, count in to_requests(lines):
                post(session, url, headers, payload, deadline)
                sent += count
    
        logger.info(f'Forwarded {sent} log entries')
        return response.Response(
            ctx, response_data=json.dumps({'records': sent}),
            headers={'Content-Type': 'application/json'}
        )
    

  4. Ganti konten requirements.txt dengan dependensi berikut:

    fdk>=0.1.0
    requests>=2.32.0
    
  5. Buka func.yaml dan tambahkan baris berikut untuk meningkatkan waktu tunggu fungsi dari default 30 detik menjadi maksimum 300 detik:

    timeout: 300
    
  6. Deploy fungsi ke OCI:

    fn -v deploy --app audit-logs-to-secops-app
    

Mengonfigurasi variabel lingkungan fungsi

  1. Di Oracle Cloud Console, buka Developer Services > Functions > Applications.
  2. Klik aplikasi (audit-logs-to-secops-app).
  3. Klik nama fungsi (oci-audit-to-secops).
  4. Klik Konfigurasi.
  5. Tambahkan variabel konfigurasi berikut:

    Kunci Nilai
    SECOPS_WEBHOOK_URL URL endpoint feed
    SECOPS_API_KEY Kunci API Google Cloud
    SECOPS_SECRET_KEY Kunci rahasia feed
  6. Klik Simpan perubahan.

Mengaktifkan log fungsi

  1. Di halaman daftar Applications, pilih audit-logs-to-secops-app.
  2. Pilih tab Monitoring, lalu buka bagian Logs.
  3. Dari menu Actions (tiga titik) untuk kategori Function Invocation Logs, pilih Enable Log.
  4. Pertahankan kompartemen, grup log, dan nama log default, atau ubah sesuai kebutuhan.
  5. Pilih Enable Log.

Membuat konektor OCI Connector Hub

  1. Buka menu navigasi dan pilih Analytics & AI. Di bagian Messaging, pilih Connector Hub.
  2. Pilih kompartemen tempat Anda ingin membuat konektor.
  3. Klik Create connector.
  4. Berikan detail konfigurasi berikut:

    • Informasi konektor:

      Setelan Nilai
      Nama Konektor Masukkan audit-logs-to-secops-connector
      Deskripsi Masukkan Forward OCI Audit logs to a webhook feed
      Kompartemen Resource Pilih kompartemen
    • Konfigurasi sumber:

      Setelan Nilai
      Source Pilih Logging
      Kompartemen Pilih kompartemen yang berisi log audit
      Grup Log Pilih _Audit (grup log default untuk log audit)
  5. Klik + Another Log.

  6. Pilih log audit untuk kompartemen Anda (misalnya, _Audit_Include_Subcompartment).

    • Configure target:

      Setelan Nilai
      Target Pilih Functions
      Kompartemen Fungsi Pilih kompartemen yang berisi fungsi
      Penerapan Fungsi Pilih audit-logs-to-secops-app
      Fungsi Pilih oci-audit-to-secops
  7. Buka Configure task (optional) dan biarkan setelan default.

  8. Jika diminta untuk membuat kebijakan (diperlukan untuk akses guna membuat atau mengupdate konektor layanan), pilih Create.

  9. Klik Create.

Membuat kebijakan IAM untuk Connector Hub

Connector Hub memerlukan izin untuk memanggil fungsi.

  1. Di Oracle Cloud Console, buka Identity & Security > Policies.
  2. Pilih kompartemen tempat Anda membuat konektor.
  3. Klik Create Policy.
  4. Berikan detail konfigurasi berikut:
    • Nama: Masukkan connector-hub-secops-function-policy.
    • Deskripsi: Masukkan Allow Connector Hub to invoke the webhook forwarding function.
    • Compartment: Pilih kompartemen.
  5. Di bagian Policy Builder, aktifkan Show manual editor.
  6. Masukkan pernyataan kebijakan berikut:

    Allow any-user to use fn-function in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    Allow any-user to use fn-invocation in compartment <compartment-name> where all {request.principal.type='serviceconnector'}
    
  7. Klik Create.

Cara fungsi mengirimkan log

  • Ukuran batch: Connector Hub mengirimkan batch fungsi hingga 6 MB, dan webhook menerima hingga 4 MB per permintaan. Fungsi ini membagi setiap batch menjadi permintaan hingga 3 MB. Logstash hanya memisahkan di antara entri log, tidak pernah di dalamnya, dan setiap entri tiba di Google SecOps sebagai satu peristiwa.
  • Percobaan ulang: Fungsi ini mencoba ulang respons HTTP 429 dan 5xx dengan backoff eksponensial, dan mematuhi header Retry-After. Error lainnya, atau permintaan yang masih gagal setelah lima kali percobaan, akan menggagalkan pemanggilan. Connector Hub kemudian akan mencoba ulang seluruh batch dan tidak akan memindahkan batch berikutnya hingga berhasil.
  • Retensi: Sumber Logging Connector Hub menyimpan data yang tidak terkirim selama 24 jam. Jika pengiriman terus gagal dalam waktu yang lebih lama, log terlama yang tidak terkirim akan hilang, jadi segera perbaiki error yang dilaporkan dalam log fungsi.
  • Duplikat: Connector Hub mengirimkan setiap batch setidaknya sekali. Jika batch dicoba lagi setelah sebagiannya sudah dikirim, Google SecOps dapat menerima entri tersebut dua kali.
  • Entri terlalu besar: Entri log yang lebih besar dari 1 MB melebihi batas baris webhook. Fungsi akan melewati dan menulis ID-nya ke log fungsi.

Memverifikasi integrasi

Untuk memverifikasi integrasi, lakukan hal berikut:

  1. Lakukan beberapa tindakan di Oracle Cloud Console yang menghasilkan log audit (misalnya, membuat atau mengubah resource).
  2. Tunggu 2-5 menit hingga Connector Hub mengirimkan log.
  3. Buka log pemanggilan fungsi yang Anda aktifkan dan pastikan log tersebut berisi pesan Forwarded N log entries. Pesan error menyertakan status HTTP yang ditampilkan Google SecOps.
  4. Di Google SecOps, jalankan penelusuran log mentah untuk jenis log OCI_AUDIT dan pastikan peristiwa audit diterima.

Tabel pemetaan UDM

Kolom Log Pemetaan UDM Logika
accept_encoding_field additional.fields Digabung
accept_field additional.fields Digabung
additional_app additional.fields Digabung
additional_content_type additional.fields Digabung
additional_sort_by additional.fields Digabung
additionaldetails_data additional.fields Digabung
allow_methods_field additional.fields Digabung
auth_type_label additional.fields Digabung
authorization_field additional.fields Digabung
backend_connect_time_field additional.fields Digabung
backend_processing_time_field additional.fields Digabung
caller_id_label additional.fields Digabung
caller_name_label additional.fields Digabung
cloud_event_versiom_field additional.fields Digabung
compartment_id_field additional.fields Digabung
compartment_name_field additional.fields Digabung
connection_field additional.fields Digabung
content_length_field additional.fields Digabung
content_type_field additional.fields Digabung
event_grouping_id_field additional.fields Digabung
event_name_label additional.fields Digabung
event_resource_label additional.fields Digabung
event_source_label additional.fields Digabung
event_type_label additional.fields Digabung
event_type_versiom_field additional.fields Digabung
has_compariment_id additional.fields Dipetakan: true → additional_app
has_sort_by additional.fields Dipetakan: true → additional_sort_by
listener_name_field additional.fields Digabung
log_group_id_field additional.fields Digabung
log_id_field additional.fields Digabung
message additional.fields Nilai yang dipetakan (total 41, misalnya \/ → tenant_id_label, \/ → auth_type_label, \/ → `ca...
opc_request_id_field additional.fields Digabung
origin_field additional.fields Digabung
param0_field additional.fields Digabung
param1_field additional.fields Digabung
referer_field additional.fields Digabung
request_processing_time_field additional.fields Digabung
resource_id_field additional.fields Digabung
routing_rules_engine_errors_field additional.fields Digabung
routing_rules_matched_rule_field additional.fields Digabung
routing_rules_rule_hits_field additional.fields Digabung
routing_rules_rule_misses_field additional.fields Digabung
source_field additional.fields Digabung
tenant_id_label additional.fields Digabung
column3 extensions.auth.type Dipetakan: login successful → AUTHTYPE_UNSPECIFIED
message extensions.auth.type Dipetakan: \/ → AUTHTYPE_UNSPECIFIED
column3 metadata.description Dipetakan secara langsung
data.message metadata.description Dipetakan secara langsung
column1 metadata.event_timestamp Diurai sebagai yyyy-MM-dd HH:mm:ss
data_event_time metadata.event_timestamp Diurai sebagai yyyy-MM-ddTHH:mm:ss.SSSSSSZ
time metadata.event_timestamp Diurai sebagai ISO8601
metadata_event_type metadata.event_type Dipetakan secara langsung
type metadata.product_event_type Dipetakan secara langsung
data_event_id metadata.product_log_id Dipetakan secara langsung
id metadata.product_log_id Dipetakan secara langsung
message metadata.product_name Dipetakan: \/ → OCI_AUDIT
specversion metadata.product_version Dipetakan secara langsung
message metadata.vendor_name Dipetakan: \/ → Oracle
message network.application_protocol Dipetakan: \/ → HTTPS, \/ → HTTP
protocol network.application_protocol Dipetakan: (?i)HTTPS → HTTPS, (?i)HTTP → HTTP
version network.application_protocol_version Dipetakan secara langsung
data_request_action network.http.method Dipetakan secara langsung
method network.http.method Dipetakan secara langsung
data_identity_userAgent network.http.parsed_user_agent Diganti namanya/dipetakan
data_request_agent network.http.parsed_user_agent Diganti namanya/dipetakan
url network.http.referral_url Dipetakan secara langsung
data.backendStatusCode network.http.response_code Dipetakan secara langsung
data_response_status network.http.response_code Diganti namanya/dipetakan
data.userAgent network.http.user_agent Dipetakan secara langsung
data_identity_userAgent network.http.user_agent Dipetakan secara langsung
data_request_agent network.http.user_agent Dipetakan secara langsung
data.receivedBytes network.received_bytes Dipetakan secara langsung
message network.received_bytes Dipetakan: \/ → uinteger
data.sentBytes network.sent_bytes Dipetakan secara langsung
message network.sent_bytes Dipetakan: \/ → uinteger
data_identity_consoleSessionId network.session_id Diganti namanya/dipetakan
data.sslCipher network.tls.cipher Dipetakan secara langsung
data.sslProtocol network.tls.version Dipetakan secara langsung
data.host principal.asset.hostname Dipetakan secara langsung
hostname principal.asset.hostname Dipetakan secara langsung
column6 principal.asset.ip Digabung
data.forwardedForAddr principal.asset.ip Digabung
data_identity_ipAddress principal.asset.ip Dipetakan: ^(?:[0-9]{1,3}[.]){3}[0-9]{1,3}$ → data_identity_ipAddress
data_request_origin principal.asset.ip Digabung
ip1 principal.asset.ip Digabung
ip2 principal.asset.ip Digabung
message principal.asset.ip Nilai yang dipetakan (total 7, mis. \/ → column6, \/ → data_request_origin, \/ → ip2)
src_ip principal.asset.ip Digabung
data.host principal.hostname Dipetakan secara langsung
hostname principal.hostname Dipetakan secara langsung
column6 principal.ip Digabung
data.forwardedForAddr principal.ip Digabung
data_identity_ipAddress principal.ip Dipetakan: ^(?:[0-9]{1,3}[.]){3}[0-9]{1,3}$ → data_identity_ipAddress
data_request_origin principal.ip Digabung
ip1 principal.ip Digabung
ip2 principal.ip Digabung
message principal.ip Nilai yang dipetakan (total 7, mis. \/ → column6, \/ → data_request_origin, \/ → ip2)
src_ip principal.ip Digabung
data_request_headers_sec-ch-ua-platform_0 principal.platform Dipetakan: (?i)Linux → LINUX, (?i)windows → WINDOWS, (?i)mac/ios → MAC
message principal.platform Dipetakan: \/ → LINUX, \/ → WINDOWS, \/ → MAC
originalConnection.sourcePort principal.port Dipetakan secara langsung
src_port principal.port Dipetakan secara langsung
data_request_headers_oci-original-url_0 principal.url Dipetakan secara langsung
credentials_label principal.user.attribute.labels Digabung
message principal.user.attribute.labels Dipetakan: \/ → credentials_label
data.identity.principalName principal.user.user_display_name Dipetakan secara langsung
data.username principal.user.user_display_name Dipetakan secara langsung
data.identity.principalId principal.user.userid Dipetakan secara langsung
data.principalId principal.user.userid Dipetakan secara langsung
column3 security_result Dipetakan: login successful → security_result
message security_result Dipetakan: \/ → security_result
allow_action security_result.action Digabung
column3 security_result.action Dipetakan: login successful → allow_action
message security_result.action Dipetakan: \/ → allow_action
credential_type_field security_result.detection_fields Digabung
message security_result.detection_fields Dipetakan: \/ → credential_type_field
data.response.message security_result.summary Dipetakan secara langsung
message target.asset.ip Dipetakan: \/ → originalConnection.destinationIp, \/ → tar_ip
originalConnection.destinationIp target.asset.ip Digabung
tar_ip target.asset.ip Digabung
message target.ip Dipetakan: \/ → originalConnection.destinationIp, \/ → tar_ip
originalConnection.destinationIp target.ip Digabung
tar_ip target.ip Digabung
originalConnection.destinationPort target.port Dipetakan secara langsung
tar_port target.port Dipetakan secara langsung
message target.resource.attribute.labels Dipetakan: \/ → namespace_label
namespace_label target.resource.attribute.labels Digabung
type target.resource.attribute.labels Dipetakan: listretentionrules → namespace_label
data.resourceId target.resource.name Dipetakan secara langsung
data.resourceName target.resource.name Dipetakan secara langsung
bucketId target.resource.product_object_id Dipetakan secara langsung
data.resourceId target.resource.product_object_id Dipetakan secara langsung
data_request_id target.resource.product_object_id Dipetakan secara langsung
message target.resource.resource_type Dipetakan: \/ → STORAGE_BUCKET
type target.resource.resource_type Dipetakan: listretentionrules → STORAGE_BUCKET
data_request_path target.url Dipetakan secara langsung
column2 target.user.email_addresses Digabung
message target.user.email_addresses Dipetakan: \/ → column2
T/A extensions.auth.type Konstanta: AUTHTYPE_UNSPECIFIED
T/A metadata.product_name Konstanta: OCI_AUDIT
T/A metadata.vendor_name Konstanta: Oracle
T/A network.application_protocol Konstanta: HTTPS
T/A principal.platform Konstanta: LINUX
T/A target.resource.resource_type Konstanta: STORAGE_BUCKET

Log Perubahan

Melihat Log Perubahan untuk parser ini

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