【问题标题】:Get blob in azure Blob Storage with API shared key使用 API 共享密钥在 Azure Blob 存储中获取 Blob
【发布时间】:2019-06-03 02:52:17
【问题描述】:

我在 Azure blob 存储中有一个(私有)blob,它是通过一个对其具有读写访问权限的帐户写入的(它是由 terraform 通过此帐户写入的)。我正在尝试通过 Python(没有 Azure SDK)获取它,但我一直无法。

我的要求如下:

import datetime
import requests


key = ...
secret = ...
now = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
# the required settings, as per https://docs.microsoft.com/en-us/rest/api/storageservices/get-blob
headers = {'Authorization': 'SharedKey {}:{}'.format(key, secret),
           'Date': now,
           'x-ms-version': '2018-03-28'
           }

storage_account = ...
container = ...
url = 'https://{}.blob.core.windows.net/{}/terraform.tfstate'.format(storage_account, container)

response = requests.get(url, headers=headers)

print(response.status_code)
print(response.text)

这会产生

400
<?xml version="1.0" encoding="utf-8"?><Error>
<Code>OutOfRangeInput</Code><Message>One of the request inputs is out of range. 
RequestId:...
Time:...</Message></Error>

我已验证此文件存在(存储资源管理器),并且当我通过控制台访问它时,我会得到与上述相同的 URL,但带有额外的 GET 参数。


对于那些想知道的人:我决定不使用 Azure SDK for Python 的原因是:我只需要获取一个 blob 和 pip install azure[blob] 就会向项目添加 88 依赖项(IMO 对这么简单的任务)。

【问题讨论】:

    标签: python azure-blob-storage


    【解决方案1】:

    所以,原因是文档中提到的signature是从请求中构造出来的,并详细描述了here

    与 Python 3 等效的是:

    import base64
    import hmac
    import hashlib
    import datetime
    
    import requests
    
    
    def _sign_string(key, string_to_sign):
        key = base64.b64decode(key.encode('utf-8'))
        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 = base64.b64encode(digest).decode('utf-8')
        return encoded_digest
    
    
    def get_blob(storage_account, token, file_path):
        now = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
        url = 'https://{account}.blob.core.windows.net/{path}'.format(account=storage_account, path=file_path)
        version = '2018-03-28'
        headers = {'x-ms-version': version,
                   'x-ms-date': now}
    
        content = 'GET{spaces}x-ms-date:{now}\nx-ms-version:{version}\n/{account}/{path}'.format(
            spaces='\n'*12,
            now=now,
            version=version,
            account=storage_account,
            path=file_path
        )
    
        headers['Authorization'] = 'SharedKey ' + storage_account + ':' + _sign_string(token, content)
    
        response = requests.get(url, headers=headers)
    
        assert response.status_code == 200
        return response.text
    

    其中file_path 的格式为{container}/{path-in-container}

    使用这个sn-p还是优于给项目添加88个依赖的。

    【讨论】:

    • 你在哪里找到GET{spaces}x-ms-date:{now}\nx-ms-version:{version}\n/{account}/{path}格式的文档?
    • @Patrick,关于 azure CLI 的 (Python) 源代码。只是对其进行了逆向工程。
    • 我很幸运能找到这篇文章。我在 powershell 中尝试了同样的方法,但在正确的格式和所需的东西上遇到了一些麻烦。 REST API 文档中没有任何内容(或者我无法找到)...
    猜你喜欢
    • 2013-06-19
    • 2019-11-08
    • 2021-05-24
    • 2016-02-05
    • 2020-11-18
    • 2020-09-19
    • 2018-05-07
    • 2018-12-05
    • 1970-01-01
    相关资源
    最近更新 更多