Collect PowerShell logs
This document explains how to collect PowerShell logs to Google Security Operations by using Bindplane. The parser transforms raw Microsoft PowerShell logs into a unified data model (UDM). It first extracts fields from the raw log message, normalizes them into UDM fields, and then enriches the data with additional context based on specific event IDs, ultimately creating a structured UDM event for security analysis.
Before you begin
- Ensure that you have a Google SecOps instance.
- Ensure that you have a Windows 2016 or later.
- If running behind a proxy, ensure firewall ports are open.
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 IDfrom the Organization Detailssection.
Install the Bindplane agent on Windows
- Open the Command Promptor PowerShellas an administrator.
-
Run the following command:
msiexec / i "https://github.com/observIQ/bindplane-agent/releases/latest/download/observiq-otel-collector.msi" / quiet
Additional installation resources
- For additional installation options, consult this installation guide .
Configure the Bindplane agent to ingest Syslog and send to Google SecOps
- Before configuring the YAML file, stop the
observIQ Distro for Open Telemetry Collector
Servicein the Services Panel. -
Access the configuration file:
- Locate the
config.yaml
file. Typically, it's in the/etc/bindplane-agent/
directory on Linux or in the installation directory on Windows. - Open the file using a text editor (for example,
nano
,vi
, or Notepad).
- Locate the
-
Edit the
config.yaml
file as follows:receivers : windowseventlog/powershell : channel : Microsoft-Windows-PowerShell/Operational max_reads : 100 poll_interval : 5s raw : true start_at : end processors : batch : exporters : chronicle/powershell : endpoint : malachiteingestion-pa.googleapis.com # Adjust the path to the credentials file you downloaded in Step 1 creds : '/path/to/ingestion-authentication-file.json' log_type : 'POWERSHELL' override_log_type : false raw_log_field : body customer_id : '<customer_id>' service : pipelines : logs/winpowershell : receivers : - windowseventlog/powershell processors : [ batch ] exporters : [ chronicle/powershell ]
-
Replace
<customer_id>
with the actual customer ID. -
Update
/path/to/ingestion-authentication-file.json
to the path where the authentication file was saved in the Get Google SecOps ingestion authentication file section. -
After saving the
config.yaml
file, starttheobservIQ Distro for Open Telemetry Collector
Service.
Restart the Bindplane agent to apply the changes
-
To restart the Bindplane agent in Windows, you can either use the Servicesconsole or enter the following command:
net stop BindPlaneAgent && net start BindPlaneAgent
UDM Mapping Table
Log Field | UDM Mapping | Logic |
---|---|---|
AccountName
|
principal.user.userid | Directly mapped from the AccountName
field in the raw log. |
ActivityID
|
security_result.detection_fields[0].value | Directly mapped from the ActivityID
field in the raw log. The curly braces are removed. |
Channel
|
Not mapped to the IDM object. | |
collection_time.nanos
|
Not mapped to the IDM object. | |
collection_time.seconds
|
Not mapped to the IDM object. | |
Command
|
Not mapped to the IDM object. | |
CommandLine
|
Not mapped to the IDM object. | |
Computer
|
principal.hostname | Directly mapped from the Computer
field in the raw log if present. |
ContextInfo
|
Not mapped to the IDM object. | |
ContextInfo_Command Name
|
security_result.detection_fields[0].value | Directly mapped from the ContextInfo_Command Name
field in the raw log if present. |
ContextInfo_Command Type
|
security_result.detection_fields[1].value | Directly mapped from the ContextInfo_Command Type
field in the raw log if present. |
ContextInfo_Host Application
|
target.process.command_line | Directly mapped from the ContextInfo_Host Application
field in the raw log if powershell.Host Application
is not present. |
ContextInfo_Host ID
|
target.asset.asset_id | Directly mapped from the ContextInfo_Host ID
field in the raw log if powershell.Host ID
is not present. The value is prefixed with Host ID:
. |
ContextInfo_Host Name
|
target.hostname | Directly mapped from the ContextInfo_Host Name
field in the raw log if powershell.Host Name
is not present. |
ContextInfo_Script Name
|
target.process.file.full_path | Directly mapped from the ContextInfo_Script Name
field in the raw log if script_name
is not present. |
ContextInfo_Sequence Number
|
security_result.detection_fields[2].value | Directly mapped from the ContextInfo_Sequence Number
field in the raw log if present. Converted to a string. |
ContextInfo_Severity
|
Not mapped to the IDM object. | |
create_time.nanos
|
Not mapped to the IDM object. | |
create_time.seconds
|
Not mapped to the IDM object. | |
customer_id
|
Not mapped to the IDM object. | |
data
|
Not mapped to the IDM object. | |
Data
|
security_result.detection_fields[0].value | Directly mapped from the Data
field in the raw log if present. |
Data_1
|
security_result.detection_fields[1].value | Directly mapped from the Data_1
field in the raw log if present. |
Data_2
|
security_result.detection_fields[2].value | Directly mapped from the Data_2
field in the raw log if present. |
Domain
|
principal.administrative_domain | Directly mapped from the Domain
field in the raw log. |
entries
|
Not mapped to the IDM object. | |
ERROR_EVT_UNRESOLVED
|
Not mapped to the IDM object. | |
EventCategory
|
Not mapped to the IDM object. | |
EventData
|
Not mapped to the IDM object. | |
EventID
|
metadata.product_event_type, security_result.rule_name | Directly mapped from the EventID
field in the raw log. The value is prefixed with EventID:
for the security_result.rule_name
field. |
EventLevel
|
Not mapped to the IDM object. | |
EventLevelName
|
security_result.severity | Mapped based on the value of EventLevelName
:- Information
maps to INFORMATIONAL
.- Verbose
maps to LOW
. |
EventLog
|
Not mapped to the IDM object. | |
EventReceivedTime
|
Not mapped to the IDM object. | |
EventType
|
Not mapped to the IDM object. | |
EventTime
|
metadata.event_timestamp | Used to extract the timestamp if present. |
ExecutionProcessID
|
principal.process.pid | Directly mapped from the ExecutionProcessID
field in the raw log if present and not empty or 0. Converted to a string. |
ExecutionThreadID
|
security_result.detection_fields[2].value | Directly mapped from the ExecutionThreadID
field in the raw log if present and not empty or 0. Converted to a string. |
File
|
target.process.file.full_path | Directly mapped from the File
field in the raw log if present. |
Host Application
|
Not mapped to the IDM object. | |
HostApplication
|
Not mapped to the IDM object. | |
Hostname
|
principal.hostname | Directly mapped from the Hostname
field in the raw log. |
id
|
Not mapped to the IDM object. | |
Keywords
|
Not mapped to the IDM object. | |
log_type
|
metadata.log_type | Directly mapped from the log_type
field in the raw log. |
Machine
|
principal.asset.asset_id, principal.asset.platform_software.platform_version | The Machine
field is parsed to extract the machine ID and platform information. The machine ID is prefixed with Machine ID:
. The platform is mapped to the UDM enum based on the value:- win
maps to WINDOWS
.- mac
maps to MAC
.- lin
maps to LINUX
.- Other values map to UNKNOWN_PLATFORM
. |
ManagementGroupName
|
additional.fields[0].value.string_value | Directly mapped from the ManagementGroupName
field in the raw log if present. |
Message.EventTime
|
metadata.event_timestamp | Used to extract the timestamp if present. Converted to a string. |
Message.Message
|
security_result.description | Directly mapped from the Message.Message
field in the raw log if EventID
is in [ 403
, 4103
, 4104
] and message_message_not_found
. Carriage returns and tabs are replaced with commas. |
Message
|
security_result.description | Directly mapped from the Message
field in the raw log if present. |
MessageNumber
|
Not mapped to the IDM object. | |
MessageSourceAddress
|
principal.ip | Directly mapped from the MessageSourceAddress
field in the raw log if present. |
MessageTotal
|
Not mapped to the IDM object. | |
MG
|
Not mapped to the IDM object. | |
Opcode
|
metadata.description | Directly mapped from the Opcode
field in the raw log. |
OpcodeValue
|
Not mapped to the IDM object. | |
Output
|
security_result.detection_fields[0].value | Directly mapped from the Output
field in the raw log if present. |
powershell.Command Name
|
security_result.detection_fields[0].value | Directly mapped from the powershell.Command Name
field if present. |
powershell.Command Type
|
security_result.detection_fields[1].value | Directly mapped from the powershell.Command Type
field if present. |
powershell.Host Application
|
target.process.command_line | Directly mapped from the powershell.Host Application
field in the raw log if present. |
powershell.Host ID
|
target.asset.asset_id | Directly mapped from the powershell.Host ID
field in the raw log if present. The value is prefixed with Host ID:
. |
powershell.Host Name
|
target.hostname | Directly mapped from the powershell.Host Name
field in the raw log if present. |
powershell.HostApplication
|
target.process.command_line | Directly mapped from the powershell.HostApplication
field in the raw log if present. |
powershell.HostId
|
target.asset.asset_id | Directly mapped from the powershell.HostId
field in the raw log if present. The value is prefixed with Host ID:
. |
powershell.HostName
|
target.hostname | Directly mapped from the powershell.HostName
field in the raw log if present. |
powershell.Script Name
|
target.process.file.full_path | Directly mapped from the powershell.Script Name
field in the raw log if present. |
powershell.ScriptName
|
target.process.file.full_path | Directly mapped from the powershell.ScriptName
field in the raw log if present. |
powershell.Sequence Number
|
security_result.detection_fields[2].value | Directly mapped from the powershell.Sequence Number
field in the raw log if present. |
powershell.SequenceNumber
|
security_result.detection_fields[0].value | Directly mapped from the powershell.SequenceNumber
field in the raw log if present. |
powershell.UserId
|
principal.user.userid | Directly mapped from the powershell.UserId
field in the raw log if present. |
Process ID
|
principal.process.pid | Directly mapped from the Process ID
field in the raw log if ExecutionProcessID
and ProcessID
are not present or empty or 0. Converted to a string. |
ProcessID
|
principal.process.pid | Directly mapped from the ProcessID
field in the raw log if ExecutionProcessID
is not present or empty or 0. Converted to a string. |
ProviderGuid
|
metadata.product_deployment_id | Directly mapped from the ProviderGuid
field in the raw log. The curly braces are removed. |
PSEdition
|
Not mapped to the IDM object. | |
PSRemotingProtocolVersion
|
Not mapped to the IDM object. | |
PSVersion
|
Not mapped to the IDM object. | |
RecordNumber
|
metadata.product_log_id | Directly mapped from the RecordNumber
field in the raw log. Converted to a string. |
RenderedDescription
|
security_result.description | Directly mapped from the RenderedDescription
field in the raw log if present. |
RunAs User
|
Not mapped to the IDM object. | |
ScriptBlockId
|
Not mapped to the IDM object. | |
ScriptBlockText
|
security_result.detection_fields[0].value | Directly mapped from the ScriptBlockText
field in the raw log if present. |
ScriptBlock ID
|
Not mapped to the IDM object. | |
Severity
|
security_result.severity, security_result.severity_details | Mapped based on the value of Severity
:- verbose
or info
maps to LOW
.- warn
or err
maps to MEDIUM
.- crit
maps to HIGH
.The raw value is also mapped to security_result.severity_details
. |
source.collector_id
|
Not mapped to the IDM object. | |
source.customer_id
|
Not mapped to the IDM object. | |
Source
|
additional.fields[1].value.string_value | Directly mapped from the Source
field in the raw log if present. |
SourceModuleName
|
principal.resource.name | Directly mapped from the SourceModuleName
field in the raw log. |
SourceModuleType
|
principal.resource.resource_subtype | Directly mapped from the SourceModuleType
field in the raw log. |
SourceName
|
metadata.product_name | Directly mapped from the SourceName
field in the raw log. |
start_time.nanos
|
Not mapped to the IDM object. | |
start_time.seconds
|
Not mapped to the IDM object. | |
TenantId
|
additional.fields[2].value.string_value | Directly mapped from the TenantId
field in the raw log if present. |
ThreadID
|
Not mapped to the IDM object. | |
timestamp.nanos
|
Not mapped to the IDM object. | |
timestamp.seconds
|
Not mapped to the IDM object. | |
type
|
Not mapped to the IDM object. | |
UserID
|
principal.user.windows_sid | Directly mapped from the UserID
field in the raw log. |
Username
|
principal.user.userid | Directly mapped from the Username
field in the raw log if AccountName
is not present. |
|
metadata.vendor_name | Set to Microsoft
. |
|
metadata.event_type | Set to PROCESS_LAUNCH
if EventID
is 4104
and _Path
is present in Message
, or if EventID
is 4103
, or if EventID
is in [ 800
, 600
, 400
] and powershell.ScriptName
and powershell.HostApplication
are present. Set to PROCESS_TERMINATION
if EventID
is 403
and _HostApplication
is present in Message
, or if EventID
is 403
and NewEngineState
is Stopped
. Set to STATUS_UPDATE
if EventID
is 4104
and _Path
is not present in Message
, or if EventID
is 4103
and no_value
, script_name
is empty, script_name_not_found
, and host_application_not_found
are all true, or if EventID
is 53504
, or if EventID
is 40962
, or if EventID
is 40961
, or if EventID
is empty and MessageSourceAddress
is present. Set to USER_UNCATEGORIZED
if EventID
is empty and Username
is present. Set to GENERIC_EVENT
if EventID
is empty and MessageSourceAddress
and Username
are not present. |
|
metadata.product_name | Set to Powershell
if SourceName
is not present. |
|
security_result.action | Set to ALLOW
. |
|
security_result.detection_fields[0].key | Set to Activity ID
. |
|
security_result.detection_fields[1].key | Set to Sequence Number
. |
|
security_result.detection_fields[2].key | Set to ExecutionThreadID
. |
|
additional.fields[0].key | Set to Management Group Name
. |
|
additional.fields[1].key | Set to Source
. |
|
additional.fields[2].key | Set to TenantId
. |
|
principal.asset.platform_software.platform | Set to WINDOWS
if platform_software
contains win
, MAC
if it contains mac
, LINUX
if it contains lin
, and UNKNOWN_PLATFORM
otherwise. |
|
target.process.file.full_path | Set to _Path
if EventID
is 4104
and _Path
is present in Message
. Set to file_path
if EventID
is 4104
and file_path
is present in Message
. Set to _HostApplication
if EventID
is 403
and _HostApplication
is present in Message
. |
Need more help? Get answers from Community members and Google SecOps professionals.