如何为 python 脚本提供对 Azure Blob 容器的有限访问权限

How to give a python script limited access to azure blob container

我希望我的 python 脚本能够以 azure 的形式将新的 blob 附加到我的容器中。使用共享访问签名 (SAS) 似乎是可行的方法。

但我不知道如何使用它们。我不想通过为脚本提供存储帐户密钥来为脚本提供对 Azure 帐户的完全访问权限,因此使用 SAS 并限制脚本创建和删除删除、获取和列表的能力似乎没问题。 但是如何在脚本中使用令牌?

这是我的测试代码:

#!/usr/bin/env python3

import requests
from azure.storage.blob import BlockBlobService, ContainerPermissions, ContentSettings

# this is only for testing, account key will be removed later

account_name = 'myaccountname'
account_key = 'myaccountkey'
container_name = 'mycontainer'
existing_file = 'existing_file.jpg'
new_file = 'test.jpg'

service = BlockBlobService(
    account_name=account_name,
    account_key=account_key
)
# There are two ways to create a permission
# 1. Assign boolean values to `read`/`add`/`create`/`write`/`delete` operation
# permission = BlobPermissions(read=True, add=True, create=True, write=True, delete=True)
# 2. Just simply assign a string to `_str`(A string representing the permissions) like `racwd` which means assign True to all operation
permission = ContainerPermissions(write=True)
sas = service.generate_container_shared_access_signature(
    container_name=container_name,
    permission=permission,
    protocol='https'
)
print(sas)

# Here begins the real script

service = BlockBlobService(
    account_name=account_name,
    sas_token=sas
)

assert service.exists(container_name=container_name, blob_name=existing_file)

service.create_blob_from_path(
        container_name=container_name,
        blob_name=new_file,
        file_path='./%s' % new_file,
        content_settings=ContentSettings(content_type=mimetypes.guess_type('./%s' % new_file)[0]),
        validate_content=True
)

r = requests.head('https://%s.blob.core.windows.net/%s/%s' % (account_name, container_name, new_file), timeout=2)
assert r.status_code == 200

service.exists() 调用失败:azure.common.AzureHttpError: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

正如@DavidMakogon 所说,这听起来像是指 blog。确实,这对您的问题有帮助。

根据您的描述,您似乎已经知道如何使用这些方法generate_account_shared_access_signature with AccountPermission, generate_container_shared_access_signature with ContainerPermission, generate_blob_shared_access_signature with BlobPermission生成不同级别(帐户、容器、blob)的 SAS,如下面的 blob 级别的代码。

from azure.storage.blob import BlockBlobService, BlobPermissions

account_name = '<your storage account name>'
account_key = '<your storage account key>'
container_name = 'mycontainer'

service = BlockBlobService(account_name=account_name, account_key=account_key)
# There are two ways to create a permission
# 1. Assign boolean values to `read`/`add`/`create`/`write`/`delete` operation
# permission = BlobPermissions(read=True, add=True, create=True, write=True, delete=True)
# 2. Just simply assign a string to `_str`(A string representing the permissions) like `racwd` which means assign True to all operation
permission = BlobPermissions(_str="racwd")
sas = service.generate_blob_shared_access_signature(container_name, 'test.jpg', permission)
print sas

使用 SAS 在 Python 脚本中访问 Azure Blob 存储,如下所示。

  1. 使用SAS调用Blob Storgae RESTAPI,可以参考文档Service SAS Examples将SAS附加到bloburl作为查询参数进行相关操作,如如下。
GET https://myaccount.blob.core.windows.net/pictures/profile.jpg?sv=2012-02-12&st=2009-02-09&se=2009-02-10&sr=c&sp=r&si=YWJjZGVmZw%3d%3d&sig=dD80ihBh5jfNpymO5Hg1IdiJIEvHcJpCMiCMnN%2fRnbI%3d   
HTTP/1.1  
Host: myaccount.blob.core.windows.net  
x-ms-date: <date>
  1. 在带有Azure Storage SDK的Python脚本中使用SAS,类BlockBlobService & BaseBlobService的构造方法有一个参数sas_token,解释如下,你可以通过sas 值。

sas_token (str) – A shared access signature token to use to authenticate requests instead of the account key. If account key and sas token are both specified, account key will be used to sign. If neither are specified, anonymous access will be used.

例如,使用 SAS 的 BlockBlobService 的代码如下。

service = BlockBlobService(sas_token=sas)

我解决了。对于任何感兴趣的人,这里是工作脚本:

#!/usr/bin/env python3

import mimetypes
mimetypes.init()
from datetime import datetime, timedelta

import requests
from azure.storage.blob import BlockBlobService, ContainerPermissions, ContentSettings

account_name = 'myaccount'
account_key = 'mykey'
container_name = 'mycontainer'
new_file = 'new_pic.jpg'
existing_file = 'old_pic.jpg'

service = BlockBlobService(account_name=account_name, account_key=account_key)
permission = ContainerPermissions(read=True, write=True)
sas = service.generate_container_shared_access_signature(container_name=container_name, permission=permission,
        protocol='https', start=datetime.now(), expiry=datetime.now() + timedelta(days=1))
print(sas)

service = BlockBlobService(account_name=account_name, sas_token=sas)

assert service.exists(container_name=container_name, blob_name=existing_file)

service.create_blob_from_path(
        container_name=container_name,
        blob_name=new_file,
        file_path=new_file,
        content_settings=ContentSettings(content_type=mimetypes.guess_type(new_file)[0]),
        validate_content=True
)

r = requests.head('https://%s.blob.core.windows.net/%s/%s' % (account_name, container_name, new_file), timeout=2)
assert r.status_code == 200

重要的是使用 ContainerPermissions 并正确设置日期时间。时区是你最糟糕的噩梦!