使用Python列出Blob遇AuthorizationPermissionMismatch错误,AZ CLI正常
问题描述
我有一个已存在的存储账户和容器,通过AZ CLI可以正常列出所有Blob:
[ ~ ]$ az storage blob list --account-name storageaccount20122022 --container-name test There are no credentials provided in your command and environment, we will query for account key for your storage account. It is recommended to provide --connection-string, --account-key or --sas-token in your command as credentials. You also can add `--auth-mode login` in your command to use Azure Active Directory (Azure AD) for authorization if your login account is assigned required RBAC roles. For more information about RBAC roles in storage, visit https://docs.microsoft.com/azure/storage/common/storage-auth-aad-rbac-cli. In addition, setting the corresponding environment variables can avoid inputting credentials in your command. Please use --help to get more information about environment variable usage. [ { "container": "test", "content": "", ... } ]
我想用Python实现同样的功能,写了如下脚本:
import sys from azure.identity import DefaultAzureCredential from azure.storage.blob import BlobServiceClient def list_blobs_using_cli_credential(account_name, container_name): credential = DefaultAzureCredential() # 也试过AzureCliCredential() blob_service_client = BlobServiceClient( account_url=f"https://{account_name}.blob.core.windows.net", credential=credential ) container_client = blob_service_client.get_container_client(container_name) print(f"Listing blobs in {account_name}/{container_name} ...") try: blobs = container_client.list_blobs() for blob in blobs: print(blob.name) except Exception as e: print(f"Error listing blobs: {e}") if __name__ == "__main__": account_name = sys.argv[1] container_name = sys.argv[2] list_blobs_using_cli_credential(account_name, container_name)
但在同一个Shell中运行该脚本时出现权限错误:
[ ~ ]$ python list-blobs.py storageaccount20122022 test Listing blobs in storageaccount20122022/test ... Error listing blobs: This request is not authorized to perform this operation using this permission. RequestId:466b2647-201e-0022-13fd-918e18000000 Time:2024-04-19T01:59:22.6413231Z ErrorCode:AuthorizationPermissionMismatch Content: <?xml version="1.0" encoding="utf-8"?><Error><Code>AuthorizationPermissionMismatch</Code><Message>This request is not authorized to perform this operation using this permission. RequestId:466b2647-201e-0022-13fd-918e18000000 Time:2024-04-19T01:59:22.6413231Z</Message></Error>
我能通过Python列出存储账户和容器,但无法对Blob执行任何操作(列出、删除、上传),而AZ CLI却能正常执行。我在两个完全独立的Azure账户中测试过,其中一个账户我是所有者,但问题依旧。
请问:
- AZ CLI是如何自动获取权限执行Blob操作的?
- 如何在Python代码中实现相同的功能?
解答
一、AZ CLI自动获取权限的方式
当你没有在az storage blob list命令中指定凭证(连接字符串、账户密钥、SAS令牌)时,AZ CLI会按优先级尝试以下两种授权方式:
- 优先获取存储账户密钥:CLI调用Azure管理API读取目标存储账户的账户密钥,然后用该密钥进行Shared Key授权。这种方式不需要Blob相关的RBAC权限,只要你的登录账户有读取存储账户密钥的权限(比如
Storage Account Contributor或更高权限,所有者角色包含此权限)就能生效。 - 回退到Azure AD授权:如果无法获取账户密钥,CLI才会尝试用当前登录的Azure AD身份授权,这时候需要你的账户被分配Blob数据相关的RBAC角色(比如
Storage Blob Data Reader)。
你看到的CLI输出提示已经明确说明了这个逻辑,这也是你作为所有者能正常操作的原因——所有者权限允许读取存储账户密钥,进而完成Blob操作的授权。
二、Python代码实现相同功能的方法
你的Python脚本使用的是Azure AD身份授权,但仅仅是账户所有者并不自动拥有Blob数据的操作权限(所有者是管理层面角色,而非数据层面)。要实现和CLI一致的行为,有两种可选方案:
方案1:模拟CLI优先使用账户密钥的逻辑
通过Azure管理API获取存储账户密钥,再用该密钥初始化BlobServiceClient:
import sys from azure.identity import DefaultAzureCredential from azure.mgmt.storage import StorageManagementClient from azure.storage.blob import BlobServiceClient def list_blobs_using_account_key(account_name, container_name, subscription_id, resource_group_name): # 获取存储账户密钥 credential = DefaultAzureCredential() storage_client = StorageManagementClient(credential, subscription_id) keys = storage_client.storage_accounts.list_keys(resource_group_name, account_name) account_key = keys.keys[0].value # 用账户密钥初始化BlobServiceClient blob_service_client = BlobServiceClient( account_url=f"https://{account_name}.blob.core.windows.net", credential=account_key ) container_client = blob_service_client.get_container_client(container_name) print(f"Listing blobs in {account_name}/{container_name} ...") try: blobs = container_client.list_blobs() for blob in blobs: print(blob.name) except Exception as e: print(f"Error listing blobs: {e}") if __name__ == "__main__": account_name = sys.argv[1] container_name = sys.argv[2] subscription_id = sys.argv[3] resource_group_name = sys.argv[4] list_blobs_using_account_key(account_name, container_name, subscription_id, resource_group_name)
方案2:给账户分配Blob数据RBAC角色
如果你想继续使用Azure AD身份授权,需要给登录账户分配Blob数据相关的RBAC角色,比如:
Storage Blob Data Reader:仅允许读取BlobStorage Blob Data Contributor:允许读写Blob
分配范围可以是存储账户、容器或资源组。角色分配生效后(通常需要几分钟),你的原Python脚本就能正常执行Blob操作。
内容的提问来源于stack exchange,提问作者MLu
相关产品推荐
相关产品推荐

