Azure ADLS Gen2 ACL:Pulumi 与 UAI 访问问题分析

2026-04-10#Azure#Pulumi

最近在使用 Pulumi 创建 Azure 上的基础设施时遇到这样一个现象:我在本地运行 pulumi up 成功创建资源,但同样使用绑定了 User Assigned Identity(UAI)的 CI/CD Pipeline 在运行 pulumi up 时,报错提示没有权限访问 Pulumi 使用的 blob 文件;而在某些项目中,Pipeline 的 UAI 则不会遇到该问题。

问题定义 🔗

当 Pipeline 使用的 UAI 无法更新 Storage Account 中的文件时,检查后发现被上传文件的 Owner 为我的个人身份(在本地执行 pulumi up 时创建),而 Pipeline 的 UAI 对该文件没有写权限。把文件的 Owner 切换为 UAI 后,Pipeline 即可写入文件。因此问题在很大程度上与 ADLS Gen2 的 ACL(访问控制列表)有关。

问题分析 🔗

经搜索得知:对于类型为 Azure Data Lake Storage (ADLS) Gen2 的 Storage Account,当开启 Hierarchical Namespace (HNS) 之后,会自动启用 Access Control Lists (ACLs) 。一些老旧的 Pulumi 项目并没有启用 HNS,因此不会出现这个问题。

但是还有一些 Storage Account,开启了 HNS 也不会出现这个问题。

对于启用了 Hierarchical Namespace(HNS)的 ADLS Gen2,会启用 POSIX 风格的 ACLs,这会引入数据平面(data plane)权限的概念。部分环境之所以没有问题,通常是因为用于访问的数据平面角色已经被正确授予。

对比可以发现:

  1. 出问题的 Pipeline 所使用的 UAI 仅被赋予 Contributor(管理平面角色);
  2. 没有问题的 Pipeline 所使用的 UAI 被授予 Storage Blob Data Owner(数据平面角色),或通过 PIM 激活了该数据平面角色。

搜索和分析:

  • 管理平面角色(如 Contributor)只控制资源管理,不保证对存储数据的读写权限。
  • 数据平面角色(如 Storage Blob Data OwnerStorage Blob Data Contributor)授予对 blob/filesystem 的读写权限。
  • 账户 Shared Key 或基于该密钥的 account/service SAS 为数据平面的“super-user”,可设置对象所有者并绕过 ACL;若主体能获取账户密钥(例如通过包含 listkeys 权限的管理角色),它就能用 Shared Key 在容器根目录创建文件/文件夹并成为创建者。
  • 对于启用 HNS 的 ADLS Gen2,ACL 在目录级生效:创建文件需要父目录的 executewrite 权限,修改文件需要文件的 write 权限。

结合实际情况:本地执行 pulumi up 的身份在首次写入时成为文件的 Owner,而 Pipeline 的 UAI(仅有管理平面 Contributor)并没有相应的数据平面写权限,因此无法修改或覆盖这些文件;而那些已被授予 Storage Blob Data Owner 的 UAI 则能正常读写。