api - 使用 Powershell 调用 Rest API - CosmosDb

标签 api powershell azure azure-cosmosdb

我尝试使用 Cosmos DB REST Api 部署 Cosmos 数据库。我正在使用一个函数来构建授权 header ,我从 https://gallery.technet.microsoft.com/scriptcenter/How-to-query-Azure-Cosmos-0a9aa517 获取了脚本关联。它对于 GET 和 POST 工作得非常好,但是当我尝试执行 PUT 命令时,我总是遇到以下错误。

Invoke-RestMethod : The remote server returned an error: (401) Unauthorized.

我正在尝试更新 Cosmos 系列的报价,但它总是以错误结束,我无法理解原因是什么。我还使用 Microsoft 文档检查了我的 header 和授权,对我来说看起来不错。请参阅https://learn.microsoft.com/en-us/rest/api/documentdb/replace-an-offer对于所需的 Uri 和 header 。我的请求和回复如下

请求

PUT https: //mycosmosdb.documents.azure.com:443/offers/mycollection HTTP/1.1
authorization: type % 3dmaster % 26ver % 3d1.0 % 26sig % 3dIgWkszNS % 2b94fUEyrG8frByB2PWSc1ZEszc06GUeuW7s % 3d
x - ms - version: 2017 - 02 - 22
x - ms - date: Wed, 02 Aug 2017 08: 40: 37 GMT
User - Agent: Mozilla / 5.0(Windows NT; Windows NT 10.0; en - US)WindowsPowerShell / 5.1.15063.483
Content - Type: application / json
Host: mycosmosdb.documents.azure.com
Content - Length: 269
{
    "offerVersion": "V2",
    "offerType": "Invalid",
    "content": {
        "offerThroughput": 500,
        "offerIsRUPerMinuteThroughputEnabled": false
    },
    "resource": "dbs/xterf==/colls/STuexopre=/",
    "offerResourceId": "STuexopre=",
    "id": "xiZw",
    "_rid": "xiZw"
}

回应

HTTP / 1.1 401 Unauthorized
Transfer - Encoding: chunked
Content - Type: application / json
Content - Location: https: //mycosmosdb.documents.azure.com/offers/variantstockquantity
Server: Microsoft - HTTPAPI / 2.0
x - ms - activity - id: 6f7be3c8 - cfa2 - 4d5e - ad69 - fb14ef218980
Strict - Transport - Security: max - age = 31536000
    x - ms - gatewayversion: version = 1.14.57.1
    Date: Wed, 02 Aug 2017 08: 40: 35 GMT

163{
    "code": "Unauthorized",
    "message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'put\noffers\mycollection\nwed, 02 aug 2017 08:40:37 gmt\n\n'\r\nActivityId: 6f7be3c8-cfa2-4d5e-ad69-fb14ef218980"
}
0

我的 Powershell 代码

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)

    If ($resourceLink -eq $resourceType) {
        $resourceLink = ""
    }

    $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")
}


Function Modify-Offer
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)][String]$DocumentDBApi,
        [Parameter(Mandatory=$true)][String]$EndPoint,
        [Parameter(Mandatory=$true)][String]$MasterKey,
        [Parameter(Mandatory=$true)][String]$CollectionName
    )
    

    $Verb = "PUT"
    $ResourceType = "offers";
    $ResourceLink = "offers"

    $body = '{
    "offerVersion": "V2",
    "offerType": "Invalid",
    "content": {
        "offerThroughput": 500,
        "offerIsRUPerMinuteThroughputEnabled": false
    },
    "resource": "dbs/xterf==/colls/STuexopre=/",
    "offerResourceId": "STuexopre=",
    "id": "xiZw",
    "_rid": "xiZw"
}'
    $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"=$DocumentDBApi;"x-ms-date"=$dateTime}
    $contentType= "application/json"
    $queryUri = "$EndPoint$ResourceLink/$CollectionName"
    $result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $body
    $result | ConvertTo-Json -Depth 10

}


