はじめに
AzureのREST APIでBlobをダウンロードしたのですが忘れそうなのでメモです。Pythonで実行しました。共有キーによる認証でクライアント側がアクセスキーを知っている必要があるのでサーバからリクエストするときとかはこれで大丈夫かな?
環境
- Azureのストレージアカウントを持っている
- Python3.6(Anaconda)
HTTPリクエストをするのでpip install requests
しておきます。urllibが使える人はそっちでも大丈夫です。
やること
雑にコードを載せます。myaccountはストレージアカウント名、mycontainerはコンテナ名、myaccess_keyはアクセスキーでそれぞれ自分のものに置き換えてください。アクセスキーはここを参考に確認してください。
# 必要なライブラリのimport
import base64
import hashlib
import hmac
from urllib.parse import quote, unquote
import requests
import datetime
# 自分のアクセスキーで置き換える
access_key = 'myaccess_key'
# 操作したいblobのurl
blob_url = 'https://myaccount.blob.core.windows.net/mycontainer/test.png'
# 必須のヘッダー
x_ms_date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT') #曜日, dd 月 yyyy hh:mm:ss GMT
x_ms_version = "2020-08-04"
# 改行の数などはこの通りに
# 最後の行はクエリとかがある場合はそれもいるっぽい(未確認)
StringToSign = \
"GET\n\n\n\n\n\n\n\n\n\n\n\n"+ \
"x-ms-date:" + x_ms_date + "\n" + \
"x-ms-version:" + x_ms_version + "\n" + \
"/myaccount/mycontainer/test.png"
# 使う関数を定義
def url_quote(url):
return quote(url)
def encode_base64(data):
if isinstance(data, str):
data = data.encode('utf-8')
encoded = base64.b64encode(data)
return encoded.decode('utf-8')
def decode_base64_to_bytes(data):
if isinstance(data, str):
data = data.encode('utf-8')
return base64.b64decode(data)
def decode_base64_to_text(data):
decoded_bytes = decode_base64_to_bytes(data)
return decoded_bytes.decode('utf-8')
def decode_base64_to_text(data):
decoded_bytes = decode_base64_to_bytes(data)
return decoded_bytes.decode('utf-8')
def sign_string(key, string_to_sign, key_is_base64=True):
if key_is_base64:
key = decode_base64_to_bytes(key)
else:
if isinstance(key, str):
key = key.encode('utf-8')
if isinstance(string_to_sign, str):
string_to_sign = string_to_sign.encode('utf-8')
signed_hmac_sha256 = hmac.HMAC(key, string_to_sign, hashlib.sha256)
digest = signed_hmac_sha256.digest()
encoded_digest = encode_base64(digest)
return encoded_digest
# アクセスキーとStringToSignを使って署名を作成
signature = sign_string(access_key,StringToSign)
# headerには以下の3つを入れる(PUTとかだと他にもいるかも)
headers = {
"x-ms-date": x_ms_date,
"x-ms-version":x_ms_version,
"Authorization":"SharedKey myaccount:"+signature
}
# 署名を使ってREST APIをたたく
response = requests.get(blob_url,headers=headers)
# 保存用
if response.status_code >= 400:
print(response.text)
else:
results = response.content
with open('./test.png', 'wb') as f:
f.write(results)
あいまいなところがありすみません。
StringToSignの改行には意味があります。詳しくは**ここ**をご覧ください。
リクエストヘッダーに必要なものやURL、メソッドについては**REST APIのリファレンス**を参照してください。
関数はAzure SDK for Pythonを参考にしてます(リンク)。
おわりに
requestsじゃなくてurllib使えるならPython標準ライブラリだけで実装できるのでAWS Lambda使うときにはLayerを追加しなくて済みます。
何か間違いがあればご指摘よろしくお願いします。