Azure Data Lake Storage 中的访问控制列表 (ACL)

Azure Data Lake Storage 实施一个访问控制模型,该模型支持 Azure 基于角色的访问控制 (Azure RBAC) 和类似于 POSIX 的访问控制列表 (ACL)。 本文介绍 Data Lake Storage 中的访问控制列表。 若要了解如何将 Azure RBAC 与 ACL 合并在一起,以及系统如何评估它们以做出授权决策,请参阅 Azure Data Lake Storage 中的 Access 控制模型。

关于 ACL

可将安全主体关联到对文件和目录的访问权限级别。 每个关联都是 访问控制列表 (ACL) 中的条目。 存储帐户中的每个文件和目录都有一个访问控制列表。 当安全主体尝试对文件或目录执行操作时,ACL 检查将确定安全主体(用户、组、服务主体或托管标识)是否具有执行该操作所需的正确权限级别。

注意

ACL 仅适用于同一租户中的安全主体。 ACL 不适用于使用共享密钥授权的用户,因为没有标识与调用方关联,因此无法执行基于安全主体权限的授权。 同一规则适用于共享访问签名(SAS)令牌,除非使用用户委托的 SAS 令牌。 在这种情况下,只要使用可选参数 suoid,Azure 存储才会对对象 ID 执行 POSIX ACL 检查,然后才授权该操作。 若要了解详细信息,请参阅构造用户委派 SAS

如何设置 ACL

若要设置文件和目录级权限,请参阅以下任一文章:

环境 文章
Azure 存储资源管理器 使用 Azure 存储资源管理器管理 Azure Data Lake Storage 中的 ACL
Azure 门户 使用 Azure 入口管理 Azure Data Lake Storage 中的 ACL
.NET 使用 .NET 管理 Azure Data Lake Storage 中的 ACL
Java 使用 Java 管理 Azure Data Lake Storage 中的 ACL
Python 使用 Python 管理 Azure Data Lake Storage 中的 ACL
JavaScript (Node.js) 使用 Node.js 中的 JavaScript SDK 管理 Azure Data Lake Storage 中的 ACL
PowerShell 使用 PowerShell 管理 Azure Data Lake Storage 中的 ACL
Azure CLI 使用 Azure CLI 管理 Azure Data Lake Storage 中的 ACL
REST API 路径 - 更新

重要

如果安全主体是服务主体,请使用 服务 主体的对象 ID,而不是相关应用注册的对象 ID。 若要获取服务主体的对象 ID,请打开Azure CLI,然后使用以下命令:az ad sp show --id <Your App ID> --query objectId。 将 <Your App ID> 占位符替换为应用注册的应用 ID。 将服务主体视为命名用户。 如同添加任何命名用户一样,将此 ID 添加到 ACL 中。 本文稍后将介绍命名用户。

ACL 的类型

访问控制列表有两种类型:访问 ACL 和默认 ACL。

访问 ACL 控制对某个对象的访问权限。 文件和目录都具有访问 ACL。

默认 ACL 是与目录关联的 ACL 模板,用于确定在该目录下创建的任何子项的访问 ACL。 文件没有默认 ACL。

访问 ACL 和默认 ACL 具有相同的结构。

注意

更改父项上的默认 ACL 不会影响已存在子项的访问 ACL 或默认 ACL。

权限级别

容器中目录和文件的权限为 “读取”、“ 写入”和 “执行”。 可以对文件和目录使用这些权限,如下表所示:

文件 目录
读取 (R) 可以读取文件内容 需有“读取”和“执行”权限才能列出目录内容
写入 (W) 可以在文件中写入或追加内容 需有“写入”和“执行”权限才能在目录中创建子项
执行 (X) 在 Data Lake Storage 的语境中,这没有任何意义 需要遍历目录的子项

注意

如果你通过仅使用 ACL(不使用 Azure RBAC)来授予权限,那么要向某个安全主体授予对文件的读取或写入访问权限,你需要向该安全主体授予容器根文件夹的Execute权限,以及通往该文件的文件夹层次结构中每一级文件夹的Execute权限。

