用户与权限管理

ACL

ACL (Access Control List) 是 Linux 操作系统中用于控制文件和目录访问权限的扩展机制。标准的 Unix 文件权限基于文件所有者、所属组和其他用户的访问权限。然而,ACL 允许更细粒度地控制访问权限,可以指定更多用户和组的权限。本文将详细介绍 Linux ACL 的相关概念和用法。

  1. ACL 概述: ACL 是在传统的文件权限基础上的扩展,它可以允许更多用户和组具有不同的权限。通过使用 ACL,可以为每个文件或目录定义不同的访问控制策略。
  2. ACL 组件: ACL 由以下两个主要组件组成:
    • 用户条目(User Entry):指定用户的权限。
    • 组条目(Group Entry):指定组的权限。
  3. ACL 权限控制: ACL 使用一套扩展的权限控制符号来表示权限,包括以下几个部分:
    • r:读取权限。
    • w:写入权限。
    • x:执行权限。
    • d:删除(仅对目录)。
    • a:授权继承。
  4. 查看和设置 ACL:
    • 使用 getfacl 命令可以查看文件或目录的 ACL。
    • 使用 setfacl 命令可以设置文件或目录的 ACL。
  5. 基本 ACL 操作:
    • 添加 ACL 条目:使用 setfacl 命令的 -m 选项可以添加新的 ACL 条目。
    • 修改 ACL 条目:使用 setfacl 命令的 -m 选项可以修改现有的 ACL 条目。
    • 删除 ACL 条目:使用 setfacl 命令的 -x 选项可以删除 ACL 条目。
  6. 默认 ACL: 默认 ACL 用于为新创建的文件和目录设置默认权限。它们类似于普通 ACL,但是应用于新创建的文件和目录,而不是已经存在的对象。默认 ACL 可以通过 -d 选项设置。
  7. 继承: 继承允许文件和目录的 ACL 条目自动传递到新创建的子项。继承规则可以通过设置 -d 选项来定义。
  8. ACL 限制:
    • 每个文件或目录可以有多个 ACL 条目。
    • 当 ACL 条目冲突时,将按照一定的顺序解析。
    • ACL 可能会受到文件系统类型和挂载选项的限制。

这些是关于 Linux ACL 的基本概念和用法。使用 ACL 可以更细致地控制文件和目录的访问权限,使权限管理更加灵活和精细化。

setfacl

setfacl 是 Linux 系统中用于设置文件和目录的 ACL(Access Control List)的命令。它允许用户更细粒度地控制文件和目录的访问权限,超过传统的基于所有者、所属组和其他用户的权限设置。下面是对 setfacl 命令的详细解释:

  1. 语法: setfacl [选项] 文件/目录
  2. 常用选项:
    • -m, --modify: 修改现有的 ACL 条目。
    • -x, --remove: 删除 ACL 条目。
    • -b, --remove-all: 删除所有 ACL 条目。
    • -R, --recursive: 递归地应用 ACL 设置到目录及其子目录和文件。
    • -d, --default: 设置默认 ACL。
    • -k, --remove-default: 删除默认 ACL。
    • -n, --no-mask: 不修改掩码权限。
  3. 设置 ACL 条目: 使用 -m 选项可以设置或修改文件或目录的 ACL 条目。语法如下: setfacl -m u:用户:权限,g:组:权限,o:权限 文件/目录 其中,用户是指定的用户名,组是指定的组名,权限是要设置的权限(如 rwx)。
  4. 删除 ACL 条目: 使用 -x 选项可以删除文件或目录的 ACL 条目。语法如下: setfacl -x u:用户,g:组,o 文件/目录 其中,用户是指定的用户名,组是指定的组名。
  5. 递归设置 ACL: 使用 -R 选项可以递归地将 ACL 设置应用于目录及其所有子目录和文件。这将确保 ACL 设置在整个目录树中生效。
  6. 设置默认 ACL: 使用 -d 选项可以设置默认 ACL。默认 ACL 将应用于新创建的文件和目录,而不是已存在的对象。
  7. 删除默认 ACL: 使用 -k 选项可以删除默认 ACL。这将取消为新创建的文件和目录设置的默认 ACL。
  8. 不修改掩码权限: 默认情况下,setfacl 命令会根据 ACL 设置自动修改掩码权限。使用 -n 选项可以阻止修改掩码权限。

