Azure Python SDK使用证书认证Azure Gov时调用订阅列表接口挂起无响应
解决方案
1. 修复signed_session属性缺失报错
该报错是由于新旧Azure SDK凭证体系不兼容导致的:
- 直接升级
azure-mgmt-subscription到3.0.0及以上稳定版本、azure-mgmt-resource到16.0.0及以上稳定版本,新版本SDK原生支持azure.identity体系下的CertificateCredential,无需额外适配器。 - 移除之前引入的第三方适配器相关代码。
2. 解决连接超时问题
同一实例下Azure CLI可正常登录说明网络链路无问题,超时是SDK配置异常导致的,按以下步骤排查:
- 先在代码最开头(导入SDK包之前)配置主权云对应的全局环境变量,避免分散配置导致的端点不匹配:
无需再在os.environ["AZURE_AUTHORITY_HOST"] = "login.microsoftonline.us"CertificateCredential的初始化参数中手动传入authority参数。 - 检查Python运行环境的代理配置:Azure CLI会自动读取系统或自身配置的HTTP/HTTPS代理,Python进程如果没有继承对应环境变量会导致连接失败,可在代码中打印验证
HTTPS_PROXY、HTTP_PROXY、NO_PROXY三个环境变量是否和CLI配置一致,不一致的话手动在代码开头赋值。 - 打开SDK调试日志定位凭证失效原因:当前报错显示SDK fallback到了
EnvironmentCredential进行认证,说明你配置的CertificateCredential本身已经认证失败,在代码开头加入os.environ["AZURE_LOG_LEVEL"] = "debug"即可打印CertificateCredential的完整认证流程日志,常见失效原因包括:- PEM证书包含私钥但设置了密码,未在
CertificateCredential初始化时传入password参数 - 证书格式不符合要求,缺失私钥或证书链
- 租户ID、客户端ID和证书不匹配
- PEM证书包含私钥但设置了密码,未在
3. 修正后的可运行代码示例
import logging import os import boto3 from msrestazure.azure_cloud import AZURE_US_GOV_CLOUD as CLOUD from azure.identity import CertificateCredential from azure.mgmt.subscription import SubscriptionClient # 提前配置全局环境变量 os.environ["AZURE_AUTHORITY_HOST"] = CLOUD.endpoints.active_directory # 打开调试日志,排查问题完成后可移除 os.environ["AZURE_LOG_LEVEL"] = "debug" # Setup logging logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) logging.basicConfig(level=logging.INFO) # Constants CERT_PATH = '/tmp/cert.pem' AZURE_TENANT_ID = os.environ['AZURE_TENANT_ID'] AZURE_CLIENT_ID = os.environ['AZURE_CLIENT_ID'] AZURE_SDK_S3_BUCKET = os.environ['AZURE_SDK_S3_BUCKET'] # 如有代理可在此处配置,替换为你实际的代理地址 # os.environ["HTTPS_PROXY"] = "http://your-proxy:port" s3 = boto3.client('s3') s3.download_file(AZURE_SDK_S3_BUCKET, 'certs/cert.pem', CERT_PATH) # Setup Azure credentials credential = CertificateCredential( tenant_id=AZURE_TENANT_ID, client_id=AZURE_CLIENT_ID, certificate_path=CERT_PATH, # 如果证书有密码,补充下面的参数 # password="your-cert-password" ) logger.info(f'tenant_id = {AZURE_TENANT_ID}, client_id = {AZURE_CLIENT_ID}') sub_client = SubscriptionClient( credential=credential, base_url=CLOUD.endpoints.resource_manager ) subscription = next(sub_client.subscriptions.list()) logger.info(f'Fetched subscription {subscription.subscription_id}')
内容的提问来源于stack exchange,提问作者Bryan Fennell
相关产品推荐
相关产品推荐