权限的短格式

使用 RWX 显示 读取 + 写入 + 执行 权限。 还有一个数字形式,其中 Read=4Write=2Execute=1。 添加这些数字以显示权限。 以下是一些示例:

数字形式 简短形式 含义
7 RWX 读取 + 写入 + 执行
5 R-X 读取 + 执行
4 R-- 读取
0 --- 无权限

权限继承

在 Data Lake Storage 使用的 POSIX 样式的模型中,项的权限存储在项本身中。 换而言之,如果是在已创建子项后设置的权限,则无法从父项继承项目的权限。 只有于创建子项前在父项上设置了默认权限时,才能继承权限。

下表显示了使安全主体能够执行 操作 列中列出的操作所需的 ACL 条目。

此表显示的列代表虚构目录层次结构的每个级别。 容器的根目录 (/)、名为 Oregon 的子目录、Oregon 目录的名为 Portland 的子目录以及 Portland 目录中名为 Data.txt 的文本文件分别对应一个列。

重要

此表假定你在不使用任何Azure角色分配的情况下使用 only ACL。 若要查看组合使用 Azure RBAC 和 ACL 的类似表,请参阅权限表:合并 Azure RBAC、ABAC 和 ACL

操作 / 俄勒冈州/ 波特兰/ Data.txt
读取 Data.txt --X --X --X R--
追加到 Data.txt --X --X --X RW-
删除 Data.txt --X --X -WX ---
删除 /俄勒冈/ -WX RWX RWX ---
删除 /俄勒冈/波特兰/ --X -WX RWX ---
创建/更新 Data.txt --X --X -WX ---
列表 / R-X --- --- ---
列表 /俄勒冈/ --X R-X --- ---
列表 /俄勒冈/波特兰/ --X --X R-X ---

删除文件和目录

如上表中所示,只要正确设置目录权限,就不需要对文件具有写入权限即可将其删除。 但是,要删除目录及其所有内容,父目录必须具有写入 + 执行权限。 要删除的目录及其中的每个目录都需要“读取 + 写入 + 执行”权限。

注意

永远无法删除根目录“/”。

用户和身份

每个文件和目录都有这些标识的不同权限:

  • 拥有者用户
  • 所有者组
  • 指定用户
  • 命名的组
  • 已命名服务主体
  • 命名托管标识
  • 所有其他用户

用户和组的标识是 Microsoft Entra 标识。 因此,除非另有说明,否则在 Data Lake Storage 的上下文中,用户可以指 Microsoft Entra 用户、服务主体、托管标识或安全组。

超级用户

在所有用户中,超级用户拥有的权限是最大的。 超级用户:

  • 具有 对所有文件和文件夹的 RWX 权限。

  • 可以更改任何文件或文件夹的权限。

  • 可以更改任何文件或文件夹的所属用户或所属组。

如果使用共享密钥、帐户 SAS 或服务 SAS 创建容器、文件或目录,则所有者和拥有组将设置为 $superuser

拥有者用户

创建该项的用户将自动是该项目的拥有用户。 具有所有权的用户可以:

  • 更改其拥有的文件的权限。
  • 更改用户自己拥有的文件的所属组,前提是该用户也是目标组的成员。

注意

文件或目录的所有者不能更改其所有者。 只有超级用户可以更改文件或目录的拥有用户。

所有者组

在 POSIX ACL 中,每个用户都与“主组”关联。 例如,用户“Alice”可能属于“finance”组。 Alice 还可能属于多个组,但始终有一个组被指定为主要组。 在 POSIX 中,当 Alice 创建文件时,该文件的拥有组将设置为她的主组,在本例中为“finance”。否则,拥有组的行为类似于为其他用户和组分配的权限。