setfacl 命令提供了灵活的 ACL 设置和管理功能,使用户能够以更细粒度的方式控制文件和目录的访问权限。通过结合其他 ACL 相关命令(如 getfacl)使用,可以有效地管理和维护 ACL 权限。

getfacl

getfacl 命令用于获取文件和目录的 ACL(Access Control List)信息。它可以显示文件或目录的当前 ACL 设置,以及默认 ACL(如果存在)。下面是对 getfacl 命令的详细解释:

  1. 语法: getfacl [选项] 文件/目录

  2. 常用选项:

    • -R, --recursive: 递归地获取目录及其子目录和文件的 ACL 信息。
    • -d, --default: 获取默认 ACL 信息。
  3. 获取 ACL 信息: 使用 getfacl 命令可以获取文件或目录的 ACL 信息。语法如下: getfacl 文件/目录

  4. 递归获取 ACL 信息: 使用 -R 选项可以递归地获取目录及其所有子目录和文件的 ACL 信息。这将显示整个目录树中每个对象的 ACL 设置。

  5. 获取默认 ACL 信息: 使用 -d 选项可以获取文件或目录的默认 ACL 信息。默认 ACL 将应用于新创建的文件和目录,而不是已存在的对象。

  6. 输出格式: getfacl 命令的输出结果通常以以下格式显示:

    # 文件/目录的 ACL 信息
    # ...
    # ...

    每行包含一个 ACL 条目,以 # 开头。通常情况下,每个条目由以下几个部分组成:

    • 权限部分:表示权限设置。
    • 用户/组部分:表示该条目适用的用户或组。
    • 类型部分:表示该条目的类型,如 “user”、“group” 等。
  7. 示例:

    • 获取文件的 ACL 信息: getfacl file.txt
    • 递归获取目录的 ACL 信息: getfacl -R dir/
    • 获取目录的默认 ACL 信息: getfacl -d dir/

getfacl 命令对于了解文件和目录的当前 ACL 设置非常有用。它提供了一种查看 ACL 信息的方式,帮助用户了解文件和目录的访问权限控制。结合其他 ACL 相关命令(如 setfacl),可以有效地管理和维护 ACL 权限。

范例

  • 设置 ACL 权限
# 设置前
# ll f1.txt
-rw-r--r-- 1 root root 709 Dec 18 14:37 f1.txt

# 将xiang用户设置为没有任何权限
# setfacl -m u:xiang:- f1.txt

# 设置后,可以看到出现了+号
# ll 
-rw-r--r--+ 1 root root 709 Dec 18 14:37 f1.txt
  • 查看 ACL 权限
# getfacl f1.txt
# file: f1.txt
# owner: root
# group: root
user::rw-
user:xiang:--- # xiang用户设置为没有任何权限了
group::r--
mask::r--
other::r--

# 也就无法查看文件了
[root@centos8 data]# su xiang
[xiang@centos8 data]$cat f1.txt
cat: f1.txt: Permission denied
[xiang@centos8 data]$ echo xx >> f1.txt
bash: f1.txt: Permission denied
  • 清除所有ACL权限
setfacl -b file1 
  • 复制file1的acl权限给file2
getfacl file1 | setfacl --set-file=-   file2  

mask

