# 主机的细部权限规划:ACL 的使用

从第 5 章开始,在强调 Linux 的权限概念非常重要,传统的权限仅有三种身份(owner、group、others)搭配三种权限(r、w、x),无法单纯的针对某一个使用者或某一个群组来设置设置特殊的权限需求,那么此时就需要使用 ACl 这个机制了

# 什么是 ACl 与如何支持启动 ACl

ACl (Access Control List),主要目的是提供传统的 owner、group、others 的 read、write、execute 权限之外的特殊权限需求设置。ACL 可以针对单一使用者、单一文件或目录来进行 r、w、x 的权限规范,对于需要特殊权限的使用状况非常有帮助

ACl 主要针对以下方面来控制权限:

  • 使用者 user
  • 群组 group
  • 默认属性 mask:针对在该目录下在建立新文件/目录时,规范新数据的默认权限

简单说,有一个目录,给一堆人使用,每个人或每个群组所需要的权限并不相同,使用传统 Linux 三种身份的三种权限是无法达到的,因此基本上,传统的 Linux 权限只能针对一个用户、一个群组以及非此群组的其他人设置权限。无法针对单一用户或个人来设计权限。

# 如何启动 ACl

原本 ACL 是 unix-like 操作系统额外支持的项目,因为近年来对权限需求日益增大,因此目前 ACl 几乎已经预设加入所有场景的 Linux 文件系统的挂载参数中(ext2\3\4、xfs 等),所以无需任何操作。可以通过如下方式来检测是否支持 ACL

[root@study mrcode]# dmesg | grep -i acl
# 这里 +ACl
[    1.329361] systemd[1]: systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
# 这里 SGI XFS with ACLs
[    2.978756] SGI XFS with ACLs, security attributes, no debug enabled
1
2
3
4
5

笔者疑问:怎么确定 xfs 支持?难道是因为我自己知道是在 xfs 系统上?

# ACL 的设置技巧:getfacl、setfacl

  • getfacl:取得某个文件/目录的 ACL 设置信息
  • setfacl:设置某个文件/目录的 ACl

# setfacl 指令用法介绍以及最简单的 u:账户:权限 设置

setfacl [-bkRd] [{-ml -x} acl 参数] 目标文件名

选项与参数:
	-m:设置后续的 acl 参数给文件使用,不可与 -x 合用
	-x:删除后续的 acl 参数,不可与 -m 合用
	-b:移除 所有的 ACL 设置参数
	-k:移除 预设的 ACL 参数;(关于所谓的预设参数后续介绍)
	-R:递归设置 acl,包括此目录也会被设置
	-d:设置 「预设 acl 参数」的意思,只对目录有效,在该目录新建的数据会引用此默认值
1
2
3
4
5
6
7
8
9

上面是 acl 的选项功能,下面来介绍一些特殊权限的设置方式:

# 1. 针对特定使用者的方式
# 设置规范:「u:[使用者账户列表]:[rwx]」
# 例如 针对 mrcode1 的权限设置为 rx
[root@study ~]# touch acl_test1
[root@study ~]# ll acl_test1 
-rw-r--r--. 1 root root 0 224 16:47 acl_test1
[root@study ~]# setfacl -m u:mrcode1:rx acl_test1 
[root@study ~]# ll acl_test1 
-rw-r-xr--+ 1 root root 0 224 16:47 acl_test1
# 权限部分多了一个 +,且与原本的权限 644 看起来差异很大。

[root@study ~]# setfacl -m u::rwx acl_test1 
[root@study ~]# ll acl_test1 
-rwxr-xr--+ 1 root root 0 224 16:47 acl_test1
# 设置 u 后面无使用者列表,代表设置该文件拥有者,所以上线显示 root 的全文为 rwx 了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

上面是设置,权限部分会多出一个 + 号,传统的 ll 是不知道设置了什么的,可以通过 getfacl 来查阅

# getfacl 指令用法

getfacl filename

选项与参数:几乎与 setfacl 相同,这里不贴了
1
2
3
# 列出刚刚设置的 acl_test1 的权限内容
[root@study ~]# getfacl acl_test1 
# file: acl_test1			# 文件名
# owner: root				# 拥有者,ls -l 看到的第 3 字段
# group: root				# 该文件所属群组,ls -l 看到的第 4 字段
user::rwx					# 使用者列表栏是空的,标识该权限设置针对的是文件的拥有者
user:mrcode1:r-x			# 针对 mrcode1 的权限设置为 rx,与拥有者不同
group::r--					# 群组的设置
mask::r-x					# 此文件预设的有效权限 mask
other::r--					# 其他人拥有的权限
1
2
3
4
5
6
7
8
9
10

# 特定的单一群组的权限设置:g:群组名:权限

# 2. 针对特定群组的方式
# 设置规范:「g:[群组列表]:[rwx]」
# 针对 mygroup1 的权限设置为 rx
[root@study ~]# setfacl -m g:mygroup1:rx acl_test1 
[root@study ~]# getfacl acl_test1 
# file: acl_test1
# owner: root
# group: root
user::rwx
user:mrcode1:r-x
group::r--
group:mygroup1:r-x				# 多了这个权限设置
mask::r-x
other::r--
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 针对有效权限设置:m:权限

