You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure DevOps流水线通过专用端点访问Blob Storage授权失败问题

Azure DevOps流水线通过专用端点访问Blob Storage遇AuthorizationFailure问题解决

问题根源

你的Blob存储账户已配置为仅允许专用端点访问,但Azure DevOps默认的微软托管代理处于公网环境,无法通过专用端点访问Blob资源。即使SAS令牌权限配置正确,请求仍会被存储账户的防火墙拦截,触发AuthorizationFailure错误。

可行性确认

完全可以通过Azure DevOps流水线使用专用端点访问Blob Storage,核心是让流水线代理处于能访问专用端点的网络环境中。

解决方案步骤

1. 部署自托管代理到专用端点所在VNet

  • 在Blob存储专用端点所属的虚拟网络(VNet)中创建Azure虚拟机(VM)
  • 在该VM上安装并注册Azure DevOps自托管代理,将其加入你的项目代理池
  • 配置VM的网络安全组(NSG),允许出站访问Azure DevOps服务所需的端口和地址

2. 验证专用端点DNS解析

  • 在自托管代理VM上执行命令:nslookup <你的存储账户名>.blob.core.windows.net
  • 确认返回结果为专用端点的私有IP地址,而非公网IP。若解析异常,需检查VNet的DNS配置:确保使用Azure专用DNS区域privatelink.blob.core.windows.net,或自定义DNS服务器已正确配置该私有区域的解析规则

3. 配置流水线使用自托管代理

在流水线YAML中指定自托管代理池:

pool:
  name: <你的自托管代理池名称>

4. 确认SAS令牌有效性

  • 检查生成SAS的代码:resource_types和permission已覆盖流水线所需操作(你的代码中已包含容器和Blob的读写、列表权限,此部分无问题)
  • 确保生成SAS时使用UTC时间,避免时区差异导致令牌提前过期

5. 检查存储账户防火墙设置

  • 进入Blob存储账户的「网络」设置,确认已启用专用端点,防火墙规则设置为「选定网络」,未添加公网IP范围
  • 无需勾选「允许受信任的Microsoft服务访问此存储账户」,自托管代理通过专用端点访问,不属于该范畴

替代方案:使用Azure AD托管身份(更安全)

若不想维护自托管代理,可采用以下方式:

  • 为Azure DevOps流水线启用系统托管身份或用户托管身份
  • 为该身份分配Blob存储的Storage Blob Data Contributor等适配角色
  • 在流水线中通过Azure CLI/PowerShell,利用托管身份获取访问令牌访问Blob,无需SAS令牌,同时确保存储账户防火墙允许该身份访问(或通过专用端点)

测试验证

在自托管代理VM上手动运行以下代码,验证访问是否正常:

from azure.storage.blob import BlobServiceClient, generate_account_sas, ResourceTypes, AccountSasPermissions
from datetime import datetime, timedelta

ACCOUNT_NAME = "你的存储账户名"
CONTAINER_NAME = "你的容器名"
account_url = f"https://{ACCOUNT_NAME}.blob.core.windows.net"
account_key = '你的存储账户密钥'

sas_token = generate_account_sas(
    account_name=ACCOUNT_NAME,
    account_key=account_key,
    resource_types=ResourceTypes(container=True, object=True),
    permission=AccountSasPermissions(read=True, write=True, list=True),
    expiry=datetime.utcnow() + timedelta(hours=1)
)

# 测试连接与列表Blob
blob_service_client = BlobServiceClient(account_url=account_url, credential=sas_token)
container_client = blob_service_client.get_container_client(CONTAINER_NAME)
blobs = list(container_client.list_blobs())
print(f"成功获取{len(blobs)}个Blob")

内容的提问来源于stack exchange,提问作者LUCAS XX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:56:11