无法使用PowerShell张贴Cosmos DB存储过程 [英] Cannot POST Cosmos DB Stored Procedures using PowerShell

查看:46
本文介绍了无法使用PowerShell张贴Cosmos DB存储过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将存储过程部署到Azure Cosmos DB帐户内的集合中,这是我在Azure DevOps中部署管道的一部分.出于安全原因,我必须使用REST API(无法使用或导入PowerShell模块来执行此操作).

I'm trying to deploy stored procedures to a collection within an Azure Cosmos DB account as part of my deployment pipeline in Azure DevOps. Due to security reasons, I have to use the REST API (cannot use or import PowerShell modules to do this).

我正在使用的构建代理是本地代理.同样,出于安全原因.

The build agents that I'm using are on-premise agents. Again, security reasons.

为了生成用于请求的授权令牌,我具有以下PowerShell功能:

In order to generate an authorization token to make requests, I have the following PowerShell function:

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函数中调用此函数:

I then call this function within the POST function that I'm using to POST the stored procedure to Azure Cosmos DB:

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
}

我从文档中看到我需要将存储过程作为字符串传递给主体,因此我将存储过程的路径设置为如下所示的变量:

I see from the documentation that I need to pass my stored procedure in the body as a string, so I set the path of my stored procedure to a variable like so:

$HelloWorld = Get-Content -Path '.\Databases\MyCosmosDB\MyCosmosCollection\Stored Procedures\HelloWorld.js' | Out-String

然后我像这样调用POST函数:

I then call my POST function like so:

Post-StoredProcToCosmosDb -EndPoint $env:COSMOSENDPOINT -DataBaseId $env:MYCOSMOSDB -CollectionId $MyCollection -MasterKey $env:MASTERKEY -JSON $HelloWorld

但是,当我运行任务时,出现以下错误:

However, when I run the task, I get the following error:

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

Invoke-RestMethod : The remote server returned an error: (400) Bad Request At D:_workAzure\r12\a_Cosmos\Deployment\scripts\postStoredProcedures.ps1:61 char:15
$result = Invoke-RestMethod -Headers $header -Method $Verb -Content ...
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

我遵循了

I have followed the example request body as outlined in the documentation for my stored procedure.

这是您的信息的外观:

"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 ,但是否则,我不确定我在哪里出问题了吗?

I'm fairly new to PowerShell, so I'm wondering where I am going wrong. I've tried setting the contentType to both application/json and application/query+json but otherwise, I'm not sure where I am going wrong?

如果有人可以提供任何指导,我将不胜感激.

If anyone can provide any guidance on this, I'd be most grateful.

推荐答案

所以事实证明请求主体是错误的.应该是这样的:

So turns out the request body was wrong. It should be like this:

{
    "body":"function HelloWorld() {\r\n    var context = getContext();\r\n    var response = context.getResponse();\r\nresponse.setBody(\"Hello, World\");\r\n}",
    "id": "HelloWorld"
}

这是存储过程可接受的请求正文.因此,我应该将$ HelloWorld变量设置为:

That's the acceptable request body for Stored Procedures. So what I should have done is set my $HelloWorld variable to:

$HelloWorld = Get-Content -Path '.\Databases\MyCosmosDB\MyCosmosCollection\Stored Procedures\HelloWorld.json' | Out-String

希望我的愚蠢有一天能帮助某人:/

Hope my stupidity helps someone someday :/

这篇关于无法使用PowerShell张贴Cosmos DB存储过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