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 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
- Buka Konsol Google Cloud.
- Pilih project Anda.
- Di menu navigasi, buka Cloud Storage > Buckets.
- Klik Create bucket.
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 Klik Create.
Mengumpulkan kredensial Trellix Endpoint Security HX API
Mendapatkan URL konsol HX
- Login ke konsol web Trellix Endpoint Security HX.
- Perhatikan 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 > Akun Pengguna.
- 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"
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
- Di Konsol GCP, buka IAM & Admin > Service Accounts.
- Klik Create Service Account.
- 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
- Nama akun layanan:
- 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 Lanjutkan, lalu klik Selesai.
Memberikan izin IAM pada bucket GCS
- Buka Cloud Storage > Buckets.
- Klik nama bucket (
fireeye-hx-logs). - Buka tab Izin.
- Klik Grant access.
- Add principals: Masukkan email akun layanan.
- Tetapkan peran: Pilih Storage Object Admin.
- Klik Simpan.
Membuat topik Pub/Sub
Buat topik yang akan dipublikasikan oleh Cloud Scheduler dan yang akan disubscribe oleh fungsi Cloud Run.
- Di GCP Console, 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 Konfigurasi, 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 Pemicu:
- 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, lalu 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, lalu tambahkan berikut ini:
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_RECORDS1000Jumlah data maks per proses PAGE_SIZE100Data per halaman LOOKBACK_HOURS24Periode lihat balik awal Di Requests, setel 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 waktunya)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 SIEM Settings > Feeds.
- Klik Tambahkan Feed Baru > Konfigurasi satu feed.
- Nama feed:
Trellix HX Logs. - Jenis sumber: Google Cloud Storage V2.
- Log type: FireEye HX.
- Klik Get Service Account dan salin email (misalnya,
chronicle-12345678@...). - Klik Berikutnya.
- URL bucket penyimpanan:
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, lalu buka tab Permissions.
- Klik Grant access.
- Add principals: Tempel email akun layanan Google SecOps.
- Tetapkan peran: 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 |
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.