public/psf-logscale.ps1
function Register-FalconEventCollector { <# .SYNOPSIS Define Falcon LogScale or Falcon NGSIEM ingestion endpoint and token for logging .DESCRIPTION Once configured, the Falcon LogScale or Falcon NGSIEM destination can be used by PSFalcon but the module will not send events to until 'Enable' options are chosen. 'Remove-FalconEventCollector' can be used to remove a configured destination and stop the transmission of events. .PARAMETER Uri Falcon LogScale cloud or Falcon NGSIEM HEC ingestion URI .PARAMETER Token Falcon LogScale or Falcon NGSIEM ingestion token .PARAMETER Enable Define events to send to the collector .LINK https://github.com/crowdstrike/psfalcon/wiki/Register-FalconEventCollector #> [CmdletBinding()] [OutputType([void])] param( [Parameter(Mandatory,ValueFromPipelineByPropertyName,Position=1)] [System.Uri]$Uri, [Parameter(Mandatory,ValueFromPipelineByPropertyName,Position=2)] [ValidatePattern('^([a-fA-F0-9]{32}|[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})$')] [string]$Token, [Parameter(ValueFromPipelineByPropertyName,Position=3)] [ValidateSet('responses','requests')] [string[]]$Enable ) process { if (!$Script:Falcon.Api) { throw "[ApiClient] has not been initiated. Try 'Request-FalconToken'." } $Script:Falcon.Api.Collector = @{ Uri = $PSBoundParameters.Uri.ToString(); Token = $PSBoundParameters.Token } if ($Token -match '^[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12}$') { $Script:Falcon.Api.Collector.Uri += 'api/v1/ingest/humio-structured/' } [string]$Message = "Added '$($Script:Falcon.Api.Collector.Uri)'" if ($PSBoundParameters.Enable) { $Script:Falcon.Api.Collector['Enable'] = $PSBoundParameters.Enable $Message += " for $(@($PSBoundParameters.Enable).foreach{ "'$_'" } -join ',')" } Write-Log 'Register-FalconEventCollector' $Message } } function Send-FalconEvent { <# .SYNOPSIS Create Falcon LogScale or Falcon NGSIEM events from PSFalcon command results .DESCRIPTION Uses the pre-defined 'Path' and 'Token' values from 'Register-FalconEventCollector' to create events from the output provided by a PSFalcon command. .PARAMETER Object PSFalcon command output .LINK https://github.com/crowdstrike/psfalcon/wiki/Send-FalconEvent #> [CmdletBinding()] [OutputType([void])] param( [Parameter(Mandatory,ValueFromPipeline,Position=1)] [object]$Object ) begin { $OriginalProgress = $ProgressPreference $ProgressPreference = 'SilentlyContinue' [System.Collections.Generic.List[object]]$List = @() } process { if ($Script:Falcon.Api.Collector.Token -and $Script:Falcon.Api.Collector.Token -match '^[a-fA-F0-9]{32}$') { # Force object into [PSCustomObject] type and send to Falcon NGSIEM [PSCustomObject]$Object = if ($Object -is [string]) { @{ string = $Object } } else { $Object } Set-Property $Object '@timestamp' ([DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()) Set-Property $Object '@sourcetype' $Script:Falcon.Api.UserAgent $Param = @{ Uri = $Script:Falcon.Api.Collector.Uri Method = 'POST' Headers = @{ Authorization = @('Bearer',$Script:Falcon.Api.Collector.Token) -join ' ' ContentType = 'application/json' } Body = @{ event = $Object } | ConvertTo-Json -Depth 32 } try { [void](Invoke-WebRequest @Param -UseBasicParsing) } catch { Write-Error $_ } } else { if ($Object) { @($Object).foreach{ $List.Add($_) }} } } end { if (!$Script:Falcon.Api.Collector.Uri -or !$Script:Falcon.Api.Collector.Token) { throw "Falcon LogScale destination has not been configured. Try 'Register-FalconEventCollector'." } elseif ($List) { # Send events to Falcon LogScale environment [object[]]$Events = @($List).foreach{ $Item = @{ timestamp = Get-Date -Format o; attributes = @{}} if ($_ -is [PSCustomObject]) { @($_.PSObject.Properties | Where-Object { $_.Name -notmatch '\.' }).foreach{ $Item.attributes[$_.Name] = $_.Value } } elseif ($_ -is [string]) { $Item.attributes['id'] = $_ } $Item } $Param = @{ Uri = $Script:Falcon.Api.Collector.Uri Method = 'post' Headers = @{ Authorization = @('Bearer',$Script:Falcon.Api.Collector.Token) -join ' ' ContentType = 'application/json' } Body = ConvertTo-Json @( @{ tags = @{ host = [System.Net.Dns]::GetHostname(); source = (Show-FalconModule).UserAgent } events = $Events } ) -Depth 8 -Compress } [void](Invoke-WebRequest @Param -UseBasicParsing) } $ProgressPreference = $OriginalProgress } } function Show-FalconEventCollector { <# .SYNOPSIS Display existing Falcon LogScale ingestion endpoint and token .LINK https://github.com/crowdstrike/psfalcon/wiki/Show-FalconEventCollector #> [CmdletBinding()] [OutputType([PSCustomObject])] param() process { if ($Script:Falcon.Api.Collector) { [PSCustomObject]$Script:Falcon.Api.Collector }} } function Unregister-FalconEventCollector { <# .SYNOPSIS Remove an existing Falcon LogScale ingestion endpoint and token .LINK https://github.com/crowdstrike/psfalcon/wiki/Unregister-FalconEventCollector #> [CmdletBinding()] param() process { if ($Script:Falcon.Api.Collector) { Write-Log 'Unregister-FalconEventCollector' "Removed '$($Script:Falcon.Api.Collector.Uri)'" $Script:Falcon.Api.Collector = @{} } } } $Register = @{ # Add default Humio cloud addresses for autocompletion CommandName = 'Register-FalconEventCollector' ParameterName = 'Uri' ScriptBlock = { param($CommandName,$ParameterName,$WordToComplete,$CommandAst,$FakeBoundParameters) $PublicCloud = @('https://cloud.community.humio.com/','https://cloud.humio.com/', 'https://cloud.us.humio.com/') $Match = $PublicCloud | Where-Object { $_ -like "$WordToComplete*" } $Match | ForEach-Object { New-Object -Type System.Management.Automation.CompletionResult -ArgumentList $_, $_, 'ParameterValue', $_ } } } Register-ArgumentCompleter @Register |