Доступ к памяти Azure с использованием bash, завитка

Я пытаюсь использовать службу хранения брандмауэра Azure с bash script с помощью REST API. Я знаю, что это можно сделать с использованием других инструментов или языков, однако я хотел бы сделать это как bash script.

Ниже приведена script попытка перечислить капли в контейнере хранения Azure.

Этот script приводит к ошибке аутентификации. Строка подписи и заголовки выглядят правильно на основе API REST API (ссылка). Я подозреваю, что проблема может заключаться в том, чтобы манипулировать различными частями процесса подписания.

Кто-нибудь успешно использовал bash и завивал для доступа к облачным ресурсам хранилища, таким как 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"

Обновить. Ошибка службы хранения и соответствующая строка подписи, созданная script.

Ниже приведена служба хранения для ошибки 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, создаваемый script.

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

Ответ 1

Я смог заставить его работать. В этом коде были две вещи: первая, как заметил Патрик Парк, заменяет echo -n на printf. Второй заменил магию sed параметром -binary на openssl.

Сравните оригинал:

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 -n не преобразует \n в фактические строки новой строки.

Требуется изменение -binary, потому что даже если вы удаляете плохую часть, openssl все равно выводит подпись в ascii-encoded-hex, а не в двоичную. Поэтому после того, как он был передан в base64, результатом была кодированная версия шестнадцатеричного представления b64 вместо исходного значения.

Ответ 2

Используйте Fiddler (или эквивалент на вашей платформе), чтобы перехватить вызов в Windows Azure Storage. При сбое это покажет вам строку, которую Служба хранения использовала для аутентификации вызова, и вы можете сравнить ее с той, которую вы использовали.

Ответ 3

Если посмотреть на документацию REST API и ваш код выше, я считаю, что существует проблема с тем, как вы создаете строку canonicalized_resource. В этой строке отсутствуют параметры запроса. Строка canonicalized_resource должна быть:

canonicalized_resource="/${storage_account}/${container_name}\ncomp:list\nrestype:container"

Ответ 4

Похоже, что openssl dgst не генерирует правильный HMAC для вас. Я написал простую программу в C, которая делает следующее:

  • Забирает base64-кодированный ключ из командной строки и декодирует его в двоичном формате.
  • Считывает строку для входа со стандартного ввода.
  • Использует процедуру libcrypto HMAC() для генерации подписи.
  • base64-кодирует подпись и выводит результат на стандартный вывод.

Затем я заменил конвейер openssl dgst в вашем script с вызовом моей программы, и он сделал трюк.

Обратите внимание, что вывод, который вы получаете от Azure, имеет XML-wrapped и base-64, поэтому вам нужно будет найти какой-то код для разбора/преобразования.

Ответ 5

используйте printf вместо echo (он работает для меня)

например:

ПОДПИСИ = printf "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt hexkey:$HEXKEY -binary | base64 -w0