bash - 使用 bash、curl 访问 Azure Blob 存储

标签 bash azure curl openssl

我正在尝试使用 REST API 从 bash 脚本使用 Azure Blob 存储服务。我知道可以使用各种其他工具或语言来完成此任务,但我想将其作为 bash 脚本来完成。

下面的脚本尝试列出 Azure 存储容器中的 blob。

此脚本会导致身份验证错误。根据 REST API ( reference ) 文档,签名字符串和 header 看起来正确。我怀疑问题可能在于处理签名过程的各个部分。

有人成功使用 bash 和curl 访问Azure 或其他提供商等云存储资源吗?

#!/bin/bash

# List the blobs in an Azure storage container.

echo "usage: ${0##*/} <storage-account-name> <container-name> <access-key>"

storage_account="$1"
container_name="$2"
access_key="$3"

blob_store_url="blob.core.windows.net"
authorization="SharedKey"

request_method="GET"
request_date=$(TZ=GMT date "+%a, %d %h %Y %H:%M:%S %Z")
storage_service_version="2011-08-18"

# HTTP Request headers
x_ms_date_h="x-ms-date:$request_date"
x_ms_version_h="x-ms-version:$storage_service_version"

# Build the signature string
canonicalized_headers="${x_ms_date_h}\n${x_ms_version_h}"
canonicalized_resource="/${storage_account}/${container_name}"

string_to_sign="${request_method}\n\n\n\n\n\n\n\n\n\n\n\n${canonicalized_headers}\n${canonicalized_resource}\ncomp:list\nrestype:container"

# Decode the Base64 encoded access key, convert to Hex.
decoded_hex_key="$(echo -n $access_key | base64 -d -w0 | xxd -p -c256)"

# Create the HMAC signature for the Authorization header
signature=$(echo -n "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$decoded_hex_key" | sed 's/^.*= //' | base64 -w0)

authorization_header="Authorization: $authorization $storage_account:$signature"

curl \
  -H "$x_ms_date_h" \
  -H "$x_ms_version_h" \
  -H "$authorization_header" \
  "https://${storage_account}.${blob_store_url}/${container_name}?restype=container&comp=list"

更新 - 存储服务错误以及脚本生成的相应签名字符串。

以下是存储服务针对 AuthenticationFailed 错误返回的内容。

<?xml version="1.0" encoding="utf-8"?>
<Error>
  <Code>AuthenticationFailed</Code>
  <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:27e6337e-52f3-4e85-98c7-2fabaacd9ebc
Time:2013-11-21T22:10:11.7029042Z</Message>
  <AuthenticationErrorDetail>The MAC signature found in the HTTP request
'OGYxYjk1MTFkYmNkMCgzN2YzODQwNzcyNiIyYTQxZDg0OWFjNGJiZDlmNWY5YzM1ZWQzMWViMGFjYTAyZDY4NAo='
is not the same as any computed signature. Server used following string to sign:
'GET

x-ms-date:Thu, 21 Nov 2013 22:10:11 GMT
x-ms-version:2011-08-18
/storage_account_name/storage_container
comp:list
restype:container'
  </AuthenticationErrorDetail>
</Error>

接下来是脚本生成的string_to_sign

GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 21 Nov 2013 22:10:11 GMT\nx-ms-version:2011-08-18\n/storage_account_name/storage_container\ncomp:list\nrestype:container

最佳答案

我能够让它工作。 这段代码有两个问题,第一,正如 Patrick Park 指出的,用 printf 替换了 echo -n。第二个是用 openssl 上的 -binary 选项替换 sed 魔法。

比较原来的:

signature=$(echo -n "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$decoded_hex_key" -binary | sed 's/^.*= //' | base64 -w0)

固定:

signature=$(printf "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$decoded_hex_key" -binary |  base64 -w0)

需要进行 echo 更改,因为 echo -n 不会将 \n 转换为实际的换行符。

需要 -binary 更改,因为即使您删除了错误的部分,openssl 仍然以 ascii 编码的十六进制格式(而不是二进制格式)输出签名。因此,在传递给 base64 后,结果是十六进制表示的 b64 编码版本,而不是原始值。

关于bash - 使用 bash、curl 访问 Azure Blob 存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20103258/

相关文章:

bash - sed问题:-bash:意外 token `('附近的语法错误

linux - 使用 Ansible 在特定时间安排命令

authentication - 使用从另一个 IdP 返回的 SAML 2.0 工件在 MS Azure AD 中进行身份验证

c# - 如何通过 REST API 创建 Azure Application Insights 的新实例

python - Python 中的 Curl 等价物

android - 尝试构建 Android 应用程序时 Cordova 失败并出现错误 "Command failed with exit code 2"Linux

python - 使用 * 对 bash 命令进行子处理

caching - 保存到 Redis 缓存时性能较差(使用 ServiceStack.Redis)

curl - Crontab cron 作业不会使用带参数的 url 运行

json - 无法在 json --data 中使用变量