在 Linux 中,“mask” 是指掩码(mask)权限,也称为 “umask”(用户掩码)。它是一种权限设置,用于确定新创建文件和目录的默认权限。掩码权限与文件或目录的访问权限(如读、写和执行权限)之间存在一种逻辑关系。

  1. 掩码权限的作用: 掩码权限用于屏蔽或限制新创建文件和目录的默认权限。它通过与权限位进行逻辑与(AND)运算,将某些权限位设置为禁止(0),从而实现权限的控制。
  2. 掩码权限的取值: 掩码权限使用三个八进制数字来表示,每个数字表示对应的权限位。常见的取值范围是 0-7。每个数字对应的权限位如下:
    • 第一个数字表示所有者权限(Owner)。
    • 第二个数字表示所属组权限(Group)。
    • 第三个数字表示其他用户权限(Others)。
  3. 掩码权限的计算: 掩码权限的计算是通过将掩码值与默认权限进行逻辑运算得出的。计算步骤如下:
    • 将掩码值转换为二进制。
    • 反转二进制数(0 变为 1,1 变为 0)。
    • 将反转后的二进制数与默认权限进行逻辑与(AND)运算。
  4. 默认权限和掩码权限的关系: 默认权限是在创建新文件或目录时,为它们分配的初始权限。掩码权限与默认权限之间的关系是通过按位与运算来确定最终的权限。掩码权限中的 1 将禁止对应的权限位,而 0 将允许对应的权限位。
  5. 设置和查看掩码权限:
    • 使用 umask 命令可以设置掩码权限。例如,umask 022 将掩码权限设置为 022。
    • 使用 umask 命令可以查看当前的掩码权限设置。
  6. 永久更改掩码权限: 如果要永久更改掩码权限,可以将 umask 命令添加到 shell 配置文件(如 ~/.bashrc)中。这样,每次启动新的 shell 会话时,都会使用指定的掩码权限。

通过掩码权限,用户可以设置默认权限的控制,以满足特定的安全需求。通过合理配置掩码权限,可以确保新创建的文件和目录符合预期的权限设置。

范例

对于文件是 666 减 umask

对于目录是 777 减 umask

  • 默认的 umask
# umask 
0022

# touch f1
# mkdir d1

# ls -l
total 0
drwxr-xr-x 2 root root 6 May 17 09:09 d1
-rw-r--r-- 1 root root 0 May 17 09:08 f1
  • d1目录将777-0022=755,即得到权限rwxr-xr-x
  • f1文件将666-0022=644,即得到权限rw-r--r--

chattr

  • chattr 命令可以设置文件或目录的特殊属性,可以防止 root 用户误操作删除或修改文件

相关命令

  • chattr +i file 不能删除,改名,更改
  • chattr -i file 删除特殊属性
  • chattr +a file不能删除,改名 ,只能追加内容
  • chattr -a file 删除特殊属性
  • lsattr 显示特定属性

范例

# 创建测试文件
# touch testfile
-rw-r--r-- 1 root root 0 Jun 17 12:17 testfile


# 加i属性
# chattr +i testfile
# lsattr testfile 
----i--------------- testfile
# rm -f testfile 
rm: cannot remove 'testfile': Operation not permitted #无法删除
# echo 123 >> testfile 
-bash: testfile: Operation not permitted #无法追加


# 加a属性
# chattr +a testfile
# lsattr testfile 
-----a-------------- testfile
# rm -f testfile 
rm: cannot remove 'testfile': Operation not permitted #无法删除
# echo 123 >> testfile #但可追加
# cat testfile 
123

权限中的 t

  • t是在其他人处标注,数字表示法为1,含义为仅允许用户修改该用户自己创建的文件
#此目录用数字表示法的权限为1777
drwxrwxrwt. 4 root root 223 Oct 23 14:44 /tmp/

非交互式修改密码

# 通用写法一
echo -e 'passwd\npasswd' | passwd user


# 通用写法二
echo 'user:passwd' | chpasswd


# centos写法一
echo 'passwd' | passwd --stdin root

# centos写法二
[root@aliyun opt]#cat pass.txt 
passwd
[root@aliyun opt]#passwd --stdin root < pass.txt 
Changing password for user root.
passwd: all authentication tokens updated successfully.

创建新用户同时指定密码

  • 在CentOS和Ubuntu都通用
