Mengumpulkan log Trellix Endpoint Security HX (sebelumnya FireEye HX)

Versi Parser: 30.0

Didukung di:

Panduan ini menjelaskan cara menyerap log Trellix Endpoint Security HX (sebelumnya dikenal sebagai FireEye HX) ke Google Security Operations menggunakan Google Cloud Storage V2. Trellix Endpoint Security HX adalah platform deteksi dan respons endpoint (EDR) yang menyediakan kemampuan deteksi, investigasi, dan penanggulangan ancaman tingkat lanjut. Platform ini menggunakan perlindungan berbasis intelijen dan indikator kompromi (IOC) real-time untuk mendeteksi dan merespons serangan canggih pada endpoint.

Sebelum memulai

Pastikan Anda memiliki prasyarat berikut:

  • Instance Google SecOps.
  • Project GCP dengan Cloud Storage API yang diaktifkan.
  • Izin untuk membuat dan mengelola bucket GCS dan kebijakan IAM.
  • Izin untuk membuat layanan Cloud Run, topik Pub/Sub, dan tugas Cloud Scheduler.
  • Akses istimewa ke konsol Trellix Endpoint Security HX dengan akses API diaktifkan.
  • Akun pengguna Trellix HX API dengan minimal peran Analis.

Buat bucket Google Cloud Storage

  1. Buka Konsol Google Cloud.
  2. Pilih project Anda.
  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, fireeye-hx-logs)
    Location type Pilih berdasarkan kebutuhan Anda (Region, Dual-region, Multi-region)
    Location Pilih lokasi terdekat dengan instance Google SecOps Anda
    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.

Mengumpulkan kredensial Trellix Endpoint Security HX API