为新的文件或目录分配所属组

  • 案例 1:根文件夹 。 此目录是在创建 Data Lake Storage 容器时创建的。 在这种情况下,如果用户使用 OAuth,则所属组会被设置为创建该容器的用户。 如果用户使用共享密钥、帐户 SAS 或服务 SAS 创建容器,则所有者和拥有组将设置为 $superuser
  • 案例 2(所有其他情况):创建新项时,从父目录复制拥有组。

更改拥有组

可以通过以下方式更改拥有组:

  • 任何超级用户。
  • 拥有用户,前提是该拥有用户也是目标组的成员。

注意

所属组无法更改文件或目录的 ACL。 虽然在前文根目录的情况(Case 1)中,所属组被设置为创建该账户的用户,但单个用户账户并不能通过所属组来提供权限。 可以将此权限分配给有效的用户组(如果适用)。

权限是如何评估的

系统按以下顺序评估身份:

  1. 超级用户
  2. 所属用户
  3. 指定用户、服务主体或托管标识
  4. 拥有组或已命名组
  5. 所有其他用户

如果其中多个标识适用于安全主体,则系统会授予与第一个标识关联的权限级别。 例如,如果安全主体同时是拥有用户和命名用户,则与拥有用户关联的权限级别适用。

系统将所有命名组一起考虑在一起。 如果安全主体是多个命名组的成员,系统会评估每个组,直到找到所需的权限。 如果命名组没有提供所需权限,则系统会继续针对与所有其他用户关联的权限评估请求。

以下伪代码显示了存储帐户的访问检查算法。 此算法显示身份评估的顺序。

def access_check( user, desired_perms, path ) :
  # access_check returns true if user has the desired permissions on the path, false otherwise
  # user is the identity that wants to perform an operation on path
  # desired_perms is a simple integer with values from 0 to 7 ( R=4, W=2, X=1). User desires these permissions
  # path is the file or directory
  # Note: the "sticky bit" isn't illustrated in this algorithm

  # Handle super users.
  if (is_superuser(user)) :
    return True

  # Handle the owning user. Note that mask isn't used.
  entry = get_acl_entry( path, OWNER )
  if (user == entry.identity)
      return ( (desired_perms & entry.permissions) == desired_perms )

  # Handle the named users. Note that mask IS used.
  entries = get_acl_entries( path, NAMED_USER )
  for entry in entries:
      if (user == entry.identity ) :
          mask = get_mask( path )
          return ( (desired_perms & entry.permissions & mask) == desired_perms)

  # Handle named groups and owning group
  member_count = 0
  perms = 0
  entries = get_acl_entries( path, NAMED_GROUP | OWNING_GROUP )
  mask = get_mask( path )
  for entry in entries:
    if (user_is_member_of_group(user, entry.identity)) :
        if ((desired_perms & entry.permissions & mask) == desired_perms)
            return True

  # Handle other
  perms = get_perms_for_other(path)
  mask = get_mask( path )
  return ( (desired_perms & perms & mask ) == desired_perms)

掩码

掩码仅适用于命名用户、命名组和拥有组的 ACL 条目。 掩码指定使用 ACL 条目中的哪些权限来授权访问。 这些已应用的权限称为 ACL 条目的有效权限。 系统忽略 ACL 条目中的所有其他权限。 通过使用掩码,可以对权限级别设置上限。

您可以针对每次调用指定掩码。 这种灵活性允许不同的使用系统(例如群集)对其文件操作使用不同的有效掩码。 如果在给定的请求上指定掩码,它将完全替代默认掩码。

粘滞位

粘滞位是 POSIX 容器的更高级功能。 在Data Lake Storage的上下文中,你不太可能需要粘滞位。 总之,如果在目录中启用粘滞位,则只有子项的拥有用户、目录的所有者或超级用户($superuser)才能删除或重命名子项。

Azure门户不显示粘滞位。 若要详细了解粘滞位以及如何设置它,请参阅 什么是粘滞位 Data Lake Storage?

根目录的默认权限