useradd -p `echo magedu | openssl passwd -6 -salt Y16DiwuVQtL6XCQK -stdin` zhang

# 或者
useradd -p `echo xiang666 | openssl passwd -6 -stdin` aaa

# 或者
useradd -p `openssl passwd -6 xiang888` bbb

设置文件/目录权限

# 设置普通权限
chmod {777|a+rwx|u+x...} {file|dir}

修改所有者所属组

chown user.user file

su

  • switch user,用户切换

    su -l user
    su -l user -c ‘COMMAND’

sudo 概述

https://www.sudo.ws/

  • sudo 即 superuser do;
  • 能够让获得授权的用户以另外一个用户的身份运行指定的命令;

sudo 安装

  • 来自 sudo 包,通常默认已经安装;

sudo 相关文件

/etc/sudo.conf  # sudo配置文件,权限必须为640

/etc/sudoers  # 授权规则主配置文件,权限必须为440
/etc/sudoers.d/  # 授权规则配置文件子目录

/usr/sbin/visudo  # 安全编辑授权规则文件和语法检查工具
/usr/bin/sudoedit  # 授权编辑规则文件的工具

/usr/bin/sudo  # 执行授权命令

/var/db/sudo  # 时间戳文件

/var/log/secure  # 日志文件

sudo 授权规则配置文件说明

可以定义在以下位置:

  • /etc/sudoers 文件,注意:此文件权限必须为440

  • /etc/sudoers.d/ 目录下定义子配置文件,注意:子配置文件权限必须为440

  • 执行visudo命令来进行编辑,本质上编辑的是 /etc/sudoers 文件

格式说明

  • user host=(runas) command
  • user 针对哪些用户或哪些组,host 在哪些主机,runas 以什么身份,command 可以执行哪些命令;

User

  • 运行命令者的身份,可以为:

    • username
  • #uid

    • %group_name
  • %#gid

    • user_alias 或 runas_alias
  • ALL

host

  • 可以通过哪些主机执行,可以为:

    • ip
    • hostname
    • network(/netmask)
    • host_alias
    • ALL

runas

  • 以哪个用户的身份,不写则默认以root身份运行,可以为:

    • username

    • #uid

    • %group_name

    • %#gid

    • user_alias 或 runas_alias

    • ALL

command

  • 可以运行哪些命令,建议写命令的绝对路径,可以为:

    • command

      • directory

      • sudoedit,特殊权限,可用于向其它用户授予sudo权限;

      • Cmnd_Alias

      • ALL

Example

最大权限

root 	ALL=(ALL) 	ALL 

%wheel 	ALL=(ALL)  	ALL 

一般定义

# 用户名 被管理主机的地址=(可使用的身份,不写则默认root) 授权命令(绝对路径)
azheng ALL=(root) /usr/sbin/cmdpath

# %组名 被管理主机的地址=(可使用的身份,不写则默认root) 授权命令(绝对路径)
%azgrp ALL=(root) /usr/sbin/cmdpath
  • 允许user组的成员关闭此系统
%users  localhost=/sbin/shutdown -h now
  • 允许azheng用户在本主机执行reboot重启命令
azheng ALL=/usr/sbin/reboot


# 测试(azheng用户在执行下面这两条命令时会切换为root用户去执行)
# sudo reboot
# sudo /usr/sbin/reboot
  • 允许student用户 以root身份执行 pidof 和 ifconfig 命令
student ALL=(root)   /sbin/pidof,/sbin/ifconfig

通配符匹配

  • xxx

正则匹配

  • 从版本 1.9.10 开始,可以对路径名和命令行参数使用正则表达式。正则表达式比 shell 风格的通配符更具表现力,并且通常更安全,因为它们在匹配时提供了更大程度的控制。支持的正则表达式类型是扩展正则表达式

sudo免密

# 普通定义
# echo "cephadm ALL = (root) ALL" > /etc/sudoers.d/cephadm
# chmod 0440 /etc/sudoers.d/cephadm