Mendapatkan URL konsol HX

  1. Login ke konsol web Trellix Endpoint Security HX.
  2. Perhatikan URL konsol dari kolom URL browser (Format: https://<hx-hostname>:<port>).

Membuat atau memverifikasi akun pengguna API

  1. Login ke konsol Trellix HX dengan akun administrator.
  2. Buka Admin > Akun Pengguna.
  3. Buat pengguna baru atau pilih pengguna yang sudah ada untuk akses API.
  4. Pastikan pengguna memiliki peran api_analyst atau api_admin.
  5. Catat nama pengguna dan sandi untuk akses API.

Memverifikasi akses API

  • Uji kredensial Anda sebelum melanjutkan integrasi:

    HX_HOST="[https://hx-console.example.com:3000](https://hx-console.example.com:3000)"
    HX_USER="api_user"
    HX_PASS="api_password"
    
    # Authenticate and get token
    curl -k -X POST "$HX_HOST/hx/api/v3/token" \
        -u "$HX_USER:$HX_PASS"
    

Buat akun layanan untuk fungsi Cloud Run

Fungsi Cloud Run memerlukan akun layanan dengan izin untuk menulis ke bucket GCS dan dipanggil oleh Pub/Sub.

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: fireeye-hx-collector-sa
    • Deskripsi akun layanan: Service account for Cloud Run function to collect Trellix HX logs
  4. Klik Create and Continue.
  5. Di bagian Grant this service account access to project, tambahkan peran berikut:
    1. Storage Object Admin
    2. Cloud Run Invoker
    3. Cloud Functions Invoker
  6. Klik Lanjutkan, lalu klik Selesai.

Memberikan izin IAM pada bucket GCS

  1. Buka Cloud Storage > Buckets.
  2. Klik nama bucket (fireeye-hx-logs).
  3. Buka tab Izin.
  4. Klik Grant access.
  5. Add principals: Masukkan email akun layanan.
  6. Tetapkan peran: Pilih Storage Object Admin.
  7. Klik Simpan.

Membuat topik Pub/Sub

Buat topik yang akan dipublikasikan oleh Cloud Scheduler dan yang akan disubscribe oleh fungsi Cloud Run.

  1. Di GCP Console, buka Pub/Sub > Topics.
  2. Klik Create topic.
  3. ID Topik: fireeye-hx-logs-trigger.
  4. Klik Create.

Membuat fungsi Cloud Run untuk mengumpulkan log

  1. Di Konsol GCP, buka Cloud Run.
  2. Klik Create service.
  3. Pilih Fungsi.
  4. Di bagian Konfigurasi, berikan detail berikut:

    Setelan Nilai
    Nama layanan fireeye-hx-collector
    Region Pilih region yang cocok dengan bucket GCS Anda
    Runtime Python 3.12 atau yang lebih baru
  5. Di bagian Pemicu:

    1. Klik + Tambahkan pemicu.
    2. Pilih Cloud Pub/Sub.
    3. Di Select a Cloud Pub/Sub topic, pilih fireeye-hx-logs-trigger.
    4. Klik Simpan.
  6. Di bagian Authentication, pilih Require authentication, lalu centang Identity and Access Management (IAM).

  7. Scroll ke bawah ke Containers, Networking, Security.

  8. Di tab Security, pilih akun layanan fireeye-hx-collector-sa.

  9. Di tab Containers, klik Variables & Secrets, lalu tambahkan berikut ini:

    Nama Variabel Nilai Contoh Deskripsi
    GCS_BUCKET fireeye-hx-logs Nama bucket GCS
    GCS_PREFIX hx-alerts Awalan untuk file log
    STATE_KEY hx-alerts/state.json Jalur file status
    HX_HOST https://hx-console.example.com:3000 URL konsol HX
    HX_USER api_user Nama pengguna API
    HX_PASS api_password Sandi API
    MAX_RECORDS 1000 Jumlah data maks per proses
    PAGE_SIZE 100 Data per halaman
    LOOKBACK_HOURS 24 Periode lihat balik awal
  10. Di Requests, setel Request timeout ke 600 detik.

  11. Klik Create. Setelah layanan dibuat, editor kode inline akan terbuka.

Menambahkan kode fungsi

  1. Masukkan main di kolom Entry point.
  2. Buat file berikut di editor inline:

    • main.py:
    import functions_framework
    from google.cloud import storage
    import json
    import os
    import urllib3
    from datetime import datetime, timezone, timedelta
    import time
    
    # Disable SSL warnings for self-signed certs
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Initialize HTTP client with timeouts
    http = urllib3.PoolManager(
        timeout=urllib3.Timeout(connect=5.0, read=30.0),
        retries=False,
        cert_reqs='CERT_NONE',
    )
    
    # Initialize Storage client
    storage_client = storage.Client()
    
    # Environment variables
    GCS_BUCKET = os.environ.get('GCS_BUCKET')
    GCS_PREFIX = os.environ.get('GCS_PREFIX', 'hx-alerts')
    STATE_KEY = os.environ.get('STATE_KEY', 'hx-alerts/state.json')
    HX_HOST = os.environ.get('HX_HOST')
    HX_USER = os.environ.get('HX_USER')
    HX_PASS = os.environ.get('HX_PASS')
    MAX_RECORDS = int(os.environ.get('MAX_RECORDS', '1000'))
    PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '100'))
    LOOKBACK_HOURS = int(os.environ.get('LOOKBACK_HOURS', '24'))
    
    def get_api_token(host, username, password):
        url = f"{host}/hx/api/v3/token"
        auth_string = f"{username}:{password}"
        import base64
        auth_b64 = base64.b64encode(auth_string.encode('utf-8')).decode('utf-8')
        headers = {'Authorization': f'Basic {auth_b64}'}
        response = http.request('POST', url, headers=headers)
        if response.status == 204:
            return response.headers.get('X-FeApi-Token')
        else:
            raise Exception(f"Authentication failed: HTTP {response.status}")
    
    @functions_framework.cloud_event
    def main(cloud_event):
        if not all([GCS_BUCKET, HX_HOST, HX_USER, HX_PASS]):
            print('Error: Missing required environment variables')
            return
        try:
            bucket = storage_client.bucket(GCS_BUCKET)
            state = load_state(bucket, STATE_KEY)
            now = datetime.now(timezone.utc)
            last_time = None
    
            if isinstance(state, dict) and state.get("last_event_time"):
                try:
                    last_time = parse_datetime(state["last_event_time"]) - timedelta(minutes=2)
                except Exception as e:
                    print(f"Warning: Could not parse last_event_time: {e}")
    
            if last_time is None:
                last_time = now - timedelta(hours=LOOKBACK_HOURS)
    
            print(f"Fetching alerts from {last_time.isoformat()} to {now.isoformat()}")
            token = get_api_token(HX_HOST, HX_USER, HX_PASS)
            alerts, newest_time = fetch_alerts(HX_HOST, token, last_time, now, PAGE_SIZE, MAX_RECORDS)
            hosts = fetch_hosts(HX_HOST, token)
            all_records = alerts + hosts
    
            if not all_records:
                print("No new records found.")
                save_state(bucket, STATE_KEY, now.isoformat())
                return
    
            timestamp = now.strftime('%Y%m%d_%H%M%S')
            object_key = f"{GCS_PREFIX}/logs_{timestamp}.ndjson"
            ndjson = '\n'.join([json.dumps(record, ensure_ascii=False) for record in all_records]) + '\n'
            bucket.blob(object_key).upload_from_string(ndjson, content_type='application/x-ndjson')
    
            print(f"Wrote {len(all_records)} records to gs://{GCS_BUCKET}/{object_key}")
            save_state(bucket, STATE_KEY, newest_time if newest_time else now.isoformat())
            release_token(HX_HOST, token)
            print(f"Successfully processed {len(all_records)} records")
        except Exception as e:
            print(f'Error processing logs: {str(e)}')
            raise
    
    def parse_datetime(value):
        if value.endswith("Z"):
            value = value[:-1] + "+00:00"
        return datetime.fromisoformat(value)
    
    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, last_event_time_iso):
        try:
            state = {'last_event_time': last_event_time_iso}
            bucket.blob(key).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_alerts(host, token, start_time, end_time, page_size, max_records):
        endpoint = f"{host}/hx/api/v3/alerts"
        headers = {'X-FeApi-Token': token, 'Accept': 'application/json'}
        records = []; newest_time = None; offset = 0; backoff = 1.0
    
        while True:
            if len(records) >= max_records: break
            start_iso = start_time.strftime('%Y-%m-%dT%H:%M:%S.000Z')
            end_iso = end_time.strftime('%Y-%m-%dT%H:%M:%S.000Z')
            url = f"{endpoint}?sort=reported_at+asc&min_reported_at={start_iso}&max_reported_at={end_iso}&offset={offset}&limit={min(page_size, max_records - len(records))}"
    
            try:
                response = http.request('GET', url, headers=headers)
                if response.status == 429:
                    time.sleep(int(response.headers.get('Retry-After', str(int(backoff))))); backoff = min(backoff * 2, 30.0); continue
                backoff = 1.0
                if response.status != 200: break
                data = json.loads(response.data.decode('utf-8'))
                page_results = data.get('data', {}).get('entries', [])
                if not page_results: break
                records.extend(page_results)
                for alert in page_results:
                    event_time = alert.get('reported_at')
                    if event_time and (newest_time is None or event_time > newest_time): newest_time = event_time
                offset += len(page_results)
                if offset >= data.get('data', {}).get('total', 0): break
            except Exception: break
        return records, newest_time
    
    def fetch_hosts(host, token):
        endpoint = f"{host}/hx/api/v3/hosts"
        headers = {'X-FeApi-Token': token, 'Accept': 'application/json'}
        try:
            response = http.request('GET', f"{endpoint}?limit=100&offset=0", headers=headers)
            if response.status != 200: return []
            return json.loads(response.data.decode('utf-8')).get('data', {}).get('entries', [])
        except Exception: return []
    
    def release_token(host, token):
        try:
            http.request('DELETE', f"{host}/hx/api/v3/token", headers={'X-FeApi-Token': token})
        except Exception: pass
    
    • requirements.txt:
    functions-framework==3.*
    google-cloud-storage==2.*
    urllib3>=2.0.0
    
  3. Klik Deploy untuk menyimpan dan men-deploy fungsi.

