使用bash、Azure命令行工具和睡觉接口访问cosmosdb-如何正确获取Token和Hash? [英] Use bash, Azure CLI and REST API to access CosmosDB - how to get token and hash right?

查看:61
本文介绍了使用bash、Azure命令行工具和睡觉接口访问cosmosdb-如何正确获取Token和Hash?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的最终目标是使用bash和Azure CLI将文档上传到现有的CosmosDB(SQL)实例。问题是:Azure CLI执行not offer a command to modify documents

为了解决此问题,我查看了az rest命令,并希望调用CosmosDB的睡觉接口来完成任务,但是经过几个小时的失败尝试后,我总是收到错误消息:

未授权({"code":"未授权","message":"输入授权 令牌无法为该请求提供服务。请检查预期有效载荷 是根据协议构建的,并检查正在使用的密钥。服务器 使用以下有效载荷签名:"get 星展银行 2020年4月25日星期六 13:50:22+0000 ‘ 活动ID:., Microsoft.Azure.Documents.Common/2.10.0"})

为简单起见,我现在尝试使用睡觉接口列出我的所有数据库,as described in the docs如果成功,请继续进行实际的文档上传。

我还在尝试按照in the docs提供的有关如何生成授权头的说明进行操作。

获取数据库列表的请求使用以下格式:GET https://{databaseaccount}.documents.azure.com/dbs

这是我的bash脚本,其中突出显示了问题/问题。

第1部分:获取访问令牌-问题:这是开始时的正确令牌吗?

masterKey=$(az cosmosdb keys list --name MYDBINSTANCENAME --query primaryMasterKey --output tsv)

第2部分:生成哈希有效负载-所有内容必须为小写

verb="get"
resourceType="dbs"
resourceLink="dbs"
now=$((date -uR) | tr '[A-Z]' '[a-z]')
payload="$verb
$resourceType
$resourceLink
$now
\n"

第3部分:散列有效负载-问题:此散列的结果与what the sample code in C# builds不同。因此,其中任何一个肯定是错误的,但都会导致相同的错误消息。

hashedPayload=$(printf $payload | openssl dgst -sha256 -hmac $masterKey -binary)

第4部分:创建所需的身份验证字符串并转换为base 64-问题:az rest一起使用是否需要base 64编码?

authString="type=master&ver=1.0&sig=$hashedPayload" | base64

第5部分:创建标头字符串。这是使用JSON表示法,因为空格分隔方法不起作用,although the docs state it should

headers="{"x-ms-date": "$now", "x-ms-version": "2018-12-31", "x-ms-documentdb-isquery": "true", "Content-Type": "application/query+json", "Authorization": "$authString"}"

第6部分:调用睡觉接口

az rest --verbose -m get -u "https://MYDBINSTANCENAME.documents.azure.com:443/dbs" --headers $headers

输出:

Request URL: 'https://MYDBINSTANCENAME.documents.azure.com:443/dbs'
Request method: 'GET'
Request headers:
    'User-Agent': 'AZURECLI/2.4.0 (HOMEBREW)'
    'Accept-Encoding': 'gzip, deflate'
    'Accept': '*/*'
    'Connection': 'keep-alive'
    'x-ms-date': 'sat, 25 apr 2020 13:54:10 +0000'
    'x-ms-version': '2018-12-31'
    'x-ms-documentdb-isquery': 'true'
    'Content-Type': 'application/query+json'
    'Authorization': 'type%3dmaster%26ver%...'
    'x-ms-client-request-id': 'a55357fe-411c-4adf-9fd6-1a255e010cca'
    'CommandName': 'rest'
    'ParameterSetName': '--verbose -m -u --headers'
Request body:
None
Response status: 401
Response headers:
    'Transfer-Encoding': 'chunked'
    'Content-Type': 'application/json'
    'Content-Location': 'https://MYDBINSTANCENAME.documents.azure.com/dbs'
    'Server': 'Microsoft-HTTPAPI/2.0'
    'x-ms-activity-id': '9119f8bd-53d9-4a87-8aff-a887ec652fed'
    'Strict-Transport-Security': 'max-age=31536000'
    'x-ms-gatewayversion': 'version=2.10.0'
    'Date': 'Sat, 25 Apr 2020 13:54:11 GMT'
Response content:
{"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: 'get
dbs

sat, 25 apr 2020 13:54:10 +0000

'
ActivityId: 9119f8bd-53d9-4a87-8aff-a887ec652fed, Microsoft.Azure.Documents.Common/2.10.0"}

推荐答案

感谢您@Gaurav Mantri和@Mark Brown的支持。您的评论帮助避免了一百万张剪纸造成的死亡:-)

我已经启动了一个存储库,我在其中收集Azure CLI bash脚本。请在https://github.com/Krumelur/AzureScripts

找到它

让我回答我自己的问题,并提供一个脚本来读取CosmosDB实例中的现有数据库。

这将在浏览器窗口中启动交互式登录。

az login
指定我们要访问的资源。URI和所需参数值可在以下位置找到:https://docs.microsoft.com/en-us/rest/api/cosmos-db/cosmosdb-resource-uri-syntax-for-rest

comsosDbInstanceName="YOUR INSTANCE NAME GOES HERE"
baseUrl="https://$comsosDbInstanceName.documents.azure.com/"
verb="get"
resourceType="dbs"
resourceLink="dbs"
resourceId=""
获取CosmosDB的主密钥。我们需要这个才能进入。这与可以在门户上CosmosDB实例的"Keys"部分找到的密钥相同。主密钥是睡觉接口中所说的"主密钥"。

masterKey=$(az cosmosdb keys list --name $comsosDbInstanceName --query primaryMasterKey --output tsv)
echo "Masterkey: $masterKey"

CosmosDB睡觉接口需要哈希授权头:https://docs.microsoft.com/de-de/rest/api/cosmos-db/access-control-on-cosmosdb-resources#authorization-header

若要以HTTP格式获取日期,区域设置必须设置为US。否则,日期名称将被本地化(例如,为德语)。

bash不直接支持HTTP格式。要使其正常工作,请将当前时区设置为GMT。时间格式如下:"星期一,2020年4月27日09:46:58 GMT"。

now=$(env LANG=en_US TZ=GMT date '+%a, %d %b %Y %T %Z')
echo "Date: " $now
采用预期格式的连接谓词、资源类型、资源ID和日期。睡觉接口要求签名为小写。

我没有意识到的"小"问题:输出字符串时,尾随换行符( )总是被截断。这会破坏散列,因为CosmosDB期望它们在那里。这就是在小写操作之后追加两个尾随换行符的原因。

signature="$(printf "%s" "$verb
$resourceType
$resourceId
$now" | tr '[A-Z]' '[a-z]')

"
echo "Signature: $signature"

使用CosmosDB实例的主键计算签名的哈希。 请参见https://superuser.com/questions/1546027/what-is-the-openssl-equivalent-of-this-given-c-hashing-code/1546036以了解这为何如此棘手的详细信息。tl;dr;version:openssl和服务器实现对哈希键的解释不同。

hexKey=$(printf "$masterKey" | base64 --decode | hexdump -v -e '/1 "%02x"')
echo "Hex key: " $hexKey
hashedSignature=$(printf "$signature" | openssl dgst -sha256 -mac hmac -macopt hexkey:$hexKey -binary | base64)
echo "Hashed signature: $hashedSignature"```

哈希签名应采用URL编码。当然,bash中没有内置的方式来实现这一点。天啊。 幸运的是,我们处理的是base64字符串。唯一需要编码的字符是等号,它变为"%3D"。

使用"type={typeoftoken}&;ver={tokenversion}&;sig={hashsignature}"

格式构建授权头
authString="type=master&ver=1.0&sig=$hashedSignature"
echo "Auth string: $authString"

身份验证字符串应采用URL编码。但当然,bash中没有内置的方式来实现这一点。天啊。 这不是完整的Base64编码,而只是更改了我们可能看到的字符:=->%3d,&;->%26,+=>%2b,/=>%2f

urlEncodedAuthString=$(printf "$authString" | sed 's/=/%3d/g' | sed 's/&/%26/g' | sed 's/+/%2b/g' | sed 's///%2f/g')
echo "URL encoded auth string: $urlEncodedAuthString"

通过组合基URL和资源链接进行API调用。

url="$baseUrl$resourceLink"
echo "URL: $url"

可以使用"az睡觉"命令:

az rest --verbose -m $verb -u $url --headers x-ms-date="$now" x-ms-version=2018-12-31 x-ms-documentdb-isquery=true Content-Type=application/query+json Authorization=$urlEncodedAuthString --debug

替代方案:使用curl

curl --request $verb -H "x-ms-date: $now" -H "x-ms-version: 2018-12-31" -H "x-ms-documentdb-isquery: true" -H "Content-Type: application/query+json" -H "Authorization: $urlEncodedAuthString" $url

这篇关于使用bash、Azure命令行工具和睡觉接口访问cosmosdb-如何正确获取Token和Hash?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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