Collect Windows Hyper-V logs
This document explains how to ingest Windows Hyper-V logs to Google Security Operations using Bindplane.
Windows Hyper-V is a Microsoft hypervisor that generates VM lifecycle, network, storage, and security event logs. The Bindplane agent collects exported Hyper-V event log files directly from the local file system.
Before you begin
Make sure you have the following prerequisites:
- A Google SecOps instance
- Windows Server 2016 or later with
observiq-otel-collectorservice support - If running behind a proxy, ensure firewall ports are open per the Bindplane agent requirements
- Privileged access to the Windows Hyper-V host with administrator permissions
Get Google SecOps ingestion authentication file
- Sign in to the Google SecOps console.
- Go to SIEM Settings > Collection Agents.
Download the Ingestion Authentication File. Save the file securely on the system where Bindplane will be installed.
Get Google SecOps customer ID
- Sign in to the Google SecOps console.
- Go to SIEM Settings > Profile.
Copy and save the Customer ID from the Organization Details section.
Install the Bindplane agent
Install the Bindplane agent on your Windows operating system according to the following instructions.
Windows installation
- Open Command Prompt or PowerShell as an administrator.
Run the following command:
msiexec /i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" /quietWait for the installation to complete.
Verify the installation by running:
sc query observiq-otel-collector
The service should show as RUNNING.
Additional installation resources
For additional installation options and troubleshooting, see Bindplane agent installation guide.
Configure Bindplane agent to ingest logs and send to Google SecOps
Locate the configuration file
Windows:
notepad "C:\Program Files\observIQ OpenTelemetry Collector\config.yaml"
Edit the configuration file
Replace the entire contents of
config.yamlwith the following configuration:receivers: filelog: include: - C:\HyperVLogs\*.evtx start_at: beginning exporters: chronicle/windows_hyperv: compression: gzip creds_file_path: 'C:\Program Files\observIQ OpenTelemetry Collector\ingestion-auth.json' customer_id: '<customer_id>' endpoint: malachiteingestion-pa.googleapis.com log_type: WINDOWS_HYPERV raw_log_field: body ingestion_labels: env: production service: pipelines: logs/hyperv_to_chronicle: receivers: - filelog exporters: - chronicle/windows_hyperv
Configuration parameters
Replace the following placeholders:
Receiver configuration:
filelog: The receiver type for collecting log files from diskinclude: List of file paths to monitor. Set this to the location where you export Hyper-V event logs (for example,C:\HyperVLogs\*.evtx)start_at: Set tobeginningto read existing logs orendto only read new entries
Exporter configuration:
windows_hyperv: Descriptive name for the exportercreds_file_path: Full path to ingestion authentication file:- Windows:
C:\Program Files\observIQ OpenTelemetry Collector\ingestion-auth.json
- Windows:
<customer_id>: Customer ID from the previous stependpoint: Regional endpoint URL:- US:
malachiteingestion-pa.googleapis.com - Europe:
europe-malachiteingestion-pa.googleapis.com - Asia:
asia-southeast1-malachiteingestion-pa.googleapis.com - See Regional Endpoints for complete list
- US:
WINDOWS_HYPERV: Log type exactly as it appears in Chronicleingestion_labels: Optional labels in YAML format (for example,env: production)
Pipeline configuration:
hyperv_to_chronicle: Descriptive name for the pipeline
Save the configuration file
- After editing, save the file:
- Windows: Click File > Save
Restart the Bindplane agent to apply the changes
To restart the Bindplane agent in Windows:
Choose one of the following options:
- Command Prompt or PowerShell as administrator:
net stop observiq-otel-collector && net start observiq-otel-collector- Services console:
- Press
Win+R, typeservices.msc, and press Enter. - Locate observIQ OpenTelemetry Collector.
- Right-click and select Restart.
- Press
Verify the service is running:
sc query observiq-otel-collectorCheck logs for errors:
type "C:\Program Files\observIQ OpenTelemetry Collector\log\collector.log"
Configure Windows Hyper-V log export
Windows Hyper-V logs are stored as Windows Event Log entries. You need to export these logs to files on disk so the Bindplane agent can collect them.
Create a directory to store the exported log files:
mkdir C:\HyperVLogsExport Hyper-V event logs using
wevtutil:wevtutil epl Microsoft-Windows-Hyper-V-VMMS-Admin C:\HyperVLogs\hyperv-vmms-admin.evtx wevtutil epl Microsoft-Windows-Hyper-V-Worker-Admin C:\HyperVLogs\hyperv-worker-admin.evtxYou can export additional Hyper-V event channels as needed. Available channels include:
Microsoft-Windows-Hyper-V-VMMS-Admin(Virtual Machine Management Service)Microsoft-Windows-Hyper-V-Worker-Admin(VM Worker processes)Microsoft-Windows-Hyper-V-Hypervisor-Admin(Hypervisor events)Microsoft-Windows-Hyper-V-Config-Admin(Configuration events)
(Optional) Schedule regular exports using PowerShell:
$action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument '/c wevtutil epl Microsoft-Windows-Hyper-V-VMMS-Admin C:\HyperVLogs\hyperv-vmms-admin.evtx /ow:true && wevtutil epl Microsoft-Windows-Hyper-V-Worker-Admin C:\HyperVLogs\hyperv-worker-admin.evtx /ow:true' $trigger = New-ScheduledTaskTrigger -RepetitionInterval (New-TimeSpan -Hours 1) -Once -At (Get-Date) Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "ExportHyperVLogs" -Description "Export Hyper-V logs for Bindplane agent"Verify that the exported log files are being created at `C:\HyperVLogs`.
Ensure the Bindplane agent
includepath inconfig.yamlmatches the export directory.
UDM mapping table
| Log Field | UDM Mapping | Logic |
|---|---|---|
| channel, event_data.data, event_id.id, event_id.qualifiers, keywords, task, SeverityValue, OpcodeValue, EventID, ProviderGuid, ActivityId, Version, RecordNumber, ProcessID, ThreadID, Channel, AccountName, UserID, AccountType, Opcode, SourceModuleName, SourceModuleType | additional.fields | Merged with labels created from these fields |
| system_time, EventReceivedTime | metadata.collected_timestamp | Parsed from system_time with formats, or from EventReceivedTime as UNIX or UNIX_MS |
| Message | metadata.description | Value copied directly |
| EventTime, EventReceivedTime | metadata.event_timestamp | Parsed from EventTime as UNIX or UNIX_MS, or from EventReceivedTime as UNIX or UNIX_MS |
| metadata.event_type | Set to "PROCESS_LAUNCH" if has_principal and has_target_process, else "USER_LOGIN" if has_principal and has_target and not has_target_process, else "STATUS_UPDATE" if has_principal and not has_target, else "USER_RESOURCE_ACCESS" if has_target, else "GENERIC_EVENT" | |
| provider.event_source | metadata.product_event_type | Value copied directly |
| record_id, RecordNumber | metadata.product_log_id | Converted to string from record_id if not empty, or from RecordNumber if not empty |
| provider.name, SourceName | metadata.product_name | Value from provider.name if not empty, else SourceName if not empty, else "Microsoft-Windows-Hyper-V" |
| Version | metadata.product_version | Converted to string |
| message | network.session_duration.nanos | Extracted from message using grok pattern, converted to integer |
| Domain | principal.administrative_domain | Value copied directly |
| computer | principal.asset.hostname | Value copied directly |
| computer, Hostname | principal.hostname | Value from computer if not empty, then from Hostname if not empty |
| AccountName | principal.user.role_description | Value copied directly |
| AccountType | principal.user.role_name | Value copied directly |
| event_data.name | principal.user.user_display_name | Value copied directly |
| security.user_id, UserID | principal.user.userid | Value from security.user_id if not empty, then from UserID if not empty |
| message | security_result.description | Extracted from message using grok pattern |
| message, ActivityId | security_result.detection_fields | Merged with label from nt_status extracted from message using grok, and from ActivityId |
| level, Severity | security_result.severity | Set based on level value (1-3 INFORMATIONAL, 4 ERROR, 5 CRITICAL, else UNKNOWN_SEVERITY), or based on Severity (INFO INFORMATIONAL, WARN MEDIUM, ERROR ERROR) |
| EventType | security_result.severity_details | Value copied directly |
| execution.process_id, ProcessID | target.process.pid | Converted to string from execution.process_id if not empty, or from ProcessID if not empty |
| execution.thread_id, ThreadID | target.process.product_specific_process_id | Set to "ThreadID: |
| provider.guid, ProviderGuid | target.resource.id | Value from provider.guid after removing { }, or from ProviderGuid after removing { } |
| message | target.resource.product_object_id | Extracted from message using grok pattern |
| provider.guid | target.resource.type | Set to "Hyper-V VmSwitch" if not empty |
Need more help? Get answers from Community members and Google SecOps professionals.