Buat tugas Cloud Scheduler

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

    Setelan Nilai
    Nama fireeye-hx-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 fireeye-hx-logs-trigger
    Isi pesan {}
  4. Klik Create.

Menguji integrasi

  1. Di Cloud Scheduler, temukan tugas Anda, lalu klik Force run.
  2. Buka Cloud Run > Services > Logs untuk memverifikasi keberhasilan.
  3. Periksa Cloud Storage untuk mengonfirmasi bahwa file .ndjson baru ada di folder hx-alerts/.

Mengonfigurasi feed di Google SecOps

  1. Buka SIEM Settings > Feeds.
  2. Klik Tambahkan Feed Baru > Konfigurasi satu feed.
  3. Nama feed: Trellix HX Logs.
  4. Jenis sumber: Google Cloud Storage V2.
  5. Log type: FireEye HX.
  6. Klik Get Service Account dan salin email (misalnya, chronicle-12345678@...).
  7. Klik Berikutnya.
  8. URL bucket penyimpanan: gs://fireeye-hx-logs/hx-alerts/ (Sertakan garis miring di akhir).
  9. Opsi penghapusan sumber: Pilih sesuai preferensi Anda.
  10. Klik Berikutnya, tinjau, lalu klik Kirim.

Memberikan izin IAM ke akun layanan

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

  1. Buka Cloud Storage > Buckets.
  2. Pilih bucket Anda, lalu buka tab Permissions.
  3. Klik Grant access.
  4. Add principals: Tempel email akun layanan Google SecOps.
  5. Tetapkan peran: Pilih Storage Object Viewer.
  6. Klik Simpan.

