感谢您的支持@Gaurav Mantri 和@Mark Brown。您的评论有助于避免一百万次被纸割伤而死亡:-)
我启动了一个存储库,在其中收集 Azure CLI bash 脚本。找到它在https://github.com/Krumelur/AzureScripts https://github.com/Krumelur/AzureScripts
让我回答我自己的问题并提供一个读取 CosmosDB 实例中现有数据库的脚本。
这将在浏览器窗口中启动交互式登录。
az login
指定我们要访问的资源。 URI 以及所需的参数值可以在以下位置找到:https://learn.microsoft.com/en-us/rest/api/cosmos-db/cosmosdb-resource-uri-syntax-for-rest https://learn.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 实例的“密钥”部分中找到的密钥相同。主键是 REST API 所说的“主”键。
masterKey=$(az cosmosdb keys list --name $comsosDbInstanceName --query primaryMasterKey --output tsv)
echo "Masterkey: $masterKey"
CosmosDB REST API 需要哈希授权标头:https://learn.microsoft.com/de-de/rest/api/cosmos-db/access-control-on-cosmosdb-resources#authorization-header https://learn.microsoft.com/de-de/rest/api/cosmos-db/access-control-on-cosmosdb-resources#authorization-header
要获取 HTTP 格式的日期,区域设置必须设置为 US。否则,日期名称将被本地化(例如德语)。
bash 不直接支持 HTTP 格式。要使其正常工作,请将当前时区设置为 GMT。时间格式如下所示:“mon, 27 apr 2020 09:46:58 gmt”。
now=$(env LANG=en_US TZ=GMT date '+%a, %d %b %Y %T %Z')
echo "Date: " $now
以预期格式连接动词、资源类型、资源 ID 和日期。 REST API 要求签名为小写。
我没有意识到的“小”问题:尾随换行符(\n
) 在输出字符串时总是被截断。这会破坏哈希值,因为 CosmosDB 期望它们在那里。这就是为什么在小写操作之后添加了两个尾随换行符。
signature="$(printf "%s" "$verb\n$resourceType\n$resourceId\n$now" | tr '[A-Z]' '[a-z]')\n\n"
echo "Signature: $signature"
使用 CosmosDB 实例的主键计算签名的哈希值。
看https://superuser.com/questions/1546027/what-is-the-openssl-equivalent-of-this-given-c-hashing-code/1546036 https://superuser.com/questions/1546027/what-is-the-openssl-equivalent-of-this-given-c-hashing-code/1546036了解为什么这如此棘手的详细信息。 tl;博士;版本: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"
Auth 字符串应采用 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"
可以使用“azrest”命令:
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