CentOS 7 使用 ACL 精确控制文件和目录的访问权限


一、前言

Linux 基本的权限控制仅可以对所属用户、所属组、其他用户进行的权限控制,而不能精确地控制每个用户的权限。ACL 规则就是用来解决这个问题的。

使用 ACL 规则,我们可以针对单一账户设置文件及目录的访问权限。


二、实验环境

  • 操作系统:CentOS 7.3.1611
  • root:包含用户 root
  • zenandidi:包含用户 zenandidi
  • nannan:包含用户 nannanzenandidi
  • 目录 test_dir/
  • 文件 test.sh

test.sh 的内容:

#/bin/bash
echo "Success!"

三、检查文件系统的 ACL 功能是否已经开启

CentOS 7 默认已经开启 ACL 功能。

tune2fs -l /dev/sda2 | grep acl

执行结果

Default mount options:    user_xattr acl

如果有看到 acl,说明已经开启。


四、查看是否设定了 ACL 规则

直接用 ls -l 查看,如果权限一栏后面有个加号,说明文件被设定了 ACL 规则。

ls -l

执行结果

总用量 12K
-rw-rwxr--+  1 root root   27 5月   7 08:03 test.sh
          └──> 已设置 ACL 规则

五、查询 ACL 规则

5.1 命令基本用法

getfacl <文件>

5.2 举例说明

列出 test.sh 的 ACL 规则(下面分段说明)

getfacl test.sh 

执行结果

以下为文件的基本信息:

# file: test.sh     # 文件名
# owner: root       # 所有者
# group: root       # 所属组


##以下为文件的用户权限设置##
user::rw-                   # Linux 默认的所属用户权限
user:zenandidi:rwx          #附加 ACL 用户权限,这里表示用户 zenandidi 有读、写、执行的权限


##以下为文件的组权限设置##
group::r--                  # Linux 默认的所属组权限


##其他信息##
mask::r-x                   # 权限掩码(最后详细说明)
other::r--                  # Linux 默认的其他用户权限

六、设置 ACL 规则

6.1 命令基本用法

setfacl <选项> [规则] <文件>
选项 功能
-m 新增一条 ACL 规则
-x 删除一条 ACL 规则
-b 清空所有 ACL 规则

6.2 举例说明

6.2.1 例 1

清空 test.sh 中所有 ACL 规则,并检查结果。

setfacl -b test.sh ;\
getfacl test.sh ;\
ls -l

执行结果

# file: test.sh
# owner: root
# group: root
user::rw-
group::r--
other::r--

########################################################

总用量 12K
-rw-r--r--   1 root root   27 5月   7 08:03 test.sh
          └──> 加号已经消失,说明没有设定 ACL 规则

6.2.2 例 2

test.sh 添加一条 ACL 规则,使得用户 zenandidi 具有读、执行权限,并检查结果。

setfacl -m u:zenandidi:rx test.sh ;\
getfacl test.sh ;\
ls -l ;\
sudo -u zenandidi ./test.sh 

执行结果

# file: test.sh
# owner: root
# group: root
user::rw-
user:zenandidi:r-x
group::r--
mask::r-x
other::r--

########################################################

总用量 12K
-rw-r-xr--+  1 root root   27 5月   7 08:03 test.sh

########################################################

Success!    # 以 zenandidi 的身份执行成功

好奇地看了下 root 是否可以执行

./test.sh 

执行结果

Success!

咦?我好像没设置 root 可以执行,为什么也执行成功了捏?其实这是 mask 在作怪,最后再看吧。

6.2.3 例 3

test.sh 添加一条 ACL 规则,使得组 nannan 具有读、写权限。

设置之前先看看能不能用用户 zenandidinannan 的身份改文件名

sudo -u zenandidi mv test.sh test1.sh ;\
sudo -u nannan mv test.sh test1.sh 

执行结果

mv: 无法将"test.sh" 移动至"test1.sh": 权限不够

########################################################

mv: 无法将"test.sh" 移动至"test1.sh": 权限不够

无法改文件名,因为没有赋予写权限。

设置权限

setfacl -m g:nannan:rw test.sh 

检查设置

getfacl test.sh 

执行结果

# file: test.sh
# owner: root
# group: root
user::rw-
user:zenandidi:r-x
group::r--
group:nannan:rw-        #effective:r--
mask::r-x
other::r--