Tabel pemetaan UDM

Kolom log Pemetaan UDM Logika
alert.event_type metadata.product_event_type Pemetaan langsung.
alert.reported_at metadata.event_timestamp Diuraikan sebagai stempel waktu.
alert.source principal.hostname Pemetaan langsung.
alert.agent._id principal.asset_id Pemetaan langsung.
alert.indicator.display_name security_result.threat_name Pemetaan langsung.
alert.md5values target.file.md5 Pemetaan langsung.
T/A metadata.vendor_name Tetapkan ke Trellix.
T/A metadata.product_name Setel ke Endpoint Security HX.
T/A metadata.log_type Tetapkan ke FIREEYE_HX.
cs12 additional.fields Dipetakan dari log perubahan
cs9 target.process.file.md5 Dipetakan dari log perubahan
account_name", "UUID", "Mitre", "host_details.data.sysinfo.url", "host_details.route", "host_details.data.reported_clone", and "host_details.data.timezone security_result.detection_fields Dipetakan dari log perubahan
Desc metadata.description Dipetakan dari log perubahan
Confidence security_result.confidence Dipetakan dari log perubahan
alert.appliance._id additional.fields Dipetakan dari log perubahan
host_details.data.stats.acqs", "host_details.data.stats.alerting_conditions", "host_details.data.stats.alerts", "host_details.data.stats.exploit_alerts", "host_details.data.stats.exploit_blocks", and "host_details.data.stats.false_positive_alerts security_result.detection_fields Dipetakan dari log perubahan
categoryOutcome", "cs13 additional.fields Dipetakan dari log perubahan
cs6 target.process.file.sha1 Dipetakan dari log perubahan
host_details.message security_result.action_details Dipetakan dari log perubahan
alert.md5values", "alert.resolution", "alert.is_false_positive", and "alert.alert_type additional.fields Dipetakan dari log perubahan
type.threat_type security_result.threat_name Dipetakan dari log perubahan
ent.lms_event_id metadata.product_log_id Dipetakan dari log perubahan
email.smtp.mail_from network.email.from Dipetakan dari log perubahan
email.headers.subject network.email.subject Dipetakan dari log perubahan
email.headers.to network.email.to Dipetakan dari log perubahan
ent.type", "ent.id", "ent.name", "ent.object_source", "ent.binary", and "ent.attributes.scan_id security_result.detection_fields Dipetakan dari log perubahan
cs11Label additional_cs11Label.key Dipetakan dari log perubahan
cs11 additional_cs11.value Dipetakan dari log perubahan
alert.sysinfo.mac_address principal.mac Dipetakan dari log perubahan
host_details.data.agent_version metadata.product_version Dipetakan dari log perubahan
alert.url metadata.url_back_to_product Dipetakan dari log perubahan
description metadata.description Dipetakan dari log perubahan
alert.agent._id principal.asset.asset_id Dipetakan dari log perubahan
alert.event_id metadata.product_log_id Dipetakan dari log perubahan
deviceCustomDate1Label additional_deviceCustomDate1.key Dipetakan dari log perubahan
deviceCustomDate1 additional_deviceCustomDate1.value Dipetakan dari log perubahan
deviceCustomDate2 additional_deviceCustomDate2.value Dipetakan dari log perubahan
client principal.ip Dipetakan dari log perubahan
principal_ip principal.ip Dipetakan dari log perubahan
remoteaddress principal.ip Dipetakan dari log perubahan
host_ principal.hostname Dipetakan dari log perubahan
line principal.application Dipetakan dari log perubahan
username principal.user.userid Dipetakan dari log perubahan
client_app_type principal.resource.attribute.labels Dipetakan dari log perubahan
upstream target.url Dipetakan dari log perubahan
role target.user.role_name Dipetakan dari log perubahan
server target.resource.attribute.labels Dipetakan dari log perubahan
localusername target.user.user_display_name Dipetakan dari log perubahan
request additional.fields Dipetakan dari log perubahan
mlocked additional.fields Dipetakan dari log perubahan
kernel_stack additional.fields Dipetakan dari log perubahan
sessionID network.session_id Dipetakan dari log perubahan
auth_mechanism extensions.auth.mechanism Dipetakan dari log perubahan
authsubmethod extensions.auth.auth_details Dipetakan dari log perubahan

Log Perubahan

Melihat Log Perubahan untuk parser ini

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