对于新的 Data Lake Storage 容器,根目录(“/”)的访问 ACL 默认为 750(适用于目录)和 640(适用于文件)。 下表显示了这些权限级别的符号表示法。

实体 目录 文件存储
所属用户 rwx rw-
拥有者组 r-x r--
其他 --- ---

文件不会收到 X 位,因为它与仅存储系统中的文件无关。

新文件和目录的默认权限

在现有目录下创建新文件或目录时,父目录上的默认 ACL 将确定:

  • 子目录的默认 ACL 和访问 ACL。
  • 子文件的访问控制列表(ACL)(文件没有默认访问控制列表)。

umask

创建默认 ACL 时,系统将 umask 应用到访问 ACL,以确定默认 ACL 的初始权限。 如果在父目录上定义默认 ACL,系统将忽略 umask,并使用父目录的默认 ACL 设置初始值。

umask 是父目录上一个 9 位的值,它包含“拥有用户”、“拥有组”和“其他”的 RWX 值。

Azure Data Lake Storage 的 umask 是固定为 007 的常量。 此值将转换为:

umask 组件 数字形式 简短形式 含义
umask.owning_user 0 --- 对于拥有权限的用户,将父元素的访问 ACL 复制到子元素的默认 ACL
umask.owning_group 0 --- 对于所属组,将父级的访问 ACL 复制到子级的默认 ACL。
umask.其他 7 RWX 对于其他项目,删除子对象访问控制列表 (ACL) 上的所有权限。

FAQ

是否必须启用 ACL 的支持?

否。 只要启用了分层命名空间(HNS)功能,就可以为存储帐户启用通过 ACL 进行访问控制。

如果 HNS 已关闭,Azure RBAC 授权规则仍适用。

应用 ACL 的最佳方式是什么?

始终将 Microsoft Entra 安全组用作 ACL 条目中分配的主体。 避免直接为单个用户或服务主体分配任务。 使用此结构,你可以添加和删除用户或服务主体,不需要向整个目录结构重新应用 ACL。 可以仅在适当的 Microsoft Entra 安全组中添加或删除用户和服务主体。

有多种不同的方法可用来设置组。 例如,假设你有一个名为 /LogData 的目录,该目录包含服务器生成的日志数据。 Azure 数据工厂 (ADF) 将数据引入到该文件夹中。 服务工程团队中的特定用户将上传日志并管理此文件夹的其他用户,而各个 Databricks 群集将分析来自该文件夹的日志。

若要启用这些活动,可以创建一个 LogsWriter 组和一个 LogsReader 组。 然后,可以按如下所示分配权限:

  • LogsWriter 组以 权限添加到 rwx 目录的 ACL 中。
  • LogsReader 组以 权限添加到 r-x 目录的 ACL 中。
  • LogsWriters 组添加用于 ADF 的服务主体对象或托管服务标识 (MSI)。
  • 将服务工程团队中的用户添加到 LogsWriter 组。
  • 将 Databricks 的服务主体对象或 MSI 添加到 LogsReader 组。

如果服务工程团队中的用户离开了公司,则只需将其从 LogsWriter 组中删除即可。 如果未将该用户添加到组中,而是为该用户添加了专用 ACL 条目,则必须从 /LogData 目录中删除此 ACL 条目。 还必须从 /LogData 目录的整个目录层次结构中的所有子目录和文件中删除此条目。

要创建组并添加成员,请参阅使用 Microsoft Entra ID 创建基本组并添加成员

如何评估 Azure RBAC 和 ACL 权限?

若要了解系统如何将 Azure RBAC 和 ACL 一起评估,以便针对存储帐户资源做出授权决策,请参阅如何评估权限

Azure 角色限制和 ACL 条目存在哪些限制?

下表提供了在使用 Azure RBAC 管理“粗粒度”权限(应用于存储帐户或容器的权限)以及使用 ACL 管理“细粒度”权限(应用于文件和目录的权限)时要考虑的限制的汇总视图。 使用安全组进行 ACL 分配。 通过使用组,您不太可能超出每个订阅的最大角色分配数量,以及每个文件或目录的最大 ACL 条目数量。

