I am trying to write an azure function which posts data to a specific table e.g. (Table_CL) inside log analytics workspace. I am running into errors.
Install-Module -Name Az.OperationalInsights -Scope CurrentUser -Force
$logAnalyticsClient = Get-AzOperationalInsightsWorkspace -ResourceGroupName "rg-name" -Name "log-analytics-wsp"
$WorkspaceId = "/subscriptions/subscriptionID/resourceGroups/rg-name/providers/Microsoft.OperationalInsights/workspaces/log-analytics-wsp"
$SharedKey = "some-value"
$CustomTableName = "Table_CL"
# Obtain an authentication token
$tenantId = 'some value'
$clientId = 'value of Function App identity client IOD'
$Uri = "https://log-analytics-wsp.ods.opinsights.azure.com/api/logs?api-version=2016-04-01"
$Body = @{
"EventId" = $eventGridEvent.id;
"eventType" = $eventGridEvent.eventType;
"subject" = $eventGridEvent.subject;
"TimeGenerated" = [datetime]$eventGridEvent.eventTime;
"data" = (ConvertTo-Json -InputObject $eventGridEvent.data);
"dataVersion" = $eventGridEventvent.dataVersion;
"metadataVersion" = $eventGridEvent.metadataVersion;
}
$signature = $SharedKey + (get-date -uformat '%a, %d %b %Y %H:%M:%S ')
$hex = ""
foreach ($byte in $signature) {
$hex += "{0:x2}" -f $byte
}
$Signature = $hex
$Headers = @{
"Content-Type" = "application/json"
"Log-Type" = $CustomTableName
"Authorization" = $Signature
}
# Use the authentication token to send a request to the Log Analytics API
Invoke-WebRequest -Uri $Uri -Method Post -Body $Body -Headers $Headers
I am getting errors, can someone please guide me on how to post to specific table in log analytics using powershell script. I am getting the following errors.
2023-01-18T19:56:48Z [Error] ERROR: The format of value 'some-shared-key-value-==Wed, 18 Jan 2023 19:56:47 GMT' is invalid.
Exception :
Type : System.FormatException
TargetSite :
Name : ParseValue
DeclaringType : System.Net.Http.Headers.HttpHeaderParser, System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
MemberType : Method
Module : System.Net.Http.dll
Message : The format of value 'some-shared-key-value-Wed, 18 Jan 2023 19:56:47 GMT' is invalid.
Source : System.Net.Http
HResult : -2146233033
StackTrace :
at System.Net.Http.Headers.HttpHeaderParser.ParseValue(String value, Object storeValue, Int32& index)
at System.Net.Http.Headers.HttpHeaders.ParseAndAddValue(HeaderDescriptor descriptor, HeaderStoreItemInfo info, String value)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetRequest(Uri uri)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
at System.Management.Automation.Cmdlet.DoProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
CategoryInfo : NotSpecified: (:) [Invoke-WebRequest], FormatException
FullyQualifiedErrorId : System.FormatException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
InvocationInfo :
MyCommand : Invoke-WebRequest
ScriptLineNumber : 55
OffsetInLine : 1
HistoryId : 1
ScriptName : C:\home\site\wwwroot\EventGridTrigger1\run.ps1
Line : Invoke-WebRequest -Uri $Uri -Method Post -Body $Body -Headers $Headers
PositionMessage : At C:\home\site\wwwroot\EventGridTrigger1\run.ps1:55 char:1
+ Invoke-WebRequest -Uri $Uri -Method Post -Body $Body -Headers $Header …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot : C:\home\site\wwwroot\EventGridTrigger1
PSCommandPath : C:\home\site\wwwroot\EventGridTrigger1\run.ps1
InvocationName : Invoke-WebRequest
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, C:\home\site\wwwroot\EventGridTrigger1\run.ps1: line 55
Any suggestions? I am looking for way to post to Log Analytics workspace specific table, any help would be great.
Thanks
I had to use the following API from azure docs. This works neatly as it is. Just plug the values and the post command is able to create table in Azure Monitor. Following is the reference for the docs as well.
# Replace with your Workspace ID
$CustomerId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# Replace with your Primary Key
$SharedKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Specify the name of the record type that you'll be creating
$LogType = "MyRecordType"
# Optional name of a field that includes the timestamp for the data. If the time field is not specified, Azure Monitor assumes the time is the message ingestion time
$TimeStampField = ""
# Create two records with the same set of properties to create
$json = @"
[{ "StringValue": "MyString1",
"NumberValue": 42,
"BooleanValue": true,
"DateValue": "2019-09-12T20:00:00.625Z",
"GUIDValue": "9909ED01-A74C-4874-8ABF-D2678E3AE23D"
},
{ "StringValue": "MyString2",
"NumberValue": 43,
"BooleanValue": false,
"DateValue": "2019-09-12T20:00:00.625Z",
"GUIDValue": "8809ED01-A74C-4874-8ABF-D2678E3AE23D"
}]
"@
# Create the function to create the authorization signature
Function Build-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource)
{
$xHeaders = "x-ms-date:" + $date
$stringToHash = $method + "`n" + $contentLength + "`n" + $contentType + "`n" + $xHeaders + "`n" + $resource
$bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash)
$keyBytes = [Convert]::FromBase64String($sharedKey)
$sha256 = New-Object System.Security.Cryptography.HMACSHA256
$sha256.Key = $keyBytes
$calculatedHash = $sha256.ComputeHash($bytesToHash)
$encodedHash = [Convert]::ToBase64String($calculatedHash)
$authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash
return $authorization
}
# Create the function to create and post the request
Function Post-LogAnalyticsData($customerId, $sharedKey, $body, $logType)
{
$method = "POST"
$contentType = "application/json"
$resource = "/api/logs"
$rfc1123date = [DateTime]::UtcNow.ToString("r")
$contentLength = $body.Length
$signature = Build-Signature `
-customerId $customerId `
-sharedKey $sharedKey `
-date $rfc1123date `
-contentLength $contentLength `
-method $method `
-contentType $contentType `
-resource $resource
$uri = "https://" + $customerId + ".ods.opinsights.azure.com" + $resource + "?api-version=2016-04-01"
$headers = @{
"Authorization" = $signature;
"Log-Type" = $logType;
"x-ms-date" = $rfc1123date;
"time-generated-field" = $TimeStampField;
}
$response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing
return $response.StatusCode
}
# Submit the data to the API endpoint
Post-LogAnalyticsData -customerId $customerId -sharedKey $sharedKey -body ([System.Text.Encoding]::UTF8.GetBytes($json)) -logType $logType