再看看能不能改文件名

sudo -u zenandidi mv test.sh test1.sh ; sudo -u nannan mv test.sh test1.sh 

执行结果

mv: 无法将"test.sh" 移动至"test1.sh": 权限不够

########################################################

mv: 无法将"test.sh" 移动至"test1.sh": 权限不够

还是不行啊,怎么回事?还是那个 mask 的事。下面详细说明。


七、关于 mask 的那点事

7.1 mask 值规定了允许的最大权限

例如:

mask 为 rwx,说明 ACL 规则可以设置全部权限。
mask 为 rw-,说明 ACL 规则仅可设置读、写权限,无论是否设置执行权限,文件都不能被执行。

如果 getfacl 输出中有 #effective:xxx 这个注释,说明 ACL 规则受 mask 限制,仅有 xxx 权限。应特别注意!

6.2.3 的问题可以通过设置 mask 来解决。

setfacl -m mask:rwx test.sh 

7.2 mask 值会直接作为 Linux 基本权限中的组权限

6.2.2 的问题就出在这里。

设置 ACL 之前

ls -l

执行结果

总用量 12K
-rw-r--r--  1 root root   27 5月   7 08:03

设置 ACL 之后,组权限变成了 mask 值

ls -l
总用量 12K
-rw-r-xr--+  1 root root   27 5月   7 08:03 test.sh

因为 root 处在 root 组之中,所以自然就有了执行的权限。


八、设置新文件或子目录的默认 ACL 规则

默认 ACL 规则只存在于目录中。它用于自动设定在该目录下新建的文件或子目录的 ACL 规则。

8.1 命令基本用法

和 6.1 基本相同,只需要在原有规则的前面加上 d: 即可。

8.2 举例说明

为目录 test_dir/ 添加一条 ACL 规则,使得用户 zenandidi 具有读、写、执行(进入目录)的权限。

为目录 test_dir/ 添加一条默认规则,使得用户 zenandidi 在目录下创建的文件或子目录默认就有读、写、执行权限。

然后以 zenandidi 的身份在该目录下创建一个文件和一个子目录,并检查结果。

为目录添加 ACL 规则

setfacl -m u:zenandidi:rwx test_dir

为目录添加默认 ACL 规则

setfacl -m d:u:zenandidi:rwx test_dir

创建文件及子目录

cd test_dir/ && \
sudo -u zenandidi mkdir zenandidi_dir && \
sudo -u zenandidi touch zenandidi_file

检查 test_dir/ 以及在此目录里新创建的文件和目录的 ACL 规则

getfacl . *

执行结果

# file: .   # test_dir/ 目录的 ACL 规则
# owner: root
# group: root
user::rwx
user:zenandidi:rwx
group::r-x
mask::rwx
other::r-x
# 以下为默认 ACL 规则
default:user::rwx
default:user:zenandidi:rwx  # 除了刚才添加的默认 ACL 规则之外,系统还会自动创建目录属主、目录属组、其他用户的默认 ACL 规则以及默认掩码
default:group::r-x
default:mask::rwx   #默认掩码
default:other::r-x

########################################################

# file: zenandidi_dir   # 以 zenandidi 身份创建目录的 ACL 规则
# owner: zenandidi
# group: zenandidi
user::rwx
user:zenandidi:rwx      # 刚才添加的默认 ACL 规则已经成功生效
group::r-x
mask::rwx
other::r-x
default:user::rwx
default:user:zenandidi:rwx
default:group::r-x
default:mask::rwx
default:other::r-x

########################################################

# file: zenandidi_file  # 以 zenandidi 身份创建文件的 ACL 规则
# owner: zenandidi
# group: zenandidi
user::rw-
user:zenandidi:rwx      #effective:rw-  # 刚才添加的默认 ACL 规则已经成功生效,但被掩码限制,不能执行。虽然 test_dir/ 目录的默认掩码允许执行,但是可以看出,它只对目录生效(允许进入目录)。系统出于安全考虑,新建的文件都无法自动创建执行权限。
group::r-x          #effective:r--
mask::rw-
other::r--

以上纯属个人经验,如有错误请及时提出,谢谢!

发表评论

电子邮件地址不会被公开。