我正在尝试将存储过程部署到Azure Cosmos DB帐户内的集合中,这是我在Azure DevOps中部署管道的一部分。出于安全原因,我必须使用REST API(无法使用或导入PowerShell模块来执行此操作)。
我正在使用的构建代理是本地代理。同样,出于安全原因。
为了生成授权令牌以进行请求,我具有以下PowerShell功能:
Add-Type -AssemblyName System.Web
# Generate Authorization Key for REST calls
Function Generate-MasterKeyAuthorizationSignature
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$verb,
[Parameter(Mandatory=$true)][String]$resourceLink,
[Parameter(Mandatory=$true)][String]$resourceType,
[Parameter(Mandatory=$true)][String]$dateTime,
[Parameter(Mandatory=$true)][String]$key,
[Parameter(Mandatory=$true)][String]$keyType,
[Parameter(Mandatory=$true)][String]$tokenVersion
)
$hmacSha256 = New-Object System.Security.Cryptography.HMACSHA256
$hmacSha256.Key = [System.Convert]::FromBase64String($key)
$payLoad = "$($verb.ToLowerInvariant())`n$($resourceType.ToLowerInvariant())`n$resourceLink`n$($dateTime.ToLowerInvariant())`n`n"
$hashPayLoad = $hmacSha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($payLoad))
$signature = [System.Convert]::ToBase64String($hashPayLoad);
[System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature")
}
然后在用于将存储过程POST到Azure Cosmos DB的POST函数中调用此函数:
Function Post-StoredProcToCosmosDb
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true)][String]$EndPoint,
[Parameter(Mandatory=$true)][String]$DataBaseId,
[Parameter(Mandatory=$true)][String]$CollectionId,
[Parameter(Mandatory=$true)][String]$MasterKey,
[Parameter(Mandatory=$true)][String]$JSON
)
$Verb = 'Post'
$ResourceType = "sprocs"
$ResourceLink = "dbs/$DataBaseId/colls/$CollectionId"
$dateTime = [DateTime]::UtcNow.ToString("r")
$authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $ResourceLink -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime
$header = @{authorization=$authHeader;"x-ms-version"="2017-02-22";"x-ms-date"=$dateTime;"xs-ms-session-token"="28"}
$contentType = "application/json"
$queryUri = "$EndPoint$ResourceLink/sprocs"
$result = Invoke-RestMethod -Headers $header -Method $Verb -ContentType $contentType -Uri $queryUri -Body $JSON
return $result.statuscode
}
我从documentation看到,我需要将存储过程作为字符串传递给主体,因此我将存储过程的路径设置为如下所示的变量:
$HelloWorld = Get-Content -Path '.\Databases\MyCosmosDB\MyCosmosCollection\Stored Procedures\HelloWorld.js' | Out-String
然后我像这样调用POST函数:
Post-StoredProcToCosmosDb -EndPoint $env:COSMOSENDPOINT -DataBaseId $env:MYCOSMOSDB -CollectionId $MyCollection -MasterKey $env:MASTERKEY -JSON $HelloWorld
但是,当我运行任务时,出现以下错误:
Invoke-RestMethod:远程服务器返回错误:(400)错误的请求 在D:_workAzure \ r12 \ a_Cosmos \ Deployment \ scripts \ postStoredProcedures.ps1:61 char:15
$ result =调用-RestMethod -Headers $ header -Method $ Verb -Content ...
+ CategoryInfo:InvalidOperation:(System.Net.HttpWebRequest:HttpWebRequest)[Invoke-RestMethod],WebException
+ FullyQualifiedErrorId:WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
对于我的存储过程,我遵循了documentation中概述的示例请求正文。
这是您的信息的外观:
"function () {\r\n var context = getContext();\r\n var response = context.getResponse();\r\n\r\n response.setBody(\"Hello, World\");\r\n}"
我对PowerShell还是很陌生,所以我想知道哪里出了问题。我尝试将contentType
设置为application/json
和application/query+json
,但否则,我不确定我要去哪里错了?
如果有人可以提供任何指导,我将不胜感激。
答案 0 :(得分:2)
所以事实证明请求主体是错误的。应该是这样的:
{
"body":"function HelloWorld() {\r\n var context = getContext();\r\n var response = context.getResponse();\r\nresponse.setBody(\"Hello, World\");\r\n}",
"id": "HelloWorld"
}
这是存储过程可接受的请求正文。因此,我应该将$ HelloWorld变量设置为:
$HelloWorld = Get-Content -Path '.\Databases\MyCosmosDB\MyCosmosCollection\Stored Procedures\HelloWorld.json' | Out-String
希望我的愚蠢有一天能帮助某人:/