群组与使用者设置类似,但是那个 mask 有点像是「有效权限」的意思:使用者或群组所设置的权限必须要存在与 mask 的权限设置范围内才会生效,也就是有效权限 effective permission

# 3. 针对有效全是 mask 的设置方式
# 设置规范:「m:[rwx]」
# 针对刚刚的文件规范仅有 r
[root@study ~]# setfacl -m m:r acl_test1 
[root@study ~]# getfacl acl_test1 
# file: acl_test1
# owner: root
# group: root
user::rwx
user:mrcode1:r-x		#effective:r--		# 有效权限只有 r
group::r--
group:mygroup1:r-x		#effective:r--
mask::r--
other::r--

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

该功能可以通过 mask 来规范最大允许的权限,就能避免不小心开放某些权限给其他使用者或者群组了。不过,通常都是将 mask 设置为 rwx,再分别依据不同的使用者、群组去规范他们的权限

# 例题

# 范例 1: 将前一小节任务二中 /srv/projecta 目录,让 myuser1 可以进入查阅,但是 myuser1 不具有修改的权限
# 由于 myuser1 是独立的使用者与群组,因此无法使用传统的 Linux 权限设置,此时应该使用 ACL 的设置

# 1. 先测试使用 myuser1 能否进入该目录
[myuser1@study ~]$ cd /srv/projecta/
-bash: cd: /srv/projecta/: Permission denied

# 2. 修改 ACL 权限为读和执行
[root@study ~]# setfacl -m u:myuser1:rx /srv/projecta/
[root@study ~]# getfacl /srv/projecta/
getfacl: Removing leading '/' from absolute path names
# file: srv/projecta/
# owner: root
# group: projecta
# flags: -s-
user::rwx
user:myuser1:r-x		# 设置了权限
group::rwx
mask::rwx
other::---

# 3. 测试是否成功进入
[myuser1@study ~]$ cd /srv/projecta/
[myuser1@study projecta]$ ll -a
total 0
drwxrws---+ 2 root projecta  6 Feb 24 15:04 .
drwxr-xr-x. 3 root root     22 Feb 24 15:04 ..
# 测试写入,缺少不可写入
[myuser1@study projecta]$ touch testing
touch: cannot touch 'testing': Permission denied

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

上面例子完成了之前任务二的后续需求,下面来介绍下默认权限,也就是创建新文件是否能继承 ACl 设置?

# 使用 root 账户取创建目录可文件,查看是否有继承 acl 设置
[root@study projecta]# touch abc1
[root@study projecta]# mkdir abc2
[root@study projecta]# ll -d abc*;
-rw-r--r--. 1 root projecta 0 Feb 25 09:32 abc1
drwxr-sr-x. 2 root projecta 6 Feb 25 09:32 abc2
1
2
3
4
5
6

可以看到权限后面没有 + 号出现,标识这个 acl 属性没有被继承

# 使用默认权限设置目录未来文件的 ACL 权限继承 d:[u|g]:[user|group]:权限

# 设置规范:d:[u|g]:[user|group 使用者列表]:[权限 rwx]
# 让 myuser1 在 /srv/projeecta 目录下一直具有 rx 的预设权限
[root@study projecta]# setfacl -m d:myuser1:rx /srv/projecta/
[root@study projecta]# getfacl /srv/projecta
getfacl: Removing leading '/' from absolute path names
# file: srv/projecta
# owner: root
# group: projecta
# flags: -s-
user::rwx
user:myuser1:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:myuser1:r-x			# 可以看到这里已经被设置上了
default:group::rwx
default:mask::rwx
default:other::---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

设置之后,还出现了其他针对拥有者的 default 配置。所以这里再次使用 root 账户取创建,也能看到继承效果了

[root@study projecta]# touch abc1
[root@study projecta]# mkdir abc2
[root@study projecta]# ll -d abc*
-rw-rw----+ 1 root projecta 0 Feb 25 09:40 abc1
drwxrws---+ 2 root projecta 6 Feb 25 09:40 abc2
1
2
3
4
5

如果需要让 ACL 属性全部消失,可以通过 setfacl -b 文件名 达到效果

# 例题练习

# 第一题

针对 /srv/projecta 目录的权限设置中,需要满足以下需求:

  1. 取消 myuser1 的设置(包括默认值)
  2. 不能让 pro3 这个用户使用该目录,也就是 pro3 在该目录下没有任何权限
# 1. 取消 myuser1 的设置和默认值
# 先查询到配置了哪些属性
[root@study projecta]# getfacl /srv/projecta/ | grep myuser1
getfacl: Removing leading '/' from absolute path names
user:myuser1:r-x
default:user:myuser1:r-x
# 通过 -x 参数来取消,取消的时候,不需要写权限,直接写前面定位部位
[root@study projecta]# setfacl -x u:myuser1 /srv/projecta/
[root@study projecta]# setfacl -x d:myuser1 /srv/projecta/
[root@study projecta]# getfacl /srv/projecta/ | grep myuser1


# 2.让 pro3 这个用户无法使用该目录
[root@study projecta]# setfacl -m u:pro3:- /srv/projecta/
[root@study projecta]# getfacl /srv/projecta/ | grep pro3   
getfacl: Removing leading '/' from absolute path names
user:pro3:---			# 这样一来就没有任何权限了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17