# 测试,需要密码
[cephadm@7 ~]$ sudo cat /etc/shadow
[sudo] password for cephadm:

---

# 定义sudo免密(NOPASSWD:ALL 表示 无需输入普通用户的密码:可以执行任何命令)
# echo "cephadm ALL = (root) NOPASSWD:ALL" > /etc/sudoers.d/cephadm


# 测试,无需密码
[cephadm@7 ~]$ sudo cat /etc/shadow
root:$6$uBF6i5CU0MlC/KEu$36WmiY6998i6m...

别名定义

  • 除普通格式必须要指定外,在一些复杂场景还可以定义别名Alias

别名格式

  • Alias_Type Alias_NAME1 = item1, item2, item3, ...

Alias_Type

  • 别名有四种类型:

    • User_Alias

    • Runas_Alias

    • Host_Alias

    • Cmnd_Alias

Alias_NAME

  • 别名名称,必须使用全大写字符,需匹配以下通配符:
    • [A-Z]([A-Z][0-9]_)*

范例1

# vim /etc/sudoers
...
# 定义用户别名,将azheng 和 xiaohong用户定义为 DEVUSER 这个别名
User_Alias DEVUSER = azheng,xiaohong
# 定义命令别名,允许修改用户名为大小写的密码,但不能修改root的密码
Cmnd_Alias ADMINCMD = /usr/sbin/useradd, /usr/sbin/usermod, /usr/bin/passwd [a-zA-Z]*, !/usr/bin/passwd root
# 调用用户别名和命令别名
DEVUSER ALL=(root) ADMINCMD
...


# 测试:
# xiaohong可以修改azheng的密码
[xiaohong@8 root]$ sudo passwd azheng
...
[sudo] password for xiaohong: #输入xiaohong的密码
Changing password for user azheng.
New password: #
BAD PASSWORD: The password is a palindrome
Retype new password: 
passwd: all authentication tokens updated successfully. #修改成功

# 但xiaohong不能修改root的密码
[xiaohong@8 root]$ sudo passwd root
Sorry, user xiaohong is not allowed to execute '/bin/passwd root' as root on 8.

范例2

User_Alias  NETADMIN=tom, jerry

Cmnd_Alias NETCMND=ip, ifconfig, route

NETADMIN 	localhost=(root) 	NETCMND

语法检查

# 检查语法
visudo -c

# 检查指定配置文件语法
visudo -f /etc/sudoers.d/test

sudo 命令

  • 以sudo的方式来运行指定的命令

syntax

  • sudo [options] COMMAND

option

-l # 列出用户在主机上可用的和被禁止的命令,查看当前用户的sudo权限
-k # 清除此前缓存用户成功认证结果;
-K # 与-k类似,还要删除时间戳文件

-i # 以目标用户身份运行登录shell;还可以指定一个命令
		# 切换身份,和 su user等价
			sudo –i –u azheng
-u # 指定用户执行命令,不指定则为当前用户
-V # 显示版本信息等配置信息
-v # 再延长密码有效期限5分钟,更新时间戳
-b # 在后台执行指令
-p # 改变询问密码的提示符号,示例:-p "password on %h for user %p: "

Example

检票机制

  • 能记录成功认证结果一段时间,默认为5分钟;
# 第一次需要密码
[azheng@8 ~]$ sudo cat /etc/shadow
[sudo] password for azheng: 
root:$6$ePauF38eEVUaxdiV$.3INY6JreJt41uNgNCRGjTGh9MU9Z0qumeckimgImAoXU56cQA1LKiCn5MaDOlh2EwSAEV0XaePsuIC.ESZtx0:18651:0:99999:7::
...

# 再次查看不需要密码,有效期五分钟
[azheng@8 ~]$ sudo cat /etc/shadow
[sudo] password for azheng: 
root:$6$ePauF38eEVUaxdiV$.3INY6JreJt41uNgNCRGjTGh9MU9Z0qumeckimgImAoXU56cQA1LKiCn5MaDOlh2EwSAEV0XaePsuIC.ESZtx0:18651:0:99999:7::

