Mengumpulkan log autentikasi Duo
Dokumen ini menjelaskan cara menyerap log autentikasi Duo ke Google Security Operations. Parser mengekstrak log dari pesan berformat JSON. Proses ini mengubah data log mentah menjadi Model Data Terpadu (UDM), memetakan kolom seperti pengguna, perangkat, aplikasi, lokasi, dan detail autentikasi, sekaligus menangani berbagai faktor dan hasil autentikasi untuk mengategorikan peristiwa keamanan. Parser juga melakukan pembersihan data, konversi jenis, dan penanganan error untuk memastikan kualitas dan konsistensi data.
Pilih salah satu dari dua metode pengumpulan:
- Opsi 1: Penyerapan langsung menggunakan API Pihak ketiga
- Opsi 2: Mengumpulkan log menggunakan fungsi Cloud Run dan Google Cloud Storage
Sebelum memulai
Pastikan Anda memiliki prasyarat berikut:
- Instance Google SecOps
- Akses istimewa ke Panel Admin Duo (Peran Pemilik diperlukan untuk membuat aplikasi Admin API)
- Akses istimewa ke GCP jika menggunakan Opsi 2
Opsi 1: Lakukan penyerapan log autentikasi Duo menggunakan API Pihak ketiga
Kumpulkan prasyarat Duo (kredensial API)
- Login ke Panel Admin Duo sebagai administrator dengan peran Pemilik, Administrator, atau Pengelola Aplikasi.
- Buka Applications > Application Catalog.
- Temukan entri untuk Admin API dalam katalog.
- Klik + Tambahkan untuk membuat aplikasi.
- Salin dan simpan detail berikut di lokasi yang aman:
- Kunci Integrasi
- Kunci Rahasia
- Nama Host API (misalnya,
api-XXXXXXXX.duosecurity.com)
- Buka bagian Izin.
- Batalkan pilihan semua opsi izin kecuali Berikan izin baca log.
- Klik Save Changes.
Mengonfigurasi feed di Google SecOps untuk menyerap log autentikasi Duo
- Buka Setelan SIEM > Feed.
- Klik + Tambahkan Feed Baru.
- Di kolom Nama feed, masukkan nama untuk feed (misalnya,
Duo Authentication Logs). - Pilih Third party API sebagai Source type.
- Pilih Duo Auth sebagai Jenis log.
- Klik Berikutnya.
- Tentukan nilai untuk parameter input berikut:
- Nama pengguna: Masukkan kunci Integrasi dari Duo.
- Secret: Masukkan Secret key dari Duo.
- Nama Host API: Masukkan nama host API Anda (misalnya,
api-XXXXXXXX.duosecurity.com). - Namespace aset: Opsional. Namespace aset.
- Label penyerapan: Opsional. Label yang akan diterapkan ke peristiwa dari feed ini.
- Klik Berikutnya.
- Tinjau konfigurasi feed baru Anda di layar Selesaikan, lalu klik Kirim.
Opsi 2: Lakukan penyerapan log autentikasi Duo menggunakan Google Cloud Storage
Kumpulkan kredensial Duo Admin API
- Login ke Panel Admin Duo.
- Buka Applications > Application Catalog.
- Cari Admin API di katalog aplikasi.
- Klik + Tambahkan untuk menambahkan aplikasi Admin API.
- Salin dan simpan nilai berikut:
- Kunci integrasi (ikey)
- Kunci rahasia (skey)
- Nama host API (misalnya,
api-XXXXXXXX.duosecurity.com)
- Di Izin, aktifkan Berikan izin untuk membaca log.
- Klik Save Changes.
Membuat bucket Google Cloud Storage
- Buka Google Cloud Console.
- Pilih project Anda atau buat project baru.
- 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, duo-auth-logs)Location type Pilih berdasarkan kebutuhan Anda (Region, Dual-region, Multi-region) Lokasi Pilih lokasi (misalnya, us-central1)Kelas penyimpanan Standar (direkomendasikan untuk log yang sering diakses) Access control Seragam (direkomendasikan) Alat perlindungan Opsional: Aktifkan pembuatan versi objek atau kebijakan retensi Klik Buat.
Buat akun layanan untuk Cloud Run Function
Fungsi Cloud Run memerlukan akun layanan dengan izin untuk menulis ke bucket GCS.
Membuat akun layanan
- Di GCP Console, buka IAM & Admin > Service Accounts.
- Klik Create Service Account.
- Berikan detail konfigurasi berikut:
- Nama akun layanan: Masukkan
duo-auth-collector-sa. - Deskripsi akun layanan: Masukkan
Service account for Cloud Run function to collect Duo authentication logs.
- Nama akun layanan: Masukkan
- Klik Create and Continue.
- Di bagian Berikan akun layanan ini akses ke project, tambahkan peran berikut:
- Klik Pilih peran.
- Telusuri dan pilih Storage Object Admin.
- Klik + Add another role.
- Telusuri dan pilih Cloud Run Invoker.
- Klik + Add another role.
- Telusuri dan pilih Cloud Functions Invoker.
- Klik Lanjutkan.
- Klik Selesai.
Peran ini diperlukan untuk:
- Storage Object Admin: Menulis log ke bucket GCS dan mengelola file status
- Cloud Run Invoker: Mengizinkan Pub/Sub memanggil fungsi
- Cloud Functions Invoker: Mengizinkan pemanggilan fungsi
Memberikan izin IAM pada bucket GCS
Beri akun layanan izin tulis di bucket GCS:
- Buka Cloud Storage > Buckets.
- Klik nama bucket Anda.
- Buka tab Izin.
- Klik Grant access.
- Berikan detail konfigurasi berikut:
- Tambahkan prinsipal: Masukkan email akun layanan (misalnya,
duo-auth-collector-sa@PROJECT_ID.iam.gserviceaccount.com). - Tetapkan peran: Pilih Storage Object Admin.
- Tambahkan prinsipal: Masukkan email akun layanan (misalnya,
- Klik Simpan.
Membuat topik Pub/Sub
Buat topik Pub/Sub yang akan dipublikasikan oleh Cloud Scheduler dan akan dilanggan oleh fungsi Cloud Run.
- Di GCP Console, buka Pub/Sub > Topics.
- Klik Create topic.
- Berikan detail konfigurasi berikut:
- ID Topik: Masukkan
duo-auth-trigger. - Biarkan setelan lainnya tetap default.
- ID Topik: Masukkan
- Klik Buat.
Membuat fungsi Cloud Run untuk mengumpulkan log
Fungsi Cloud Run dipicu oleh pesan Pub/Sub dari Cloud Scheduler untuk mengambil log dari Duo Admin API dan menuliskannya ke GCS.
- Di GCP Console, buka Cloud Run.
- Klik Create service.
- Pilih Function (gunakan editor inline untuk membuat fungsi).
Di bagian Konfigurasi, berikan detail konfigurasi berikut:
Setelan Nilai Nama layanan duo-auth-collectorWilayah Pilih region yang cocok dengan bucket GCS Anda (misalnya, us-central1)Runtime Pilih Python 3.12 atau yang lebih baru Di bagian Pemicu (opsional):
- Klik + Tambahkan pemicu.
- Pilih Cloud Pub/Sub.
- Di Select a Cloud Pub/Sub topic, pilih topik
duo-auth-trigger. - Klik Simpan.
Di bagian Authentication:
- Pilih Wajibkan autentikasi.
- Periksa Identity and Access Management (IAM).
Scroll ke bawah dan luaskan Containers, Networking, Security.
Buka tab Security:
- Akun layanan: Pilih akun layanan
duo-auth-collector-sa.
- Akun layanan: Pilih akun layanan
Buka tab Containers:
- Klik Variables & Secrets.
- Klik + Tambahkan variabel untuk setiap variabel lingkungan:
Nama Variabel Nilai Contoh GCS_BUCKETduo-auth-logsGCS_PREFIXduo/auth/STATE_KEYduo/auth/state.jsonDUO_IKEYDIXYZ...DUO_SKEY****************DUO_API_HOSTNAMEapi-XXXXXXXX.duosecurity.comLIMIT500Scroll ke bawah di tab Variables & Secrets ke Requests:
- Waktu tunggu permintaan: Masukkan
600detik (10 menit).
- Waktu tunggu permintaan: Masukkan
Buka tab Setelan di Penampung:
- Di bagian Materi:
- Memori: Pilih 512 MiB atau yang lebih tinggi.
- CPU: Pilih 1.
- Klik Selesai.
- Di bagian Materi:
Scroll ke Lingkungan eksekusi:
- Pilih Default (direkomendasikan).
Di bagian Penskalaan revisi:
- Jumlah minimum instance: Masukkan
0. - Jumlah maksimum instance: Masukkan
100(atau sesuaikan berdasarkan perkiraan beban).
- Jumlah minimum instance: Masukkan
Klik Buat.
Tunggu hingga layanan dibuat (1-2 menit).
Setelah layanan dibuat, editor kode inline akan terbuka secara otomatis.
Menambahkan kode fungsi
- Masukkan main di Function entry point
Di editor kode inline, buat dua file:
- File pertama: main.py:
#!/usr/bin/env python3 # Cloud Run Function: Pull Duo Admin API v2 Authentication Logs to GCS (raw JSON pages) # Notes: # - Duo v2 requires mintime/maxtime in *milliseconds* (13-digit epoch). # - Pagination via metadata.next_offset ("<millis>,<txid>"). # - We save state (mintime_ms) in ms to resume next run without gaps. import functions_framework from google.cloud import storage import os import json import time import hmac import hashlib import base64 import email.utils import urllib.parse from urllib.request import Request, urlopen from urllib.error import HTTPError, URLError DUO_IKEY = os.environ["DUO_IKEY"] DUO_SKEY = os.environ["DUO_SKEY"] DUO_API_HOSTNAME = os.environ["DUO_API_HOSTNAME"].strip() GCS_BUCKET = os.environ["GCS_BUCKET"] GCS_PREFIX = os.environ.get("GCS_PREFIX", "duo/auth/").strip("/") STATE_KEY = os.environ.get("STATE_KEY", "duo/auth/state.json") LIMIT = min(int(os.environ.get("LIMIT", "500")), 1000) # default 500, max 1000 storage_client = storage.Client() def _canon_params(params: dict) -> str: parts = [] for k in sorted(params.keys()): v = params[k] if v is None: continue parts.append(f"{urllib.parse.quote(str(k), '~')}={urllib.parse.quote(str(v), '~')}") return "&".join(parts) def _sign(method: str, host: str, path: str, params: dict) -> dict: now = email.utils.formatdate() canon = "\n".join([ now, method.upper(), host.lower(), path, _canon_params(params) ]) sig = hmac.new( DUO_SKEY.encode("utf-8"), canon.encode("utf-8"), hashlib.sha1 ).hexdigest() auth = base64.b64encode(f"{DUO_IKEY}:{sig}".encode()).decode() return { "Date": now, "Authorization": f"Basic {auth}" } def _http(method: str, path: str, params: dict, timeout: int = 60, max_retries: int = 5) -> dict: host = DUO_API_HOSTNAME assert host.startswith("api-") and host.endswith(".duosecurity.com"), \ "DUO_API_HOSTNAME must be like api-XXXXXXXX.duosecurity.com" qs = _canon_params(params) url = f"https://{host}{path}" + (f"?{qs}" if qs else "") attempt, backoff = 0, 1.0 while True: req = Request(url, method=method.upper()) req.add_header("Accept", "application/json") for k, v in _sign(method, host, path, params).items(): req.add_header(k, v) try: with urlopen(req, timeout=timeout) as r: return json.loads(r.read().decode("utf-8")) except HTTPError as e: if (e.code == 429 or 500 <= e.code <= 599) and attempt < max_retries: time.sleep(backoff) attempt += 1 backoff *= 2 continue raise except URLError: if attempt < max_retries: time.sleep(backoff) attempt += 1 backoff *= 2 continue raise def _read_state_ms() -> int | None: try: bucket = storage_client.bucket(GCS_BUCKET) blob = bucket.blob(STATE_KEY) if blob.exists(): state_data = blob.download_as_text() val = json.loads(state_data).get("mintime") if val is None: return None # Backward safety: if seconds were stored, convert to ms return int(val) * 1000 if len(str(int(val))) <= 10 else int(val) except Exception: return None def _write_state_ms(mintime_ms: int): bucket = storage_client.bucket(GCS_BUCKET) blob = bucket.blob(STATE_KEY) body = json.dumps({"mintime": int(mintime_ms)}).encode("utf-8") blob.upload_from_string(body, content_type="application/json") def _write_page(payload: dict, when_epoch_s: int, page: int) -> str: bucket = storage_client.bucket(GCS_BUCKET) key = f"{GCS_PREFIX}/{time.strftime('%Y/%m/%d', time.gmtime(when_epoch_s))}/duo-auth-{page:05d}.json" blob = bucket.blob(key) blob.upload_from_string( json.dumps(payload, separators=(",", ":")).encode("utf-8"), content_type="application/json" ) return key def fetch_and_store(): now_s = int(time.time()) # Duo recommends a ~2-minute delay buffer; use maxtime = now - 120 seconds (in ms) maxtime_ms = (now_s - 120) * 1000 mintime_ms = _read_state_ms() or (maxtime_ms - 3600 * 1000) # 1 hour on first run page = 0 total = 0 next_offset = None while True: params = { "mintime": mintime_ms, "maxtime": maxtime_ms, "limit": LIMIT } if next_offset: params["next_offset"] = next_offset data = _http("GET", "/admin/v2/logs/authentication", params) _write_page(data, maxtime_ms // 1000, page) page += 1 resp = data.get("response") items = resp if isinstance(resp, list) else [] total += len(items) meta = data.get("metadata") or {} next_offset = meta.get("next_offset") if not next_offset: break # Advance window to maxtime_ms for next run _write_state_ms(maxtime_ms) return { "ok": True, "pages": page, "events": total, "next_mintime_ms": maxtime_ms } @functions_framework.cloud_event def main(cloud_event): """ Cloud Run function triggered by Pub/Sub to fetch Duo authentication logs and write to GCS. Args: cloud_event: CloudEvent object containing Pub/Sub message """ try: result = fetch_and_store() print(f"Successfully processed {result['events']} events in {result['pages']} pages") print(f"Next mintime_ms: {result['next_mintime_ms']}") except Exception as e: print(f"Error processing logs: {str(e)}") raise- File kedua: requirements.txt:
functions-framework==3.* google-cloud-storage==2.*Klik Deploy untuk menyimpan dan men-deploy fungsi.
Tunggu hingga deployment selesai (2-3 menit).
Buat tugas Cloud Scheduler
Cloud Scheduler memublikasikan pesan ke topik Pub/Sub secara berkala, sehingga memicu fungsi Cloud Run.
- Di GCP Console, buka Cloud Scheduler.
- Klik Create Job.
Berikan detail konfigurasi berikut:
Setelan Nilai Nama duo-auth-collector-hourlyWilayah 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 Pilih topik duo-auth-triggerIsi pesan {}(objek JSON kosong)Klik Buat.
Opsi frekuensi jadwal
Pilih frekuensi berdasarkan volume log dan persyaratan latensi:
Frekuensi Ekspresi Cron Kasus Penggunaan Setiap 5 menit */5 * * * *Volume tinggi, latensi rendah Setiap 15 menit */15 * * * *Volume sedang Setiap jam 0 * * * *Standar (direkomendasikan) Setiap 6 jam 0 */6 * * *Volume rendah, pemrosesan batch Harian 0 0 * * *Pengumpulan data historis
Menguji tugas penjadwal
- Di konsol Cloud Scheduler, temukan tugas Anda.
- Klik Jalankan paksa untuk memicu secara manual.
- Tunggu beberapa detik, lalu buka Cloud Run > Services > duo-auth-collector > Logs.
- Pastikan fungsi berhasil dieksekusi.
- Periksa bucket GCS untuk mengonfirmasi bahwa log telah ditulis.
Mengambil akun layanan Google SecOps
Google SecOps menggunakan akun layanan unik untuk membaca data dari bucket GCS Anda. Anda harus memberi akun layanan ini akses ke bucket Anda.
Dapatkan email akun layanan
- Buka Setelan SIEM > Feed.
- Klik Tambahkan Feed Baru.
- Klik Konfigurasi satu feed.
- Di kolom Nama feed, masukkan nama untuk feed (misalnya,
Duo Authentication Logs). - Pilih Google Cloud Storage V2 sebagai Source type.
- Pilih Duo Auth sebagai Jenis log.
Klik Get Service Account. Email akun layanan yang unik akan ditampilkan, misalnya:
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.comSalin alamat email ini untuk digunakan di langkah berikutnya.
Memberikan izin IAM ke akun layanan Google SecOps
Akun layanan Google SecOps memerlukan peran Storage Object Viewer di bucket GCS Anda.
- Buka Cloud Storage > Buckets.
- Klik nama bucket Anda.
- Buka tab Izin.
- Klik Grant access.
- Berikan detail konfigurasi berikut:
- Add principals: Tempel email akun layanan Google SecOps.
- Tetapkan peran: Pilih Storage Object Viewer.
Klik Simpan.
Mengonfigurasi feed di Google SecOps untuk menyerap log autentikasi Duo
- Buka Setelan SIEM > Feed.
- Klik Tambahkan Feed Baru.
- Klik Konfigurasi satu feed.
- Di kolom Nama feed, masukkan nama untuk feed (misalnya,
Duo Authentication Logs). - Pilih Google Cloud Storage V2 sebagai Source type.
- Pilih Duo Auth sebagai Jenis log.
- Klik Berikutnya.
Tentukan nilai untuk parameter input berikut:
URL bucket penyimpanan: Masukkan URI bucket GCS dengan jalur awalan:
gs://duo-auth-logs/duo/auth/Ganti:
duo-auth-logs: Nama bucket GCS Anda.duo/auth/: Awalan/jalur folder opsional tempat log disimpan (biarkan kosong untuk root).
Contoh:
- Bucket root:
gs://company-logs/ - Dengan awalan:
gs://company-logs/duo-logs/ - Dengan subfolder:
gs://company-logs/duo/auth/
- Bucket root:
Opsi penghapusan sumber: Pilih opsi penghapusan sesuai preferensi Anda:
- Jangan pernah: Tidak pernah menghapus file apa pun setelah transfer (direkomendasikan untuk pengujian).
- Hapus file yang ditransfer: Menghapus file setelah transfer berhasil.
Hapus file yang ditransfer dan direktori kosong: Menghapus file dan direktori kosong setelah transfer berhasil.
Usia File Maksimum: Menyertakan file yang diubah dalam beberapa hari terakhir. Defaultnya adalah 180 hari.
Namespace aset: Namespace aset.
Label penyerapan: Label yang akan diterapkan ke peristiwa dari feed ini.
Klik Berikutnya.
Tinjau konfigurasi feed baru Anda di layar Selesaikan, lalu klik Kirim.
Tabel pemetaan UDM
| Kolom Log | Pemetaan UDM | Logika |
|---|---|---|
| access_device.browser | target.resource.attribute.labels.value | Jika access_device.browser ada, nilainya dipetakan ke UDM. |
| access_device.hostname | principal.hostname | Jika access_device.hostname ada dan tidak kosong, nilainya dipetakan ke UDM. Jika kosong dan event_type adalah USER_CREATION, event_type diubah menjadi USER_UNCATEGORIZED. Jika access_device.hostname kosong dan kolom hostname ada, nilai hostname akan digunakan. |
| access_device.ip | principal.ip | Jika access_device.ip ada dan merupakan alamat IPv4 yang valid, nilainya akan dipetakan ke UDM. Jika bukan alamat IPv4 yang valid, alamat tersebut akan ditambahkan sebagai nilai string ke additional.fields dengan kunci access_device.ip. |
| access_device.location.city | principal.location.city | Jika ada, nilai dipetakan ke UDM. |
| access_device.location.country | principal.location.country_or_region | Jika ada, nilai dipetakan ke UDM. |
| access_device.location.state | principal.location.state | Jika ada, nilai dipetakan ke UDM. |
| access_device.os | principal.platform | Jika ada, nilai akan diterjemahkan ke nilai UDM yang sesuai (MAC, WINDOWS, LINUX). |
| access_device.os_version | principal.platform_version | Jika ada, nilai dipetakan ke UDM. |
| application.key | target.resource.id | Jika ada, nilai dipetakan ke UDM. |
| application.name | target.application | Jika ada, nilai dipetakan ke UDM. |
| auth_device.ip | target.ip | Jika ada dan bukan "None", nilai akan dipetakan ke UDM. |
| auth_device.location.city | target.location.city | Jika ada, nilai dipetakan ke UDM. |
| auth_device.location.country | target.location.country_or_region | Jika ada, nilai dipetakan ke UDM. |
| auth_device.location.state | target.location.state | Jika ada, nilai dipetakan ke UDM. |
| auth_device.name | target.hostname ATAU target.user.phone_numbers | Jika auth_device.name ada dan berupa nomor telepon (setelah normalisasi), nomor tersebut akan ditambahkan ke target.user.phone_numbers. Jika tidak, nilai ini dipetakan ke target.hostname. |
| client_ip | target.ip | Jika ada dan bukan "None", nilai akan dipetakan ke UDM. |
| client_section | target.resource.attribute.labels.value | Jika client_section ada, nilainya dipetakan ke UDM dengan kunci client_section. |
| dn | target.user.userid | Jika dn ada dan user.name serta username tidak ada, userid akan diekstrak dari kolom dn menggunakan grok dan dipetakan ke UDM. event_type ditetapkan ke USER_LOGIN. |
| event_type | metadata.product_event_type AND metadata.event_type | Nilai dipetakan ke metadata.product_event_type. Kolom ini juga digunakan untuk menentukan metadata.event_type: "authentication" menjadi USER_LOGIN, "enrollment" menjadi USER_CREATION, dan jika kosong atau bukan salah satu dari keduanya, kolom ini akan menjadi GENERIC_EVENT. |
| faktor | extensions.auth.mechanism DAN extensions.auth.auth_details | Nilai diterjemahkan ke nilai auth.mechanism UDM yang sesuai (HARDWARE_KEY, REMOTE_INTERACTIVE, LOCAL, OTP). Nilai asli juga dipetakan ke extensions.auth.auth_details. |
| hostname | principal.hostname | Jika ada dan access_device.hostname kosong, nilai akan dipetakan ke UDM. |
| log_format | target.resource.attribute.labels.value | Jika log_format ada, nilainya dipetakan ke UDM dengan kunci log_format. |
| loglevel._classuuid_ | target.resource.attribute.labels.value | Jika loglevel._classuuid_ ada, nilainya dipetakan ke UDM dengan kunci class_uuid. |
| log_level.name | target.resource.attribute.labels.value AND security_result.severity | Jika log_level.name ada, nilainya dipetakan ke UDM dengan nama kunci. Jika nilainya adalah "info", security_result.severity disetel ke INFORMATIONAL. |
| log_logger.unpersistable | target.resource.attribute.labels.value | Jika log_logger.unpersistable ada, nilainya dipetakan ke UDM dengan kunci unpersistable. |
| log_namespace | target.resource.attribute.labels.value | Jika log_namespace ada, nilainya dipetakan ke UDM dengan kunci log_namespace. |
| log_source | target.resource.attribute.labels.value | Jika log_source ada, nilainya dipetakan ke UDM dengan kunci log_source. |
| msg | security_result.summary | Jika ada dan alasan kosong, nilai dipetakan ke UDM. |
| alasan | security_result.summary | Jika ada, nilai dipetakan ke UDM. |
| hasil | security_result.action_details AND security_result.action | Jika ada, nilai dipetakan ke security_result.action_details. "success" atau "SUCCESS" diterjemahkan menjadi security_result.action ALLOW, jika tidak, BLOCK. |
| server_section | target.resource.attribute.labels.value | Jika server_section ada, nilainya dipetakan ke UDM dengan kunci server_section. |
| server_section_ikey | target.resource.attribute.labels.value | Jika server_section_ikey ada, nilainya dipetakan ke UDM dengan kunci server_section_ikey. |
| status | security_result.action_details AND security_result.action | Jika ada, nilai dipetakan ke security_result.action_details. "Izinkan" diterjemahkan menjadi security_result.action ALLOW, "Tolak" diterjemahkan menjadi BLOCK. |
| timestamp | metadata.event_timestamp AND event.timestamp | Nilai dikonversi menjadi stempel waktu dan dipetakan ke metadata.event_timestamp dan event.timestamp. |
| txid | metadata.product_log_id AND network.session_id | Nilai dipetakan ke metadata.product_log_id dan network.session_id. |
| user.groups | target.user.group_identifiers | Semua nilai dalam array ditambahkan ke target.user.group_identifiers. |
| user.key | target.user.product_object_id | Jika ada, nilai dipetakan ke UDM. |
| user.name | target.user.userid | Jika ada, nilai dipetakan ke UDM. |
| nama pengguna | target.user.userid | Jika ada dan user.name tidak ada, nilai akan dipetakan ke UDM. event_type ditetapkan ke USER_LOGIN. |
| (Logika Parser) | metadata.vendor_name | Selalu ditetapkan ke "DUO_SECURITY". |
| (Logika Parser) | metadata.product_name | Selalu ditetapkan ke "MULTI-FACTOR_AUTHENTICATION". |
| (Logika Parser) | metadata.log_type | Diambil dari kolom log_type tingkat teratas log mentah. |
| (Logika Parser) | extensions.auth.type | Selalu disetel ke "SSO". |
Perlu bantuan lebih lanjut? Dapatkan jawaban dari anggota Komunitas dan profesional Google SecOps.