Python生成Azure认证令牌并列出资源组时遇403授权失败问题求助
问题:Python生成Azure认证令牌调用资源组API报403授权错误
问题详情
尝试用Python生成Azure认证令牌并列出资源组,使用以下代码:
from azure.identity import ClientSecretCredential import requests subscription_id = 'MYSUBID' client_id = 'MYCLIENTID' client_secret = 'MYSECRETVALUE' tenant_id = 'MYTENANTID' # Create a ClientSecretCredential object credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret) url = f"https://management.azure.com/subscriptions/{subscription_id}/resourcegroups?api-version=2021-04-01" # Get an access token for the Azure Management API access_token = credential.get_token("https://management.azure.com/.default") # Make the GET request to retrieve a list of resource groups headers = { "Authorization": f"Bearer {access_token}" } response = requests.get(url, headers=headers) if response.status_code == 200: resource_groups = response.json() for rg in resource_groups['value']: print(rg['name']) else: print(response.status_code, "-" ,response.text)
运行后出现403错误:
403 - {"error":{"code":"AuthorizationFailed","message":"The client 'f89e9744-3f48-444c-bf6f-525d15974a46' with object id 'f89e9744-3f48-444c-bf6f-525d15974a46' does not have authorization to perform action 'Microsoft.Resources/subscriptions/resourcegroups/read' over scope '/subscriptions/MYSUBID' or the scope is invalid. If access was recently granted, please refresh your credentials."}}
但使用微软官网的REST API测试工具能成功列出资源组,且两者使用的Bearer令牌不同。
原因分析
- 权限不匹配:代码中使用的是服务主体(client_id对应的身份),而官网测试工具使用的是你当前登录的用户身份。用户身份有读取资源组的权限,但服务主体未被授予对应权限,导致授权失败。
- 令牌使用错误:
credential.get_token()返回的是AccessToken对象,直接拼接进Authorization头会导致令牌格式错误,进一步触发权限验证问题。
解决步骤
- 给服务主体分配订阅级读取权限
登录Azure门户,找到目标订阅,进入「访问控制(IAM)」,点击「添加」→「添加角色分配」,选择「读者」角色,搜索并选中你的服务主体,完成权限分配。 - 修正令牌获取代码
将获取令牌的代码改为取AccessToken对象的token属性:access_token = credential.get_token("https://management.azure.com/.default").token - 等待权限生效
Azure权限分配可能需要1-5分钟生效,若刚完成权限分配,等待后再测试。
修正后的完整代码
from azure.identity import ClientSecretCredential import requests subscription_id = 'MYSUBID' client_id = 'MYCLIENTID' client_secret = 'MYSECRETVALUE' tenant_id = 'MYTENANTID' credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret) url = f"https://management.azure.com/subscriptions/{subscription_id}/resourcegroups?api-version=2021-04-01" access_token = credential.get_token("https://management.azure.com/.default").token headers = { "Authorization": f"Bearer {access_token}" } response = requests.get(url, headers=headers) if response.status_code == 200: resource_groups = response.json() for rg in resource_groups['value']: print(rg['name']) else: print(response.status_code, "-" ,response.text)
内容的提问来源于stack exchange,提问作者Navi
相关产品推荐
相关产品推荐

