【问题标题】:Unauthorized access while accessing Azure Cosmos DB to get specific document using Query in power shell访问 Azure Cosmos DB 以在 power shell 中使用 Query 获取特定文档时未经授权的访问
【发布时间】:2020-04-16 08:05:13
【问题描述】:

参考下面的链接,我正在尝试修改 Github 示例以通过以下方式获取特定文档 在正文中提供查询选项。

链接: https://docs.microsoft.com/en-us/rest/api/cosmos-db/querying-cosmosdb-resources-using-the-rest-api

Github 示例: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/PowerShellRestApi/PowerShellScripts/ReadItem.ps1

我修改了如下代码:

 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
 }

 Function Get-Document {
[string] $endpoint = "https://testcosmos.documents.azure.com/"
[string] $MasterKey = "masterkey=="
[string] $databaseId = "testdb"
[string] $containerId = "containercollection1"

$KeyType = "master"
$TokenVersion = "1.0"
$date = Get-Date
$utcDate = $date.ToUniversalTime()
$xDate = $utcDate.ToString('r', [System.Globalization.CultureInfo]::InvariantCulture)
$itemResourceType = "docs"
$itemResourceId = $null
$itemResourceLink = $null
# $itemResourceId = "dbs/" + $databaseId + "/colls/" + $containerId
$itemResourceLink = "dbs/" + $databaseId + "/colls/" + $containerId + "/docs/"
$itemResourceId = "dbs/" + $databaseId + "/colls/" + $containerId

$verbMethod = "POST"
$requestUri = "$endpoint$itemResourceLink"
$authKey = Generate-MasterKeyAuthorizationSignature -Verb $verbMethod -ResourceId $itemResourceId -ResourceType $itemResourceType -Date $xDate -MasterKey $MasterKey -KeyType $KeyType -TokenVersion $TokenVersion
$itemResourceId
$itemResourceLink
$requestUri
$header = @{

    "x-ms-documentdb-isquery" = "True";

    "authorization"           = "$authKey";

    "x-ms-version"            = "2018-12-31";

    "Cache-Control"           = "no-cache";

    "x-ms-date"               = "$xDate";
}

  $queryJson = @"
 { 
"query": "SELECT * FROM TestCollection c WHERE c.userid = 2",     
"parameters": [ ] 
  }
  "@ 
   try {
      $result = Invoke-RestMethod -Uri $requestUri -Headers $header -Method 
  $verbMethod -ContentType "application/query+json" -Body $queryJson - 
   ErrorAction Stop
    Write-Host "Read item response = "$result

}
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
    Write-Host $_.Exception|format-list -force
  }
 }

  Get-Document

错误:

响应状态码不表示成功:400(错误请求)

【问题讨论】:

    标签: azure powershell azure-cosmosdb azure-powershell azure-cosmosdb-sqlapi


    【解决方案1】:

    我认为问题出在您的 $itemResourceId 变量上。

    请改成:

    $itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId
    

    你不应该得到这个 401 错误。

    如果你注意到了,我从这里删除了/docs

    另外,我发现这个有用的链接可能会对您有所帮助:https://github.com/Azure/azure-cosmos-dotnet-v2/blob/master/samples/rest-from-.net/Program.cs。这将准确告诉您应该使用哪些值来计算常用操作的授权标头。

    更新

    请将以下内容添加到您的请求标头中:

    "x-ms-documentdb-query-enablecrosspartition" = "True";
    

    这是对我有用的完整代码:

    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 = "DatabaseId"
    $containerId = "ContainerId"
    
    $itemResourceType = "docs"
    $itemResourceId = "dbs/"+$databaseId+"/colls/"+$containerId
    $itemResourceLink = "dbs/"+$databaseId+"/colls/"+$containerId+"/docs"
    $verbMethod = "POST"
    
    $requestUri = "$endpoint$itemResourceLink"
    
    $authKey = Generate-MasterKeyAuthorizationSignature -Verb $verbMethod -ResourceId $itemResourceId -ResourceType $itemResourceType -Date $xDate -MasterKey $MasterKey -KeyType $KeyType -TokenVersion $TokenVersion
    
    $queryJson = "{`"query`": `"SELECT * FROM test c WHERE c.id = 1 `", `"parameters`": []}"
    
    $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-query-enablecrosspartition" = "True";
        }
    
    try {
        $result = Invoke-RestMethod -Uri $requestUri -Headers $header -Method $verbMethod -Body $queryJson -ContentType "application/query+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
    }
    

    【讨论】:

    • 漂亮的答案。我在最后一个案例中已经提到了$itemResourceIdstackoverflow.com/questions/61225910/…
    • 我已经尝试删除“/docs”,但仍然出现错误。我已经研究过的 C# 示例。它对我有用。
    • 401 错误还是别的什么?您可能想发布整个代码。
    • 400 错误请求错误。我尝试了带和不带的端点 URL:443 testcosmos.documents.azure.com testcosmos.documents.azure.com:443
    • 非常感谢。它工作。它需要添加单个标题。可悲的是我什至没有想到。
    猜你喜欢
    • 2020-07-28
    • 2018-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多