Mengumpulkan log Trellix Endpoint Security HX (sebelumnya FireEye HX)
Versi Parser: 30.0
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 penanganan ancaman tingkat lanjut. Platform ini menggunakan perlindungan berbasis kecerdasan dan indikator penyusupan (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 setidaknya peran Analyst.
Membuat bucket Google Cloud Storage
- Buka Konsol Google Cloud.
- Pilih project Anda.
- Di menu navigasi, buka Cloud Storage > Buckets.
- Klik Create bucket.
Berikan detail konfigurasi berikut:
Setelan Nilai Memberi nama bucket Anda Masukkan nama yang unik secara global (misalnya, fireeye-hx-logs)Location type Pilih sesuai kebutuhan Anda (Region, Dual-region, Multi-region) Location Pilih lokasi yang paling dekat dengan instance Google SecOps Anda Storage class Standard (direkomendasikan untuk log yang sering diakses) Kontrol akses Seragam (direkomendasikan) Alat perlindungan Opsional: Mengaktifkan pembuatan versi objek atau kebijakan retensi Klik Create.
Mengumpulkan kredensial Trellix Endpoint Security HX API
Mendapatkan URL konsol HX
- Login ke konsol web Trellix Endpoint Security HX.
- Catat URL konsol dari kolom URL browser (Format:
https://<hx-hostname>:<port>).
Membuat atau memverifikasi akun pengguna API
- Login ke konsol Trellix HX dengan akun administrator.
- Buka Admin > User Accounts.
- Buat pengguna baru atau pilih pengguna yang sudah ada untuk akses API.
- Pastikan pengguna memiliki peran api_analyst atau api_admin.
- 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"
Membuat 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
- Di Konsol GCP, buka IAM & Admin > Service Accounts.
- Klik Create Service Account.
- Berikan detail konfigurasi berikut:
- Service account name:
fireeye-hx-collector-sa - Service account description:
Service account for Cloud Run function to collect Trellix HX logs
- Service account name:
- Klik Create and Continue.
- Di bagian Grant this service account access to project, tambahkan peran berikut:
- Storage Object Admin
- Cloud Run Invoker
- Cloud Functions Invoker
- Klik Continue, lalu Done.
Memberikan izin IAM di bucket GCS
- Buka Cloud Storage > Buckets.
- Klik nama bucket (
fireeye-hx-logs). - Buka tab Izin.
- Klik Grant access.
- Tambahkan entitas: Masukkan email akun layanan.
- Assign roles: Pilih Storage Object Admin.
- Klik Simpan.
Membuat topik Pub/Sub
Buat topik yang akan dipublikasikan oleh Cloud Scheduler dan di-subscribe oleh fungsi Cloud Run.
- Di Konsol GCP, buka Pub/Sub > Topics.
- Klik Create topic.
- ID Topik:
fireeye-hx-logs-trigger. - Klik Create.
Membuat fungsi Cloud Run untuk mengumpulkan log
- Di Konsol GCP, buka Cloud Run.
- Klik Create service.
- Pilih Fungsi.
Di bagian Configure, berikan detail berikut:
Setelan Nilai Nama layanan fireeye-hx-collectorRegion Pilih region yang cocok dengan bucket GCS Anda Runtime Python 3.12 atau yang lebih baru Di bagian Trigger:
- Klik + Tambahkan pemicu.
- Pilih Cloud Pub/Sub.
- Di Select a Cloud Pub/Sub topic, pilih
fireeye-hx-logs-trigger. - Klik Simpan.
Di bagian Authentication, pilih Require authentication dan centang Identity and Access Management (IAM).
Scroll ke bawah ke Containers, Networking, Security.
Di tab Security, pilih akun layanan
fireeye-hx-collector-sa.Di tab Containers, klik Variables & Secrets dan tambahkan hal berikut:
Nama Variabel Nilai Contoh Deskripsi GCS_BUCKETfireeye-hx-logsNama bucket GCS GCS_PREFIXhx-alertsAwalan untuk file log STATE_KEYhx-alerts/state.jsonJalur file status HX_HOSThttps://hx-console.example.com:3000URL konsol HX HX_USERapi_userNama pengguna API HX_PASSapi_passwordSandi API MAX_RECORDS1000Data maksimum per operasi PAGE_SIZE100Data per halaman LOOKBACK_HOURS24Periode lihat balik awal Di Requests, tetapkan Request timeout ke
600detik.Klik Create. Setelah layanan dibuat, editor kode inline akan terbuka.
Menambahkan kode fungsi
- Masukkan main di kolom Entry point.
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.0Klik Deploy untuk menyimpan dan men-deploy fungsi.
Buat tugas Cloud Scheduler
- Di Konsol GCP, buka Cloud Scheduler.
- Klik Create Job.
Berikan detail konfigurasi berikut:
Setelan Nilai Nama fireeye-hx-collector-hourlyRegion Pilih region yang sama dengan fungsi Cloud Run Frekuensi 0 * * * *(setiap jam, tepat pada jamnya)Zona Waktu Pilih zona waktu (UTC direkomendasikan) Jenis target Pub/Sub Topik fireeye-hx-logs-triggerIsi pesan {}Klik Create.
Menguji integrasi
- Di Cloud Scheduler, temukan tugas Anda, lalu klik Force run.
- Buka Cloud Run > Services > Logs untuk memverifikasi keberhasilan.
- Periksa Cloud Storage untuk mengonfirmasi bahwa file
.ndjsonbaru ada di folderhx-alerts/.
Mengonfigurasi feed di Google SecOps
- Buka Setelan > Pengelolaan Data > Feed. Jika Anda menggunakan platform khusus SIEM, buka Settings > Feeds.
- Klik Tambahkan Feed Baru > Konfigurasi satu feed.
- Nama feed:
Trellix HX Logs. - Source type: Google Cloud Storage V2.
- Log type: FireEye HX.
- Klik Get Service Account dan salin email (misalnya,
chronicle-12345678@...). - Klik Berikutnya.
- Storage bucket URL:
gs://fireeye-hx-logs/hx-alerts/(Sertakan garis miring di akhir). - Opsi penghapusan sumber: Pilih sesuai preferensi Anda.
- Klik Berikutnya, tinjau, lalu klik Kirim.
Memberikan izin IAM ke akun layanan
Akun layanan Google SecOps memerlukan peran Storage Object Viewer di bucket Anda.
- Buka Cloud Storage > Buckets.
- Pilih bucket Anda dan buka tab Permissions.
- Klik Grant access.
- Add principals: Tempel email akun layanan Google SecOps.
- Assign roles: Pilih Storage Object Viewer.
- 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 |
Diurai 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 |
Tetapkan 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.