2017-08-02 27 views
4

我試圖使用Cosmos DB REST Api部署cosmos數據庫。我正在使用一個函數來構建授權頭,我從https://gallery.technet.microsoft.com/scriptcenter/How-to-query-Azure-Cosmos-0a9aa517鏈接中獲得了腳本。它工作得很好GET & POST但是當我試圖執行一個PUT命令時,我總是得到錯誤。使用Powershell調用Rest API - CosmosDb

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

我試圖更新宇宙收集的報價,但它總是以錯誤結束,我不明白是什麼原因。我還檢查了我的標題和微軟文檔的授權,看起來很好。請參閱https://docs.microsoft.com/en-us/rest/api/documentdb/replace-an-offer以獲取Uri和標題。我的請求和響應都低於

請求

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請求由於授權錯誤而失敗,我錯過了什麼以及如何糾正它。

回答

2

響應消息清楚地說明了用於驗證的有效負載。在Generate-MasterKeyAuthorizationSignature中跟蹤'$ payLoad'將很快解決這個問題。

你需要解決的,至少以下兩個問題這個工作擺脫報價

  • RepalceOffer文檔狀態,而不是你是 通過集合名稱。
  • 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 

其他替代推薦的方法,如果可能的是消費客戶端SDK在PowerShell中。以下是更新帳戶第一次報價的示例代碼。

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 
} 
+0

謝謝@Kiran。您的意見非常感謝,現在它工作得很好。 我應該看到有效載荷。 我與RID混淆。該文件說RID,我期待_rid返回這是「xiZw」我需要通過的值,但我們仍然傳遞集合名稱作爲RID。這是否意味着offerRID與集合名稱相同? 現在我們沒有興趣使用SDK,因爲我們所有的部署服務器都需要這麼做,所以我們考慮使用REST API。 – VidhyaSagar

+0

不好意思。對於SelfLink,RID可互換使用。對於您提供的產品,您只需要使用SelfLink。 –