Modify-Offer -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DocumentDBApi $DocumentDBApiVersion -CollectionName $ColName

有人可以向我提供一些帮助,说明为什么我的 PUT 请求因授权错误而失败、我缺少什么以及如何纠正它。

最佳答案

响应消息清楚地说明了用于验证的有效负载。在Generate-MasterKeyAuthorizationSignature中跟踪“$payLoad”将很快发现这个问题。

您至少需要解决以下两个问题才能使其发挥作用

  • RepalceOffer 文档说明了优惠的 RID,但您是 传递集合名称。
  • ResourceLin 硬编码:$ResourceLink =“Modify-Offer”中的“offers”,因为它需要指向资源的 RID。

这里是稍微修改过的代码,应该可以完成工作

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)

    If ($resourceLink -eq $resourceType) {
        $resourceLink = ""
    }

    $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);
    Write-Host $payLoad

    [System.Web.HttpUtility]::UrlEncode("type=$keyType&ver=$tokenVersion&sig=$signature")
}


Function Modify-Offer
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)][String]$DocumentDBApi,
        [Parameter(Mandatory=$true)][String]$EndPoint,
        [Parameter(Mandatory=$true)][String]$MasterKey,
        [Parameter(Mandatory=$true)][String]$OfferRID
    )


    $Verb = "PUT"
    $ResourceType = "offers";

    $body = '{
    "offerVersion": "V2",
    "offerType": "Invalid",
    "content": {
        "offerThroughput": 600,
        "offerIsRUPerMinuteThroughputEnabled": false
    },
"resource": "dbs/xterf==/colls/STuexopre=/",
"offerResourceId": "STuexopre=",
"id": "xiZw",
"_rid": "xiZw"
}'
    $dateTime = [DateTime]::UtcNow.ToString("r")
    $authHeader = Generate-MasterKeyAuthorizationSignature -verb $Verb -resourceLink $OfferRID -resourceType $ResourceType -key $MasterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime
    $header = @{authorization=$authHeader;"x-ms-version"=$DocumentDBApi;"x-ms-date"=$dateTime}
    $contentType= "application/json"
    $queryUri = "$EndPoint$ResourceType/$OfferRID"
    $result = Invoke-RestMethod -Method $Verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $body
    $result | ConvertTo-Json -Depth 10

}

Modify-Offer -EndPoint $CosmosDBEndPoint -MasterKey $MasterKey -DocumentDBApi $DocumentDBApiVersion -OfferRID $ColName

如果可能的话,建议的其他替代方法是在 Powershell 中使用客户端 SDK。以下是更新帐户首次报价的示例代码。

Add-Type -Path "...\Microsoft.Azure.Documents.Client.dll"
$client=New-Object Microsoft.Azure.Documents.Client.DocumentClient($CosmosDBEndPoint, $MasterKey)
$offersEnum=$client.ReadOffersFeedAsync().Result.GetEnumerator();
if ($offersEnum.MoveNext())
{
    $targetOffer=$offersEnum.Current
    $offerUpdated=New-Object Microsoft.Azure.Documents.OfferV2($targetOffer, 600, $FALSE)
    $client.ReplaceOfferAsync($offerUpdated).Result
}

关于api - 使用 Powershell 调用 Rest API - CosmosDb,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45456029/

相关文章:

c# - 我应该在何时/何处在我的 ASP.NET MVC 项目中创建以下类?

wordpress - Rest API 插件 wordpress 禁用默认路由

powershell - 如何在 PowerShell 中为读取主机配置超时

powershell - 在 PowerShell 中逐行读取文件

azure - 从 CI/CD YAML 引用 Azure Key Vault secret

api - 针对标记内容的新 Instagram API 限制的解决方法

java - NTLM 身份验证方案选择错误

powershell - 在 powershell 中使用 Robocopy 摘要发送邮件正文

azure - CosmosDB RU 计算器错误

azure - 如何使用 MSI 从另一个租户中的服务访问资源?