问题
I am trying to access azure cosmos db account collection documents and also each document in collection. I had referred below link and changed all necessary cosmos db values like databaseid,container,itemid master key etc.,
Link:
https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/PowerShellRestApi/PowerShellScripts/ReadItem.ps1
But i am getting below error while running in Powershell.
Error:
StatusCode: 401
Exception Message: The remote server returned an error: (401) Unauthorized.
System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
NOTE: When i tried same in postman, i am getting list of documents but when i tried to get specific document . I am getting below error.
Error:
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:
FYI: I am contributor role for Cosmodb account in azure portal
Parameters:
$endpoint = "https://testcosmos.documents.azure.com:443/"
$MasterKey = "<Key from Cosmos db account>"
$KeyType = "master"
$TokenVersion = "1.0"
$date = Get-Date
$utcDate = $date.ToUniversalTime()
$xDate = $utcDate.ToString('r',
[System.Globalization.CultureInfo]::InvariantCulture)
$databaseId = "testdb"
$containerId = "containercollection"
$itemResourceType = "docs"
$ItemId="1"
$itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"
$itemResourceLink = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"
$verbMethod = "GET"
$header = @{
"authorization" = "$authKey";
"x-ms-version" = "2018-12-31";
"Cache-Control" = "no-cache";
"x-ms-date" = "$xDate"
"Accept" = "application/json";
"User-Agent" = "PowerShell-RestApi-Samples";
"x-ms-documentdb-partitionkey" = '["testPK"]'
}
I had tried commenting "Accept","User-Agent", Cache-Control header options but in vain. I also tried just getting only list of /docs without itemID but that also went in vain.
$result = Invoke-RestMethod -Uri $requestUri -Headers $header -Method $verbMethod -ContentType "application/json"
Write-Host "Read item response = "$result
Updated Code: I finally able to understand why issue is coming. its neither authentication issue nor resourceID. I am passing partition key in headers which is not hard coded as per sample . When i am passing value to partition key, it was not taking correctly hence causing issue. Below is my dynamic Code passing partition key
"x-ms-documentdb-partitionkey" = '["$Partitionkey"]' -- Displaying as
[$Partitionkey] but it must print in headers like ["partitionkeyValue"]
Am trying how to fix that. Many many thanks for your suggestions.
回答1:
I tried the following code and it worked well for me. I was able to fetch the document details:
Add-Type -AssemblyName System.Web
Function Generate-MasterKeyAuthorizationSignature{
[CmdletBinding()]
param (
[string] $Verb,
[string] $ResourceId,
[string] $ResourceType,
[string] $Date,
[string] $MasterKey,
[String] $KeyType,
[String] $TokenVersion
)
$keyBytes = [System.Convert]::FromBase64String($MasterKey)
$sigCleartext = @($Verb.ToLower() + "`n" + $ResourceType.ToLower() + "`n" + $ResourceId + "`n" + $Date.ToString().ToLower() + "`n" + "" + "`n")
Write-Host "sigCleartext = " $sigCleartext
$bytesSigClear = [Text.Encoding]::UTF8.GetBytes($sigCleartext)
$hmacsha = new-object -TypeName System.Security.Cryptography.HMACSHA256 -ArgumentList (, $keyBytes)
$hash = $hmacsha.ComputeHash($bytesSigClear)
$signature = [System.Convert]::ToBase64String($hash)
$key = [System.Web.HttpUtility]::UrlEncode('type='+$KeyType+'&ver='+$TokenVersion+'&sig=' + $signature)
return $key
}
$endpoint = "https://account-name.documents.azure.com:443/"
$MasterKey = "account-key"
$KeyType = "master"
$TokenVersion = "1.0"
$date = Get-Date
$utcDate = $date.ToUniversalTime()
$xDate = $utcDate.ToString('r', [System.Globalization.CultureInfo]::InvariantCulture)
$databaseId = "MyDatabaseId"
$containerId = "MyContainerId"
$itemId = "TestItem"
$itemResourceType = "docs"
$itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"+$ItemId
$itemResourceLink = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"+$ItemId
$verbMethod = "GET"
$requestUri = "$endpoint$itemResourceLink"
$authKey = Generate-MasterKeyAuthorizationSignature -Verb $verbMethod -ResourceId $itemResourceId -ResourceType $itemResourceType -Date $xDate -MasterKey $MasterKey -KeyType $KeyType -TokenVersion $TokenVersion
$header = @{
"authorization" = "$authKey";
"x-ms-version" = "2018-12-31";
"Cache-Control" = "no-cache";
"x-ms-date" = "$xDate";
"Accept" = "application/json";
"User-Agent" = "PowerShell-RestApi-Samples";
"x-ms-documentdb-partitionkey" = '["testPk"]'
}
try {
$result = Invoke-RestMethod -Uri $requestUri -Headers $header -Method $verbMethod -ContentType "application/json"
Write-Host "Read item response = "$result
return "ReadItemSuccess";
}
catch {
# Dig into the exception to get the Response details.
# Note that value__ is not a typo.
Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "Exception Message:" $_.Exception.Message
echo $_.Exception|format-list -force
}
UPDATE
Regarding your comment about dynamically specifying the partition key value, try something like the following:
"x-ms-documentdb-partitionkey" = '["' + $Partitionkey + '"]'
回答2:
Firstly, i could query my item successfully with github code as same as @Gaurav Mantri. Your error code is 401
auth issue,so I assume that you make some mistakes with generation of MasterKeyAuthorizationSignature
,especially the value of $itemResourceId
.Please refer to the REST API document.
2 parts:
1.Query a specific item:
$itemId = "1"
$itemResourceType = "docs"
$itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"+$ItemId
$itemResourceLink = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"+$ItemId
2.List items in a specific colletion:
No #itemId
$itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId
$itemResourceLink = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs/"
来源:https://stackoverflow.com/questions/61225910/unauthorized-status-while-accessing-cosmos-db-collection-documents-in-power-shel