# 清除缓存
[azheng@8 ~]$ sudo -K

# 又需要密码了
[azheng@8 ~]$ sudo cat /etc/shadow
[sudo] password for azheng: 

sudo 注意事项

  • 对于任何重要的事情,通常最好在 sudoers 文件之外使用脚本语言进行命令行处理。

不要将普通用户加入到wheel组

  • 在 sudo 的默认规则中,用户如果加入到 wheel 组中将获得root权限,因此生产中不建议将用户加入到wheel 组中
  • Ubuntu中不要将普通用户加入到 admin 和 sudo 组
[root@8 ~]# vim /etc/sudoers
...
%wheel  ALL=(ALL)   ALL
...

[root@8 ~]# getent group wheel 
wheel:x:10:

[azheng@8 ~]$ cat /etc/shadow
cat: /etc/shadow: Permission denied

[root@8 ~]# groupmems -g wheel -a azheng 
[root@8 ~]# getent group wheel 
wheel:x:10:azheng

[azheng@8 ~]$ sudo cat /etc/shadow

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for azheng: 
root:$6$ePauF38eEVUaxdiV$.3INY6JreJt41uNgNCRGjTGh9MU9Z0qumeckimgImAoXU56cQA1LKiCn5MaDOlh2EwSAEV0XaePsuIC.ESZtx0:18651:0:99999:7:::
bin:*:18397:0:99999:7:::
...

#不建议将普通用户加入到wheel组
# groupmems -g wheel -d azheng
# getent group wheel
wheel:x:10:

cat 授权安全漏洞

# vim /etc/sudoers
...
azheng   ALL=(ALL) /bin/cat /var/log/messages*
...

# ll /var/log/messages*
-rw------- 1 root root  119249 Apr 22 17:46 /var/log/messages
-rw------- 1 root root 1274675 May 18  2021 /var/log/messages-20210518
-rw------- 1 root root 1138820 Jun  2  2021 /var/log/messages-20210602
-rw------- 1 root root  986475 Feb 24 20:03 /var/log/messages-20220224
-rw------- 1 root root   45551 Apr 22 10:09 /var/log/messages-20220422


# 除查看本身定义的日志外,其他的日志也可以查看
[azheng@8 ~]$ sudo cat /var/log/messages /etc/shadow
...
Apr 22 17:46:20 8 systemd[1]: Started Network Manager Script Dispatcher Service.
Apr 22 17:46:31 8 systemd[1]: NetworkManager-dispatcher.service: Succeeded.
root:$6$ePauF38eEVUaxdiV$.3INY6JreJt41uNgNCRGjTGh9MU9Z0qumeckimgImAoXU56cQA1LKiCn5MaDOlh2EwSAEV0XaePsuIC.ESZtx0:18651:0:99999:7:::
...

解决方案1

  • 使用正则表达式

  • 注意:sudo 1.9.10 版本以后才支持正则匹配,1.9.10版本推出时间 2022-03-03

azheng ALL=(ALL) /bin/cat ^/var/log/messages[^[:space:]]*$

解决方案2

  • 使用通配符
azheng ALL=(ALL) /bin/cat /var/log/messages*,!/bin/cat /var/log/messages* *

语法非常严格

  • 这种情况语法检测还不会报错,因此要注意观察编辑的字段
# 定义规则
# vim /etc/sudoers
...
azheng  ALL=(ALL)   /usr/bin/mount /dev/sr0 /mnt
...


# 测试报错,因为/mnt多了/
# sudo mount /dev/sr0 /mnt/
[sudo] password for azheng: 
Sorry, user azheng is not allowed to execute '/bin/mount /dev/sr0 /mnt/' as root on 8.


# 必须和配置文件中的允许指令保持一致 /mnt
# sudo mount /dev/sr0 /mnt
[sudo] password for azheng: 
mount: /mnt: WARNING: device write-protected, mounted read-only.