Azure Function PowerShell脚本写入Log Analytics指定表报错求助
我正在编写Azure Function的PowerShell脚本,目标是将数据写入Log Analytics工作区的指定表(如Table_CL),但执行过程中出现错误。以下是我的脚本内容及具体报错信息,恳请指导如何正确实现该功能:
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
报错信息
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
核心问题
签名生成逻辑完全不符合Log Analytics API的要求,Authorization头需要遵循特定的HMAC-SHA256签名格式,而非简单拼接SharedKey和时间再转十六进制。同时脚本存在语法错误和逻辑疏漏。
具体修复步骤
修正签名生成逻辑
Log Analytics的签名需要对请求内容的哈希值进行HMAC-SHA256加密,再Base64编码,格式为SharedKey <WorkspaceId>:<Base64EncodedSignature>。替换原签名代码为:$date = (Get-Date).ToUniversalTime().ToString("r") $bodyJson = ConvertTo-Json -InputObject $Body -Compress $contentLength = $bodyJson.Length # 构造签名字符串 $signatureString = "POST`n$contentLength`napplication/json`nx-ms-date:$date`n/api/logs" $encoding = [System.Text.Encoding]::UTF8 $signatureBytes = $encoding.GetBytes($signatureString) $sharedKeyBytes = [System.Convert]::FromBase64String($SharedKey) # 计算HMAC-SHA256哈希 $hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256 $hmacsha256.Key = $sharedKeyBytes $hashBytes = $hmacsha256.ComputeHash($signatureBytes) $signature = [System.Convert]::ToBase64String($hashBytes) # 构造Authorization头 $authorizationHeader = "SharedKey $WorkspaceId`:$signature"修正Body语法错误
原脚本中$eventGridEventvent.dataVersion多打了一个vent,应改为$eventGridEvent.dataVersion。同时需将Body转为JSON字符串,因为Invoke-WebRequest的-Body参数需要字符串格式:$Body = @{ "EventId" = $eventGridEvent.id; "eventType" = $eventGridEvent.eventType; "subject" = $eventGridEvent.subject; "TimeGenerated" = [datetime]$eventGridEvent.eventTime; "data" = (ConvertTo-Json -InputObject $eventGridEvent.data -Compress); "dataVersion" = $eventGridEvent.dataVersion; "metadataVersion" = $eventGridEvent.metadataVersion; } $bodyJson = ConvertTo-Json -InputObject $Body -Compress修正请求头内容
添加x-ms-date头,并使用正确格式的Authorization头:$Headers = @{ "Content-Type" = "application/json" "Log-Type" = $CustomTableName "x-ms-date" = $date "Authorization" = $authorizationHeader }修正Invoke-WebRequest调用
使用转换后的JSON字符串作为请求Body:Invoke-WebRequest -Uri $Uri -Method Post -Body $bodyJson -Headers $Headers移除冗余代码
Azure Function中不应每次运行都执行Install-Module,建议部署前预先安装模块;未使用的$logAnalyticsClient、$tenantId、$clientId变量可直接删除。
完整修复后的脚本
$WorkspaceId = "/subscriptions/subscriptionID/resourceGroups/rg-name/providers/Microsoft.OperationalInsights/workspaces/log-analytics-wsp" $SharedKey = "some-value" $CustomTableName = "Table_CL" $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 -Compress); "dataVersion" = $eventGridEvent.dataVersion; "metadataVersion" = $eventGridEvent.metadataVersion; } $bodyJson = ConvertTo-Json -InputObject $Body -Compress $contentLength = $bodyJson.Length $date = (Get-Date).ToUniversalTime().ToString("r") # 生成正确的签名 $signatureString = "POST`n$contentLength`napplication/json`nx-ms-date:$date`n/api/logs" $encoding = [System.Text.Encoding]::UTF8 $signatureBytes = $encoding.GetBytes($signatureString) $sharedKeyBytes = [System.Convert]::FromBase64String($SharedKey) $hmacsha256 = New-Object System.Security.Cryptography.HMACSHA256 $hmacsha256.Key = $sharedKeyBytes $hashBytes = $hmacsha256.ComputeHash($signatureBytes) $signature = [System.Convert]::ToBase64String($hashBytes) $authorizationHeader = "SharedKey $WorkspaceId`:$signature" # 构造请求头 $Headers = @{ "Content-Type" = "application/json" "Log-Type" = $CustomTableName "x-ms-date" = $date "Authorization" = $authorizationHeader } # 发送请求到Log Analytics API Invoke-WebRequest -Uri $Uri -Method Post -Body $bodyJson -Headers $Headers
内容的提问来源于stack exchange,提问作者lavoizer

