ACL 核心概念:ACE、ACL 类型与掩码

上一章我们聊了 ACL 能干什么,这一章咱们来拆开它,看看里面到底长什么样。说白了,ACL 就是一张权限清单,但清单上的每一项怎么写、怎么分组、怎么控制生效范围,这里头有不少门道。

我刚开始接触 ACL 时,最头疼的就是 ACE、ACL 类型、掩码这三个概念搅在一起。你想想看,一个文件系统里既有访问控制列表,又有默认列表,每个列表里还挂着好几条条目,条目上还压着一个掩码……嗯,今天咱们就把这团乱麻理清楚。

ACE:ACL 的最小单元

ACE 的全称是 Access Control Entry,翻译过来就是「访问控制条目」。它是 ACL 里最小的权限单位,一条 ACE 就代表一条规则。

一条 ACE 长什么样?我习惯把它拆成四个部分:

  • 类型:允许还是拒绝?
  • 主体:这条规则针对谁?用户、用户组,还是特殊主体?
  • 权限:读、写、执行,还是更细粒度的权限?
  • 标志:这条 ACE 是否继承?是否传播给子目录?

核心要点:ACE 的顺序至关重要。大多数系统按「拒绝优先」或「首次匹配」规则处理,顺序错了,权限就全乱了。

举个例子,在 Linux 的 setfacl 命令里,一条 ACE 的写法是这样的:

# 给用户 zhangsan 赋予读写权限
setfacl -m u:zhangsan:rw- project.txt

# 这条 ACE 拆开看:
# 类型:允许(默认就是允许)
# 主体:用户 zhangsan
# 权限:rw-(读+写)
# 标志:无(不涉及继承)

我在项目中遇到过一个问题:有人把拒绝 ACE 放在了允许 ACE 后面,结果用户明明被拒绝了,系统却先匹配到了允许规则,权限就漏出去了。所以,拒绝 ACE 一定要放在允许 ACE 前面,这是铁律。

ACL 类型:访问 ACL 与默认 ACL

ACL 分两种:访问 ACL 和默认 ACL。这两个概念,说白了就是「当前生效」和「未来继承」的区别。

对比维度 访问 ACL 默认 ACL
作用对象 文件或目录本身 仅目录(文件没有默认 ACL)
生效时机 立即生效 子文件/子目录创建时生效
是否继承 不继承 子目录会继承父目录的默认 ACL
典型场景 给某个用户临时开放文件 团队共享目录,新文件自动有权限

我举个例子你就明白了。假设你有一个团队共享目录 /data/team:

# 设置访问 ACL:给当前目录加权限
setfacl -m u:zhangsan:rwx /data/team

# 设置默认 ACL:以后新建的文件自动继承
setfacl -m d:u:zhangsan:rwx /data/team

第一条命令,zhangsan 立刻能访问 /data/team。第二条命令,zhangsan 以后在这个目录下新建的任何文件,自动就有 rwx 权限。我曾经踩过这个坑——只设了访问 ACL,没设默认 ACL,结果 zhangsan 能进目录,但新建的文件他打不开。嗯,后来我就养成了习惯:共享目录一定要同时配默认 ACL。

小技巧:用 getfacl 查看 ACL 时,默认 ACL 会以 default: 开头显示。一眼就能区分。

ACL 掩码:权限的「天花板」

掩码(Mask)这个概念,我刚开始也觉得绕。你想想看,明明 ACE 里已经写了权限,为什么还要加个掩码?

说白了,掩码就是一道「上限锁」。它限制了所有非文件所有者、非特殊主体的最大权限。注意,它不限制文件所有者(owner)和特殊主体(比如 Linux 的 other)。

举个例子:

# 查看当前 ACL
getfacl myfile.txt

# 输出:
# user::rw-
# user:zhangsan:rwx      # 这条 ACE 给了 rwx
# group::r--
# mask::r--              # 掩码只有 r--
# other::r--

# 实际生效的权限:
# zhangsan 的权限 = ACE 权限 ∩ 掩码权限 = rwx ∩ r-- = r--

看到了吗?zhangsan 的 ACE 写了 rwx,但掩码只有 r--,所以最终他只能读。这就是掩码的「天花板」作用。

注意:修改 ACE 时,系统可能会自动重新计算掩码。比如你用 setfacl -m 加了一条带写权限的 ACE,掩码可能会自动升级。我建议每次修改后都用 getfacl 确认一下掩码值。

我个人习惯把掩码理解成「安全阀」。它防止你无意中给某个用户或组开了过高的权限。尤其是在多人协作的目录里,掩码能帮你兜底。

三者关系:一张图看懂

下面这张 SVG 图,把 ACE、ACL 类型、掩码的关系画清楚了。你一看就明白。

ACL 核心概念关系图 ACL(访问控制列表) 访问 ACL 默认 ACL 作用于文件或目录本身 立即生效,不继承 文件/目录都有 仅目录有 子文件/子目录创建时继承 不作用于当前目录 ACE(访问控制条目) 类型(允许/拒绝) 主体(用户/组) 权限(rwx) 标志(继承) 掩码(Mask) 限制非 owner 的最大权限 ACE ∩ Mask = 实际权限

避坑指南:我踩过的三个坑

最后,分享几个我实际项目中遇到的坑,你遇到了能少走弯路。

  1. ACE 顺序搞反:拒绝 ACE 放后面,结果被允许 ACE 覆盖了。我曾经在给一个离职员工收权限时,把拒绝 ACE 加在了允许 ACE 后面,结果他还能访问。排查了半天才发现是顺序问题。
  2. 默认 ACL 忘设:只配了访问 ACL,没配默认 ACL。新文件创建后,团队成员打不开。后来我写了个脚本,每次创建共享目录时自动检查默认 ACL 是否配置。
  3. 掩码被自动修改:用 setfacl -m 加了一条高权限 ACE,系统自动把掩码也抬高了。结果本来只想给一个人开权限,掩码一升,整个组的权限都变大了。嗯,从那以后我每次改完 ACL 都会用 getfacl 确认一遍掩码。

一句话总结:ACE 是规则,ACL 是规则集合,掩码是规则的上限。记住这个三层结构,ACL 就不难了。