internal/loggingProviders/splunk.provider.ps1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
$functionDefinitions = { function Send-SplunkData { <# .SYNOPSIS Writes data to a splunk http event collector. .DESCRIPTION Writes data to a splunk http event collector. See this blog post for setting up the Splunk server: https://ntsystems.it/post/sending-events-to-splunks-http-event-collector-with-powershell .PARAMETER InputObject The object to send as message. .PARAMETER HostName The name of the computer from which the message was generated. .PARAMETER Timestamp The timestamp fron when the message was generated. .PARAMETER Uri Link to the http collector endpoint to which to write to. Example: https://localhost:8088/services/collector .PARAMETER Token The token associated with the http event collector. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $InputObject, [Parameter(Mandatory = $true)] [string] $HostName, [Parameter(Mandatory = $true)] [System.DateTime] $Timestamp, [Parameter(Mandatory = $true)] [string] $Uri, [Parameter(Mandatory = $true)] [string] $Token ) process { # Splunk events can have a 'time' property in epoch time. If it's not set, use current system time. $unixEpochStart = New-Object -TypeName DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc) $unixEpochTime = [int]($Timestamp.ToUniversalTime() - $unixEpochStart).TotalSeconds # Create json object to send $eventData = @{ event = $InputObject host = $HostName time = $unixEpochTime } if ($index = Get-ConfigValue -Name Index) { $eventData.index = $index } if ($source = Get-ConfigValue -Name Source) { $eventData.source = $source } if ($sourcetype = Get-ConfigValue -Name SourceType) { $eventData.sourcetype = $sourcetype } $body = ConvertTo-Json -InputObject $eventData -Compress # Only return if something went wrong, i.e. http response is not "success" try { $null = Invoke-RestMethodCustom -Uri $uri -Method Post -Headers @{ Authorization = "Splunk $Token" } -Body $body -ErrorAction Stop -IgnoreCert:$(Get-ConfigValue -Name IgnoreCert) } catch { throw } } } function Invoke-RestMethodCustom { [CmdletBinding()] param ( [string] $Uri, [System.Collections.Hashtable] $Headers, [string] $Method, [string] $ContentType = 'application/json', [string] $Body, [switch] $IgnoreCert ) process { $request = [System.Net.WebRequest]::Create($Uri) foreach ($key in $Headers.Keys) { $request.Headers[$key] = $Headers[$key] } $request.Method = $Method if ($IgnoreCert) { $request.ServerCertificateValidationCallback = { $true } } $request.ContentLength = $Body.Length $requestWriter = New-Object System.IO.StreamWriter($request.GetRequestStream(), [System.Text.Encoding]::ASCII) $requestWriter.Write($Body) $requestWriter.Close() try { $responseStream = $request.GetResponse().GetResponseStream() $reader = New-Object System.IO.StreamReader($responseStream) $reader.ReadToEnd() $reader.Close() } catch { throw } } } function Write-SplunkMessage { [CmdletBinding()] param ( $Message ) $splunkUrl = Get-ConfigValue -Name 'Url' $splunkToken = Get-ConfigValue -Name 'Token' $properties = Get-ConfigValue -Name 'Properties' $name = Get-ConfigValue -Name 'LogName' $selectProps = switch ($properties) { 'Message' { 'LogMessage as Message' } 'Timestamp' { 'Timestamp.ToUniversalTime().ToString("yyyy-MM-dd_HH:mm:ss.fff") as Timestamp' } 'Level' { 'Level to String' } 'Type' { 'Type to String' } 'CallStack' { 'CallStack to String' } 'ErrorRecord' { 'ErrorRecord to String' } default { $_ } } $selectProps = @($selectProps) + @(@{ Name = 'LogName'; Expression = { $name } }) $Message | Select-PSFObject $selectProps | Send-SplunkData -HostName $Message.ComputerName -Timestamp $Message.Timestamp -Uri $splunkUrl -Token $splunkToken } } $message_event = { param ( $Message ) Write-SplunkMessage -Message $Message } $configuration_Settings = { Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.Url' -Description 'The url to the Splunk http event collector. Example: https://localhost:8088/services/collector' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.Token' -Description 'The token used to authenticate to the Splunk event collector.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.Properties' -Initialize -Value 'Timestamp', 'Message', 'Level', 'Tags', 'FunctionName', 'ModuleName', 'Runspace', 'Username', 'ComputerName', 'TargetObject', 'Data' -Description 'The properties to write to Splunk.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.LogName' -Initialize -Value 'Undefined' -Validation string -Description 'Name associated with the task. Included in each entry, making it easier to reuse the same http event collector for multiple tasks.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.IgnoreCert' -Initialize -Value $false -Validation bool -Description 'Whether the server certificate should be validated or not.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.Index' -Initialize -Value '' -Validation string -Description 'The index to apply to all messages. Uses the splunk-defined default index if omitted.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.Source' -Initialize -Value '' -Validation string -Description 'Event source to add to all messages.' Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Splunk.SourceType' -Initialize -Value '' -Validation string -Description 'Event source type to add to all messages.' } $paramRegisterPSFLoggingProvider = @{ Name = "splunk" Version2 = $true ConfigurationRoot = 'PSFramework.Logging.Splunk' InstanceProperties = 'Url', 'Token', 'Properties', 'LogName', 'IgnoreCert', 'Index', 'Source', 'SourceType' MessageEvent = $message_Event ConfigurationSettings = $configuration_Settings FunctionDefinitions = $functionDefinitions ConfigurationDefaultValues = @{ Properties = 'Timestamp', 'Message', 'Level', 'Tags', 'FunctionName', 'ModuleName', 'Runspace', 'Username', 'ComputerName', 'TargetObject', 'Data' LogName = 'Undefined' IgnoreCert = $false } } # Register the Azure logging provider Register-PSFLoggingProvider @paramRegisterPSFLoggingProvider |