Mengumpulkan log Pemantauan Berkelanjutan Qualys
Kode parser Logstash ini pertama-tama mengekstrak kolom seperti IP sumber, pengguna, metode, dan protokol aplikasi dari pesan log mentah menggunakan pola grok. Kemudian, kode ini memetakan kolom tertentu dari data log mentah ke kolom yang sesuai dalam Model Data Terpadu (UDM), melakukan konversi jenis data, dan memperkaya data dengan label dan metadata tambahan sebelum akhirnya menyusun output dalam format UDM yang diinginkan.
Sebelum memulai
Pastikan Anda memiliki prasyarat berikut:
- Instance Google Security Operations.
- Akses istimewa ke Google Cloud.
- Akses istimewa ke Qualys.
Mengaktifkan API yang Diperlukan:
- Login ke Google Cloud konsol.
- Buka API & Layanan > Library.
- Cari API berikut dan aktifkan:
- Cloud Functions API
- Cloud Scheduler API
- Cloud Pub/Sub (diperlukan agar Cloud Scheduler dapat memanggil fungsi)
Membuat Google Cloud Bucket Penyimpanan
- Login ke Google Cloud konsol.
Buka halaman Bucket Cloud Storage.
Klik Buat.
Konfigurasi bucket:
- Nama: masukkan nama unik yang memenuhi persyaratan nama bucket (misalnya, qualys-asset-bucket).
- Pilih tempat untuk menyimpan data: pilih lokasi.
- Pilih kelas penyimpanan untuk data: pilih kelas penyimpanan default untuk bucket, atau pilih Autoclass untuk pengelolaan kelas penyimpanan otomatis.
- Pilih cara mengontrol akses ke objek: pilih tidak untuk menerapkan pencegahan akses publik, dan pilih model kontrol akses untuk objek bucket Anda.
- Kelas penyimpanan: pilih berdasarkan kebutuhan Anda (misalnya, Standar).
Klik Buat.
Membuat Akun Layanan Google Cloud
- Login ke Google Cloud konsol.
- Buka IAM & Admin > Akun Layanan.
- Buat akun layanan baru.
- Beri nama deskriptif (misalnya, qualys-user).
- Beri akun layanan peran Admin Objek Penyimpanan di bucket GCS yang Anda buat pada langkah sebelumnya.
- Beri akun layanan peran Invoker Cloud Functions.
- Buat kunci SSH untuk akun layanan.
- Download file kunci JSON untuk akun layanan. Amankan file ini.
Opsional: Membuat Pengguna API khusus di Qualys
- Login ke konsol Qualys.
- Buka Pengguna.
- Klik Baru > Pengguna.
- Masukkan Informasi Umum yang diperlukan untuk pengguna.
- Pilih tab Peran Pengguna.
- Pastikan peran tersebut memiliki kotak centang Akses API yang dipilih.
- Klik Simpan.
Mengidentifikasi URL API Qualys tertentu
Opsi 1
Identifikasi URL Anda seperti yang disebutkan dalam identifikasi platform.
Opsi 2
- Login ke konsol Qualys.
- Buka Bantuan > Tentang.
- Scroll untuk melihat informasi ini di bagian Pusat Operasi Keamanan (SOC).
- Salin URL API Qualys.
Mengonfigurasi Cloud Function
- Buka Cloud Functions di Google Cloud konsol.
- Klik Create Function.
Konfigurasi Fungsi:
- Nama: masukkan nama untuk fungsi Anda (misalnya, fetch-qualys-cm-alerts).
- Region: pilih region yang dekat dengan Bucket Anda.
- Runtime: Python 3.10 (atau runtime pilihan Anda).
- Pemicu: pilih pemicu HTTP jika diperlukan atau Cloud Pub/Sub untuk eksekusi terjadwal.
- Autentikasi: amankan dengan autentikasi.
- Tulis Kode dengan editor inline:
```python from google.cloud import storage import requests import base64 import json # Google Cloud Storage Configuration BUCKET_NAME = "<bucket-name>" FILE_NAME = "qualys_cm_alerts.json" # Qualys API Credentials QUALYS_USERNAME = "<qualys-username>" QUALYS_PASSWORD = "<qualys-password>" QUALYS_BASE_URL = "https://<qualys_base_url>" def fetch_cm_alerts(): """Fetch alerts from Qualys Continuous Monitoring.""" auth = base64.b64encode(f"{QUALYS_USERNAME}:{QUALYS_PASSWORD}".encode()).decode() headers = { "Authorization": f"Basic {auth}", "Content-Type": "application/xml" } payload = """ <ServiceRequest> <filters> <Criteria field="alert.date" operator="GREATER">2024-01-01</Criteria> </filters> </ServiceRequest> """ response = requests.post(f"{QUALYS_BASE_URL}/qps/rest/2.0/search/cm/alert", headers=headers, data=payload) response.raise_for_status() return response.json() def upload_to_gcs(data): """Upload data to Google Cloud Storage.""" client = storage.Client() bucket = client.get_bucket(BUCKET_NAME) blob = bucket.blob(FILE_NAME) blob.upload_from_string(json.dumps(data, indent=2), content_type="application/json") def main(request): """Cloud Function entry point.""" try: alerts = fetch_cm_alerts() upload_to_gcs(alerts) return "Qualys CM alerts uploaded to Cloud Storage successfully!" except Exception as e: return f"An error occurred: {e}", 500 ```Klik Deploy setelah menyelesaikan konfigurasi.
Mengonfigurasi Cloud Scheduler
- Buka Cloud Scheduler di Google Cloud konsol.
- Klik Create Job.
Konfigurasi Tugas:
- Nama: masukkan nama untuk tugas Anda (misalnya, trigger-fetch-qualys-cm-alerts).
- Frekuensi: gunakan sintaksis cron untuk menentukan jadwal (misalnya,
0 * * * *untuk menjalankan setiap jam). - Zona Waktu: tetapkan zona waktu pilihan Anda.
- Jenis Pemicu: pilih HTTP.
- URL Pemicu: Masukkan URL Cloud Function (ditemukan di detail fungsi setelah deployment).
- Metode: Pilih POST.
Buat tugas.
Menyiapkan feed
Untuk mengonfigurasi feed, ikuti langkah-langkah berikut:
- Buka Setelan SIEM > Feed.
- Klik Tambahkan Feed Baru.
- Di halaman berikutnya, klik Konfigurasi satu feed.
- Di kolom Nama feed, masukkan nama untuk feed; misalnya, Log Pemantauan Berkelanjutan Qualys.
- Pilih Google Cloud Storage V2 sebagai Jenis sumber.
- Pilih Pemantauan Berkelanjutan Qualys sebagai Jenis log.
- Klik Berikutnya.
Tentukan nilai untuk parameter input berikut:
- URI Bucket Penyimpanan: URI sumber bucket penyimpanan. Google Cloud
- Opsi penghapusan sumber: pilih opsi penghapusan sesuai preferensi Anda.
Klik Berikutnya.
Tinjau konfigurasi feed baru Anda di layar Finalize, lalu klik Submit.
Tabel Pemetaan UDM
| Kolom Log | Pemetaan UDM | Logika |
|---|---|---|
| Alert.alertInfo.appVersion | metadata.product_version | Dipetakan langsung dari Alert.alertInfo.appVersion |
| Alert.alertInfo.operatingSystem | principal.platform_version | Dipetakan langsung dari Alert.alertInfo.operatingSystem |
| Alert.alertInfo.port | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.port dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Alert port" |
| Alert.alertInfo.protocol | network.ip_protocol | Dipetakan langsung dari Alert.alertInfo.protocol |
| Alert.alertInfo.sslIssuer | network.tls.client.certificate.issuer | Dipetakan langsung dari Alert.alertInfo.sslIssuer |
| Alert.alertInfo.sslName | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.sslName dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "SSL Name" |
| Alert.alertInfo.sslOrg | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.sslOrg dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "SSL Org" |
| Alert.alertInfo.ticketId | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.ticketId dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Ticket Id" |
| Alert.alertInfo.vpeConfidence | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.vpeConfidence dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "VPE Confidence" |
| Alert.alertInfo.vpeStatus | additional.fields.value.string_value | Dipetakan langsung dari Alert.alertInfo.vpeStatus dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "VPE Confidence" |
| Alert.eventType | additional.fields.value.string_value | Dipetakan langsung dari Alert.eventType dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Event Type" |
| Alert.hostname | principal.hostname | Dipetakan langsung dari Alert.hostname |
| Alert.id | security_result.threat_id | Dipetakan langsung dari Alert.id |
| Alert.ipAddress | principal.ip | Dipetakan langsung dari Alert.ipAddress |
| Alert.profile.id | additional.fields.value.string_value | Dipetakan langsung dari Alert.profile.id dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Profile Id" |
| Alert.profile.title | additional.fields.value.string_value | Dipetakan langsung dari Alert.profile.title dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Profile Title" |
| Alert.qid | vulnerability.name | Dipetakan sebagai "QID: Alert.qid |
| Alert.source | additional.fields.value.string_value | Dipetakan langsung dari Alert.source dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Alert Source" |
| Alert.triggerUuid | metadata.product_log_id | Dipetakan langsung dari Alert.triggerUuid |
| Alert.vulnCategory | additional.fields.value.string_value | Dipetakan langsung dari Alert.vulnCategory dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Vulnerability Category" |
| Alert.vulnSeverity | vulnerability.severity | Dipetakan berdasarkan nilai Alert.vulnSeverity: 1-3: LOW, 4-6: MEDIUM, 7-8: HIGH |
| Alert.vulnTitle | vulnerability.description | Dipetakan langsung dari Alert.vulnTitle |
| Alert.vulnType | additional.fields.value.string_value | Dipetakan langsung dari Alert.vulnType dan ditambahkan sebagai pasangan nilai kunci di additional.fields dengan kunci "Vulnerability Type" |
| Host | principal.ip | Diuraikan dari baris log "Host: |
| edr.client.ip_addresses | Disalin dari principal.ip |
|
| edr.client.hostname | Disalin dari principal.hostname |
|
| edr.raw_event_name | Ditetapkan ke "STATUS_UPDATE" jika Alert.ipAddress, Alert.hostname, atau src_ip ada, jika tidak, tetapkan ke "GENERIC_EVENT" |
|
| metadata.event_timestamp | Diekstrak dari kolom Alert.eventDate atau timestamp. Alert.eventDate diprioritaskan jika ada, jika tidak, timestamp akan digunakan. Stempel waktu dikonversi ke UTC. |
|
| metadata.event_type | Logika yang sama dengan edr.raw_event_name |
|
| metadata.log_type | Ditetapkan ke "QUALYS_CONTINUOUS_MONITORING" | |
| metadata.product_name | Ditetapkan ke "QUALYS_CONTINUOUS_MONITORING" | |
| metadata.vendor_name | Ditetapkan ke "QUALYS_CONTINUOUS_MONITORING" | |
| network.application_protocol | Diuraikan dari baris log " |
|
| network.http.method | Diuraikan dari baris log " |
|
| timestamp | event.timestamp | Diekstrak dari kolom Alert.eventDate atau timestamp. Alert.eventDate diprioritaskan jika ada, jika tidak, timestamp akan digunakan. Stempel waktu dikonversi ke UTC. |
Log Perubahan
Lihat Log Perubahan untuk parser ini
Perlu bantuan lain? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.