机制 Scope 限制 支持的权限级别
Azure RBAC 存储帐户、容器。
在订阅或资源组级别进行跨资源的 Azure 角色分配。
一个订阅中 4000 个 Azure 角色分配 Azure 角色(内置或自定义)
ACL 目录、文件 每个文件和每个目录有 32 个 ACL 条目(实际上是 28 个 ACL 条目)。 访问 ACL 和默认 ACL 都有各自的 32 个 ACL 条目限制。 ACL 权限

Data Lake Storage 是否支持继承 Azure RBAC?

Azure 角色分配具有继承性。 分配从订阅、资源组和存储帐户资源向下传递到容器资源。

Data Lake Storage 是否支持继承 ACL?

可以使用默认 ACL 来设置父目录下创建的新子目录和文件的 ACL。 若要更新现有子项的 ACL,需要以递归方式为所需目录层次结构添加、更新或删除 ACL。 有关指南,请参阅本文的如何设置 ACL 部分。

以递归方式删除目录及其内容需要哪些权限?

  • 调用方具有超级用户权限,

  • 父目录具有写入和执行权限。
  • 要删除的目录及其中的每个目录都需要读取、写入和执行权限。

注意

无需写入权限即可删除目录中的文件。 另外,永远无法删除根目录“/”。

谁是文件或目录的所有者?

文件或目录的创建者就是所有者。 对于根目录,此标识是创建容器的用户。

创建文件或目录时将哪个组设置为其拥有组?

新文件或目录的拥有组是从其父目录的拥有组中复制而来的。

我是文件的拥有者,但没有我需要的 RWX 权限。 我该怎么办?

拥有用户可以更改文件的权限,以便为自己赋予所需的任何 RWX 权限。

为什么我有时在 ACL 中看到 GUID?

如果条目表示一个用户且该用户不再位于 Microsoft Entra 中,则显示 GUID。 当用户离职,或者其帐户已在 Microsoft Entra ID 中删除时,往往会发生这种情况。 此外,服务主体和安全组没有用于标识它们的用户主体名称 (UPN),因此用它们的 OID 属性(即一个 GUID)来表示它们。 若要清理 ACL,请手动删除这些 GUID 条目。

如何为服务主体正确设置 ACL?

为服务主体定义 ACL 时,必须使用所创建应用注册的服务主体的对象 ID (OID)。 请务必注意,注册的应用在特定的 Microsoft Entra 租户中具有独立的服务主体。 注册的应用会在 Azure 门户中显示一个 OID,但服务主体具有另一个(不同的)OID。

若要获取服务主体的对应于应用注册的 OID,可以使用 az ad sp show 命令。 指定应用程序 ID 作为参数。 下面是获取服务主体的 OID 的示例,该 OID 对应于应用 ID 为 00001111-aaaa-2222-bbbb-3333cccc4444 的应用注册。 在 Azure CLI 中运行以下命令:

az ad sp show --id 00001111-aaaa-2222-bbbb-3333cccc4444 --query objectId

将显示 OID。

获取服务主体的正确 OID 后,转到存储资源管理器的“管理访问权限”页,以添加该 OID 并为其分配适当的的权限。 请务必选择“保存”

是否可以设置容器的 ACL?

否。 容器没有 ACL。 但是,你可以设置容器的根目录的 ACL。 每个容器都有一个根目录,该目录与容器同名。 例如,如果容器名为 my-container,则根目录名为 my-container/

Azure 存储 REST API 包含一个名为设置容器 ACL 的操作,但该操作不能用来设置容器或容器根目录的 ACL, 而该操作用于指示容器中的Blob是否可以通过匿名请求访问。 建议对所有 Blob 数据请求要求授权。 有关详细信息,请参阅概述:修正对 blob 数据的匿名读取访问

在哪里可以了解 POSIX 访问控制模型的详细信息?

另请参阅