龙之介大人

Linux的ACL权限与sudo的使用
14.1 主机的权限规划:ACL 的使用从一开始开始,我们就一直强调 Linux 的权限概念是非常重要的! 但是传...
扫描右侧二维码阅读全文
03
2019/10

Linux的ACL权限与sudo的使用

14.1 主机的权限规划:ACL 的使用

从一开始开始,我们就一直强调 Linux 的权限概念是非常重要的! 但是传统的权限仅有三种身份 (owner, group, others) 搭配三种权限 (r,w,x) 而已,并没有办法单纯的针对某一个使用者或某一个群 组来设定特定的权限需求,例如前一小节最后的那个任务! 此时就得要使用 ACL 这个机制啦!这 玩意挺有趣的,底下我们就来谈一谈:

14.1.1 什么是 ACL 与如何支持启动 ACL

ACL 是 Access Control List 的缩写,主要的目的是在提供传统的 owner,group,othersread,write,execute 权限之外的细部权限设定。ACL 可以针对单一使用者,单一文件或目录来进行 r,w,x 的权限规范,对于需要特殊权限的使用状况非常有帮助。

那 ACL 主要可以针对哪些方面来控制权限呢?他主要可以针对几个项目:

  • 使用者 (user):可以针对使用者来设定权限;
  • 群组 (group):针对群组为对象来设定其权限;
  • 默认属性 (mask):还可以针对在该目录下在建立新文件/目录时,规范新数据的默认权限;

也就是说,如果你有一个目录,需要给一堆人使用,每个人或每个群组所需要的权限并不相同时,在过去,传统的 Linux 三种身份的三种权限是无法达到的,因为基本上,传统的 Linux 权限只能针 对一个用户、一个群组及非此群组的其他人设定权限而已,无法针对单一用户或个人来设计权限。而 ACL 就是为了要改变这个问题啊!好了,稍微了解之后,再来看看如何让你的文件系统可以支持 ACL 吧!

14.1.2 如何启动 ACL

事实上,原本 ACL 是 unix-like 操作系统的额外支持项目,但因为近年以来 Linux 系统对权限细部设定的热切需求,因此目前 ACL 几乎已经预设加入在所有常见的 Linux 文件系统的挂载参数中 (ext2/ext3/ext4/xfs 等等)!所以你无须进行任何动作, ACL 就可以被你使用啰!不过,如果你不放 心系统是否真的有支持 ACL 的话,那么就来检查一下核心挂载时显示的信息吧!

[root@study xiaoqi]# dmesg | grep -i acl
[    0.802725] 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)
[    5.984586] SGI XFS with ACLs, security attributes, no debug enabled
  • 至少 xfs 已经支持这个 ACL 的功能.

14.1.3 ACL的设定技巧

好了,既然知道我们的 filesystem 有支持 ACL 之后,接下来该如何设定与观察 ACL 呢? 很简单,利用这两个指令就可以了:

  • getfacl:取得某个文件/目录的 ACL 设定项目;
  • setfacl:设定某个目录/文件的 ACL 规范。

getfacl

  • setfacl 指令用法介绍及最简单的『 u:账号:权限 』设定
 [root@study ~]# setfacl [-bkRd] [{-m|-x} acl 参数] 目标文件名 
 选项与参数:
-m :设定后续的 acl 参数给文件使用,不可与 -x 合用;
-x :删除后续的 acl 参数,不可与 -m 合用;
-b :移除『所有的』 ACL 设定参数;
-k :移除『预设的』 ACL 参数,关于所谓的『预设』参数于后续范例中介绍;
-R :递归设定 acl ,亦即包括次目录都会被设定起来;
-d :设定『预设 acl 参数』的意思!只对目录有效,在该目录新建的数据会引用此默认值

上面谈到的是 acl 的选项功能,那么如何设定 ACL 的特殊权限呢?特殊权限的设定方法有很多,我们先来谈谈最常见的,就是针对单一使用者的设定方式:

#1. 针对特定使用者的方式:
#设定规范:『 u:[使用者账号列表]:[rwx] 』,例如针对 vbird1 的权限规范 rx :
[root@study xiaoqi]# touch acl_test1
[root@study xiaoqi]# ll acl_test1 
-rw-r--r--. 1 root root 0 10月  3 16:53 acl_test1
[root@study xiaoqi]# setfacl -m u:vbird1:rx acl_test1
[root@study xiaoqi]# ll acl_test1 
-rw-r-xr--+ 1 root root 0 10月  3 16:53 acl_test1
#权限部分多了个 + ,且与原本的权限 (644) 看起来差异很大!但要如何查阅呢?

[root@study xiaoqi]# setfacl -m u::rwx acl_test1
[root@study xiaoqi]# ll acl_test1 
-rwxr-xr--+ 1 root root 0 10月  3 16:53 acl_test1
#设定值中的 u 后面无使用者列表,代表设定该文件拥有者,所以上面显示 root 的权限成为 rwx 了!

上述动作为最简单的 ACL 设定,利用『 u:使用者:权限 』的方式来设定的啦!设定前请加上 -m 这 个选项。 如果一个文件设定了 ACL 参数后,他的权限部分就会多出一个 + 号了!但是此时你看到的权限与实际权限可能就会有点误差! 那要如何观察呢?就透过 getfacl !

setfacl

  • setfacl:设定某个目录/文件的 ACL 规范。
[root@study ~]# getfacl filename
选项与参数:
getfacl 的选项几乎与 setfacl 相同!所以鸟哥这里就免去了选项的说明啊!

#请列出刚刚我们设定的 acl_test1 的权限内容:
[root@study xiaoqi]# getfacl acl_test1 
#file: acl_test1    <==说明文件名而已!
#owner: root        <==说明此文件的拥有者,亦即 ls -l 看到的第三使用者字段
#group: root        <==此文件的所属群组,亦即 ls -l 看到的第四群组字段
user::rwx            <==使用者列表栏是空的,代表文件拥有者的权限
user:vbird1:r-x        <==针对 vbird1 的权限设定为 rx ,与拥有者并不同!
group::r--            <==针对文件群组的权限设定仅有 r
mask::r-x            <==此文件预设的有效权限 (mask)
other::r--            <==其他人拥有的权限!

上面的数据非常容易查阅吧?显示的数据前面加上 # 的,代表这个文件的默认属性,包括文件名、文件拥有者与文件所属群组。底下出现的 user, group, mask, other 则是属于不同使用者、群组与有效权限(mask)的设定值。 以上面的结果来看,我们刚刚设定的 vbird1 对于这个文件具有 r 与 x 的权限!

  • 特定的单一群组的权限设定:『 g:群组名:权限 』
#2.针对特定群组的方式:
#设定规范:『 g:[群组列表]:[rwx] 』,例如针对 mygroup1 的权限规范 rx :
[root@study xiaoqi]# setfacl -m g:mygroup1:rx acl_test1
[root@study xiaoqi]# getfacl acl_test1 
#file: acl_test1
#owner: root
#group: root
user::rwx
user:vbird1:r-x
group::r--
group:mygroup1:r-x    <==这里就是新增的部分!多了这个群组的权限设定!
mask::r-x
other::r--
  • 针对有效权限设定:『 m:权限 』

基本上,群组与使用者的设定并没有什么太大的差异啦!如上表所示,非常容易了解意义。不过,你 应该会觉得奇怪的是, 那个 mask 是什么东西啊?其实他有点像是『有效权限』的意思!他的意义 是: 使用者或群组所设定的权限必须要存在于 mask 的权限设定范围内才会生效,此即『有效权限 (effective permission)』我们举个例子来看,如下所示:

#3.针对有效权限 mask 的设定方式:
#设定规范:『 m:[rwx] 』,例如针对刚刚的文件规范为仅有 r :
[root@study xiaoqi]# setfacl -m:r acl_test1 
[root@study xiaoqi]# getfacl acl_test1 
#file: acl_test1
#owner: root
#group: root
user::r--
user:vbird1:r-x        #effective:r-- <--vbird1+mask 均存在者,仅有 r 而已,x 不会生效
group::r--
group:mygroup1:r-x    #effective:r--    
mask::r-x
other::r--

您瞧,vbird1 与 mask 的集合发现仅有 r 存在,因此 vbird1 仅具有 r 的权限而已,并不存在 x 权限!这就是 mask 的功能了!我们可以透过使用 mask 来规范最大允许的权限,就能够避免不小心 开放某些权限给其他使用者或群组了不过,通常都是将 mask 设定为 rwx !然后再分别依据不同的使用者/群组去规范她们的权限就是了。

例题:将前一小节任务二中 /srv/projecta 这个目录,让 myuser1 可以进入查阅,但 myuser1 不具有修改的权力。

答:由于 myuser1 是独立的使用者与群组,因此无法使用传统的 Linux 权限设定。此时使用 ACL 的设定如下:

#1.先测试看看,使用 myuser1 能否进入该目录?
[myuser@study xiaoqi]$ cd /srv/projecta/
bash: cd: /srv/projecta/: 权限不够

#2.开始用 root 的身份来设定一下该目录的权限吧!
[root@study xiaoqi]# setfacl -m u:myuser1:rx /srv/projecta/
[root@study xiaoqi]# 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::---

#还是要使用 myuser1 去测试看看结果!
[myuser1@study xiaoqi]$ cd /srv/projecta/
[myuser1@study projecta]$ pwd
/srv/projecta
[myuser1@study projecta]$ ll -la
总用量 4
drwxrws---+ 2 root projecta  6 10月  2 22:56 .    <--可以查看
drwxr-xr-x. 3 root root     54 10月  2 22:56 ..


[myuser1@study projecta]$ touch testing
touch: 无法创建"testing": 权限不够    <--确实不可以写入!
  • 请注意,上述的 1, 3 步骤使用 myuser1 的身份,2 步骤才是使用 root 去设定的!

接下来让我们来测试一下,如果我 用 root 或者是 pro1 的身份去 /srv/projecta 增加文件或目录时,该文件或目录是否能够具有 ACL 的设定?意思就是说,ACL 的权限设定是否能够被次目录所『继承?』先试看看:

[root@study xiaoqi]# cd /srv/projecta/
[root@study projecta]# touch abc1
[root@study projecta]# mkdir abc2
[root@study projecta]# ll -d abc*
-rw-r--r--. 1 root projecta 0 10月  3 17:38 abc1
drwxr-sr-x. 2 root projecta 6 10月  3 17:38 abc2
你可以明显的发现,权限后面都没有 + ,代表这个 acl 属性并没有继承喔!如果你想要让 acl 在目录底下的数据都有继承的功能,那就得如下这样做了!
  • 使用默认权限设定目录未来文件的 ACL 权限继承『 d:[u|g]:[user|group]:权限 』
#4.针对预设权限的设定方式:
#设定规范:『d:[ug]:使用者列表:[rwx] 』

#让 myuser1 在 /srv/projecta 底下一直具有 rx 的预设权限!
[root@study projecta]# setfacl -m d:u: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::---


[root@study projecta]# cd /srv/projecta/
[root@study projecta]# touch zzz1
[root@study projecta]# mkdir zzz2
[root@study projecta]# ll -d zzz*
-rw-rw----+ 1 root projecta 0 10月  3 17:42 zzz1
drwxrws---+ 2 root projecta 6 10月  3 17:42 zzz2
#看吧!确实有继承喔!然后我们使用 getfacl 再次确认看看!

[root@study projecta]# getfacl zzz2
#file: zzz2
#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::---

透过这个『针对目录来设定的默认 ACL 权限设定值』的项目,我们可以让这些属性继承到次目录底下呢! 非常方便!那如果想要让 ACL 的属性全部消失又要如何处理?透过『 setfacl -b 文件名 』

问:针对刚刚的 /srv/projecta 目录的权限设定中,我需要 1)取消 myuser1 的设定(连同默认值),以及 2)我不能让 pro3 这个用户使用该目录,亦即 pro3 在该目录下无任何权限,该如何设定?

答:取消全部的 ACL 设定可以使用 -b 来处理,但单一设定值的取消,就得要透过 -x 才行了!所以你应该这样作:

#1.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

#1.2 针对每个设定值来处理,注意,取消某个账号的 ACL 时,不需要加上权限项目!
[root@study projecta]# setfacl -x u:myuser1 /srv/projecta/
[root@study projecta]# setfacl -x d:u:myuser1 /srv/projecta/

2.1开始让 pro3 这个用户无法使用该目录啰!
[root@study projecta]# setfacl -m u:pro3:- /srv/projecta/
  • 只需要留意,当设定一个用户/群组没有任何权限的 ACL 语法中,在权限的字段不可留白,而是应该加上一个减号 (-) 才是正确的作法!

14.2 使用者身份切换

为什么?在 Linux 系统当中还要作身份的变换?可能有底下几个原因啦!

  • 使用一般账号:系统平日操作的好习惯

事实上,为了安全的缘故,一些老人家都会建议你,尽量以一般身份使用者来操作 Linux 的日常 作业!等到需要设定系统环境时, 才变换身份成为 root 来进行系统管理,相对比较安全啦!避 免作错一些严重的指令,例如恐怖的『 rm -rf / 』

  • 用较低权限启动系统服务

相对于系统安全,有的时候,我们必须要以某些系统账号来进行程序的执行。 举例来说, Linux 主机上面的一套软件,名称为 apache ,我们可以额外建立一个名为 apache 的用户来启动 apache 软件啊,如此一来,如果这个程序被攻破,至少系统还不至于就损毁了~

  • 软件本身的限制

在远古时代的 telnet 程序中,该程序默认是不许使用 root 的身份登入的,telnet 会判断登入者的 UID,若 UID 为 0 的话,那就直接拒绝登入了。所以,你只能使用一般使用者来登入 Linux 服务器。 此外, ssh 也可以设定拒绝 root 登入喔!那如果你有系统设定需求该如何是好啊? 就变换身份啊!

由于上述考虑,所以我们都是使用一般账号登入系统的,等有需要进行系统维护或软件更新时才转为 root 的身份来动作。 那如何让一般使用者转变身份成为 root 呢?主要有两种方式喔:
  • 以『 su - 』直接将身份变成 root 即可,但是这个指令却需要 root 的密码,也就是说,如果你要以 su 变成 root 的话,你的一般使用者就必须要有 root 的密码才行;
  • 以『 sudo 指令 』执行 root 的指令串,由于 sudo 需要事先设定妥当,且 sudo 需要输入用户自己的密码,因此多人共管同一部主机时,sudo 要比 su 来的好喔!至少 root 密码不会流出去!

底下我们就来说一说 su 跟 sudo 的用法!

14.2.1 su

su 是最简单的身份切换指令了,他可以进行任何身份的切换唷!方法如下:

[root@study ~]# su [-lm] [-c 指令] [username]
选项与参数:
-  :单纯使用 - 如『 su - 』代表使用 login-shell 的变量文件读取方式来登入系统;
    若使用者名称没有加上去,则代表切换为 root 的身份。
-l :与 - 类似,但后面需要加欲切换的使用者账号!也是 login-shell 的方式。
-m :-m 与 -p 是一样的,表示『使用目前的环境设定,而不读取新使用者的配置文件』 
-c :仅进行一次指令,所以 -c 后面可以加上指令喔!

上表的解释当中有出现之前谈过的 login-shell 配置文件读取方式,如果你忘记那是啥东西, 请先回去瞧瞧再回来吧!这个 su 的用法当中,有没有加上那个减号『 - 』差很多喔! 因为涉及 login-shell 与 non-login shell 的变量读取方法。这里让我们以一个小例子来说明吧!

#范例一:假设你原本是 xiaoqi 的身份,想要使用 non-login shell 的方式变成 root
[xiaoqi@study ~]$ su
密码:
[root@study xiaoqi]# id <-提示的信息xiaoqi
uid=0(root) gid=0(root) 组=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023    <--确实是root的身份
[root@study xiaoqi]# env | grep 'xiaoqi'
HOSTNAME=study.centos.xiaoqi
USER=xiaoqi        <--用户还是xiaoqi
PATH=/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/xiaoqi/.local/bin:/home/xiaoqi/bin
MAIL=/var/spool/mail/xiaoqi
PWD=/home/xiaoqi <--目录并不是root的家目录
LOGNAME=xiaoqi

#虽然你的 UID 已经是具有 root 的身份,但是看到上面的输出讯息吗?
#还是有一堆变量为原本 dmtsai 的身份,所以很多数据还是无法直接利用。
[root@study xiaoqi]# exit 
exit

单纯使用『 su 』切换成为 root 的身份,读取的变量设定方式为 non-login shell 的方式,这种方式 很多原本的变量不会被改变,尤其是我们之前谈过很多次的 PATH 这个变量,由于没有改变成为 root 的环境,因此很多 root 惯用的指令就只能使用绝对路径来执行咯。其他的还有 MAIL 这个变量,你输入 mail 时,收到的邮件竟然还是 xiaoqi 的,而不是 root 本身的邮件!是否觉得很奇怪啊!所以切换身份时,请务必使用如下的范例二:

#范例二:使用 login shell 的方式切换为 root 的身份并观察变量
[xiaoqi@study ~]$ su -
密码:
上一次登录:四 10月  3 18:10:26 CST 2019pts/0 上
[root@study ~]# env | grep 'root'
USER=root
MAIL=/var/spool/mail/root
PATH=/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
HOME=/root
LOGNAME=root
#了解差异了吧?下次变换成为 root 时,记得最好使用 su - !

上述的作法是让使用者的身份变成 root 并开始操作系统,如果想要离开 root 的身份则得要利用 exit 离开才行。那我如果只是想要执行『一个只有 root 才能进行的指令,且执行完毕就恢复原本的身份』呢?那就可以加上 -c 这个选项! 请参考底下范例三!

#范例三:xiaoqi 想要执行『 head -n 3 /etc/shadow 』一次,且已知 root 密码
[xiaoqi@study ~]$ head -n 3 /etc/shadow
head: 无法打开"/etc/shadow" 读取数据: 权限不够

[xiaoqi@study ~]$ su - -c "head -n 3 /etc/shadow"
密码:    <--输入密码
root:$6$IMbw1vkZUaa9tcgT$2IIAFR4RXN4Fy93tfGae3OrELBJN98EYFhFpubiGtcXUim99egm8OWBqj1Eeqx1Ioz3yubj8prWv05Drwsypz0::0:99999:7:::
bin:*:16659:0:99999:7:::
daemon:*:16659:0:99999:7:::
[xiaoqi@study ~]$   <-- 注意身份还是

由于 /etc/shadow 权限的关系,该文件仅有 root 可以查阅。为了查阅该文件,所以我们必须要使用 root 的身份工作。但我只想要进行一次该指令而已,此时就使用类似上面的语法吧!好,那接下来,如果我是 root 或者是其他人,想要变更成为某些特殊账号,可以使用如下的方法来切换喔!

#范例四:原本是 xiaoqi 这个使用者,想要变换身份成为 vbird1 时?
[xiaoqi@study ~]$ su -l vbird1
密码: <--这里输入 vbird1 的密码喔!
上一次登录:三 10月  2 22:14:10 CST 2019pts/0 上
[vbird1@study ~]$ su -
密码:    <--这里输入 root 的密码喔!
上一次登录:四 10月  3 18:18:18 CST 2019pts/0 上
[root@study ~]# id sshd
uid=74(sshd) gid=74(sshd) 组=74(sshd)    <--确实有存在此用户

[root@study ~]# su -l sshd
This account is currently not available.  <--用户存在但是无法登录

[root@study ~]# finger  sshd
Login: sshd                             Name: Privilege-separated SSH
Directory: /var/empty/sshd              Shell: /sbin/nologin
Last login 四 10月  3 18:47 (CST) on pts/0
No mail.
No Plan.

[root@study ~]# exit
[vbird1@study ~]$ exit

su 就这样简单的介绍完毕,总结一下他的用法是这样的:

  • 若要完整的切换到新使用者的环境,必须要使用『 su - username 』或『 su -l username 』, 才会连同 PATH/USER/MAIL 等变量都转成新用户的环境;
  • 如果仅想要执行一次 root 的指令,可以利用『 su - -c "指令串" 』的方式来处理;
  • 使用 root 切换成为任何使用者时,并不需要输入新用户的密码;

14.2.2 sudo

虽然使用 su 很方便啦,不过缺点是,当我的主机是多人共管的环境时,如果大家都要使用 su 来切换成为 root 的身份,那么不就每个人都得要知道 root 的密码,这样密码太多人知道可能会流出去,很不妥当!怎办办?透过 sudo 来处理即可!

相对于 su 需要了解新切换的用户密码 (常常是需要 root 的密码),sudo 的执行则仅需要自己的密码即可! 甚至可以设定不需要密码即可执行 sudo 呢!由于 sudo 可以让你以其他用户的身份执行 指令 (通常是使用 root 的身份来执行指令),因此并非所有人都能够执行 sudo ,而是仅有规范到 /etc/sudoers 内的用户才能够执行 sudo 这个指令喔!说的这么神奇,底下就来瞧瞧那 sudo 如何使用?

事实上,一般用户能够具有 sudo 的使用权,就是管理员事先审核通过后,才开放 sudo 的使用权的!因此, 除非是信任用户,否则一般用户默认是不能操作 sudo

  • sudo 的指令用法

由于一开始系统默认仅有 root 可以执行 sudo ,因此底下的范例我们先以 root 的身份来执行,等到谈到 visudo 时,再以一般使用者来讨论其他 sudo 的用法吧! sudo 的语法如下:

[root@study ~]# sudo [-b] [-u 新使用者账号] 
选项与参数:
-b :将后续的指令放到背景中让系统自行执行,而不与目前的 shell 产生影响 
-u :后面可以接欲切换的使用者,若无此项则代表切换身份为 root 。

#范例一:你想要以 sshd 的身份在 /tmp 底下建立一个名为 mysshd 的文件
[xiaoqi@study ~]$ sudo -u sshd touch /tmp/mysshd

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 xiaoqi: 
[xiaoqi@study ~]$ ll /tmp/mysshd 
-rw-r--r--. 1 sshd sshd 0 10月  3 21:29 /tmp/mysshd
#特别留意,这个文件的权限是由 sshd 所建立的情况喔!


#范例二:你想要以 vbird1 的身份建立 ~vbird1/www 并于其中建立 index.html 文件
[xiaoqi@study ~]$ sudo -u vbird1 sh -c "mkdir ~vbird1/www; cd ~vbird1/www; \
> echo 'This is index.html file' > index.html"
[sudo] password for xiaoqi: 
[root@study xiaoqi]# ll ~vbird1/www/index.html 
-rw-r--r--. 1 vbird1 vbird1 24 10月  3 21:41 /home/vbird1/www/index.html
#要注意,建立者的身份是 vbird1 ,且我们使用 sh -c "一串指令" 来执行的!

sudo 可以让你切换身份来进行某项任务,例如上面的两个范例。范例一中,我们的 root 使用 sshd 的权限去进行某项任务! 要注意,因为我们无法使用『 su - sshd 』去切换系统账号 (因为系统账号的 shell 是 /sbin/nologin), 这个时候 sudo 是非常方便的!立刻以 sshd 的权限在 /tmp 底下建 立文件!查阅一下文件权限你就了解意义啦! 至于范例二则更使用多重指令串 (透过分号 ; 来延续指令进行),使用 sh -c 的方法来执行一连串的指令!

  • 但是 sudo 预设仅有 root 能使用啊!为什么呢?因为 sudo 的执行是这样的流程:
  1. 当用户执行 sudo 时,系统于 /etc/sudoers 文件中搜寻该使用者是否有执行 sudo 的权限;
  2. 若使用者具有可执行 sudo 的权限后,便让使用者『输入用户自己的密码』来确认;
  3. 若密码输入成功,便开始进行 sudo 后续接的指令(但 root 执行 sudo 时,不需要输入密码);
  4. 若欲切换的身份与执行者身份相同,那也不需要输入密码。

所以说,sudo 执行的重点是:能否使用 sudo 必须要看 /etc/sudoers 的设定值, 而可使用 sudo 者 是透过输入用户自己的密码来执行后续的指令串由于能否使用与 /etc/sudoers 有关, 所以我们当然要去编辑 sudoers 文件!不过,因为该文件的内容是有一定的规范的,因此直接使用 vi 去编辑是不好的。此时,我们得要透过 visudo 去修改这个文件喔!

14.2.3 visudo 与 /etc/sudoers

从上面的说明我们可以知道,除了 root 之外的其他账号,若想要使用 sudo 执行属于 root 的权限 指令,则 root 需要先使用 visudo 去修改 /etc/sudoers ,让该账号能够使用全部或部分的 root 指令功能。为什么要使用 visudo 呢?这是因为 /etc/sudoers 是有设定语法的,如果设定错误那会造成无 法使用 sudo 指令的不良后果。因此才会使用 visudo 去修改,并在结束离开修改画面时,系统会去检验 /etc/sudoers 的语法就是了。

一般来说,visudo 的设定方式有几种简单的方法喔,底下我们以几个简单的例子来分别说明:

单一用户可进行 root 所有指令,与 sudoers 文件语法:

假如我们要让 vbird1 这个账号可以使用 root 的任何指令,基本上有两种作法,第一种是直接透过修改 /etc/sudoers ,方法如下:

[root@study xiaoqi]# visudo 
....
root    ALL=(ALL)       ALL <--找到这一行,大约在98行
vbird1    ALL=(ALL)       ALL <--在上面这一行的后面添加这行
...

有趣吧!其实 visudo 只是利用 vi 将 /etc/sudoers 文件呼叫出来进行修改而已,所以这个文件就是 /etc/sudoers 啦! 这个文件的设定其实很简单,如上面所示,如果你找到 98 行 (有 root 设定 的那行) 左右,看到的数据就是:

使用者账号   登入者的来源主机名=(可切换的身份)   可下达的指令
root                   ALL=(ALL)              ALL

上面这一行的四个组件意义是:

  1. 『使用者账号』:系统的哪个账号可以使用 sudo 这个指令的意思;
  2. 『登入者的来源主机名』:当这个账号由哪部主机联机到本 Linux 主机,意思是这个账号可能是由哪一部网络主机联机过来的, 这个设定值可以指定客户端计算机(信任的来源的意思)。默认值 root 可来自任何一部网络主机
  3. 『(可切换的身份)』:这个账号可以切换成什么身份来下达后续的指令,默认 root 可以切换成任何人;
  4. 『可下达的指令』:可用该身份下达什么指令?这个指令请务必使用绝对路径撰写。 预设 root 可以切换任何身份且进行任何指令之意。

那个 ALL 是特殊的关键词,代表任何身份、主机或指令的意思。所以,我想让 vbird1 可以进行 任何身份的任何指令,就如同上表特殊字体写的那样,其实就是复制上述默认值那一行,再将 root 改成 vbird1 即可啊! 此时『vbird1 不论来自哪部主机登入,他可以变换身份成为任何人,且可以进行系统上面的任何指令』之意。 修改完请储存后离开 vi,并以 vbird1 登入系统后,进行如下的测试看看:

[vbird1@study ~]$ tail -n 1 /etc/shadow <==注意!身份是 vbird1
tail: cannot open `/etc/shadow' for reading: Permission denied
#因为不是 root 嘛!所以当然不能查询 /etc/shadow


[xiaoqi@study ~]$ sudo tail -n 1 /etc/shadow<==透过 sudo
[sudo] password for xiaoqi: 
myuser:$6$huR0Ovy6$5/hXE.TvwtTPOmc226qNvgxQnfgot9M.KcLFAF7cuvNIWPgph4n.MchHjy1m9ZzWAifbNxc9FwPxS5T/saC7s.:18172:0:99999:7:::
#看!vbird1 竟然可以查询 shadow !

注意到了吧!vbird1 输入自己的密码就能够执行 root 的指令!所以,系统管理员当然要了解 vbird1 这个用户的『操守』才行!否则随便设定一个用户,他恶搞系统怎办?另外,一个一个设定太麻烦了,能不能使用群组的方式来设定呢?参考底下的第二种方式吧。

利用 wheel 群组以及免密码的功能处理 visudo

我们在本章前面曾经建立过 pro1, pro2, pro3 ,这三个用户能否透过群组的功能让这三个人可以管理系统? 可以的,而且很简单!同样我们使用实际案例来说明:

[root@study ~]# visudo <==同样的,请使用 root 先设定
...
%wheel  ALL=(ALL)       ALL <--大约在105行左右,请将这行的#删掉
...
#在最左边加上 % ,代表后面接的是一个『群组』之意!改完请储存后离开

[root@study xiaoqi]# usermod -a -G wheel pro1  <--将 pro1 加入 wheel 的支持

上面的设定值会造成『任何加入 wheel 这个群组的使用者,就能够使用 sudo 切换任何身份来操作任何指令』的意思。你当然可以将 wheel 换成你自己想要的群组名。接下来,请分别切换身份成为 pro1 及 pro2 试看看 sudo 的运作。

[pro1@study xiaoqi]$ sudo tail -n 1 /etc/shadow  <--注意身份是 pro1
....
[sudo] password for pro1: 
myuser:$6$huR0Ovy6$5/hXE.TvwtTPOmc226qNvgxQnfgot9M.KcLFAF7cuvNIWPgph4n.MchHjy1m9ZzWAifbNxc9FwPxS5T/saC7s.:18172:0:99999:7:::

[pro2@study xiaoqi]$ sudo tail -n 1 /etc/shadow        <--注意身份是 pro2
....
[sudo] password for pro2:     <--输入 pro2 的密码喔!
pro2 不在 sudoers 文件中。此事将被报告。

这样理解群组了吧?如果你想要让 pro3 也支持这个 sudo 的话,不需要重新使用 visudo ,只要利用 usermod 去修改 pro3 的群组支持,让 pro3 用户加入 wheel 群组当中,那他就能够进行 sudo! 好了!那么现在你知道为啥在安装时建立的用户,就是那个 xiaoqi 预设可以使用 sudo 了 吗?请使用『 id xiaoqi 』看看, 这个用户是否有加入 wheel 群组!

从 CentOS 7 开始,在 sudoers 文件中,预设已经开放 %wheel 那一行啰!以前的 CentOS 旧版本都是没有启用的!

既然我们都信任这些 sudo 的用户了,能否提供『不需要密码即可使用 sudo 』呢? 就透过如下的方式:

[root@study ~]# visudo <==同样的,请使用 root 先设定
%wheel ALL=(ALL) NOPASSWD: ALL <==大约在 108 行左右,请将 # 删掉!
#在最左边加上 % ,代表后面接的是一个『群组』之意!改完请储存后离开

[pro1@study xiaoqi]$ sudo tail -n 1 /etc/shadow
myuser:$6$huR0Ovy6$5/hXE.TvwtTPOmc226qNvgxQnfgot9M.KcLFAF7cuvNIWPgph4n.MchHjy1m9ZzWAifbNxc9FwPxS5T/saC7s.:18172:0:99999:7:::

有限制的指令操作:

上面两点都会让使用者能够利用 root 的身份进行任何事情!这样总是不太好~如果我想要让用户仅能够进行部分系统任务,比方说,系统上面的 myuser1 仅能够帮 root 修改其他用户的密码时,亦即『当使用者仅能使用 passwd 这个指令帮忙 root 修改其他用户的密码』时,你该如何撰写呢? 可以这样做:

[root@study ~]# visudo <==注意是 root 身份
myuser1 ALL=(root) /usr/bin/passwd <==最后指令务必用绝对路径

上面的设定值指的是『myuser1 可以切换成为 root 使用 passwd 这个指令』的意思。其中要注意 的是: 指令字段必须要填写绝对路径才行!否则 visudo 会出现语法错误的状况发生! 此外,上 面的设定是有问题的!我们使用底下的指令操作来让您了解:

[myuser1@study ~]$ sudo passwd myuser3 <==注意,身份是 myuser1
[sudo] password for myuser1: <==输入 myuser1 的密码
Changing password for user myuser3. <==底下改的是 myuser3 的密码喔!这样是正确的 New password:
Retype new password:
passwd: all authentication tokens updated successfully.

[myuser1@study ~]$ sudo passwd
Changing password for user root. <==见鬼!怎么会去改 root 的密码?

恐怖啊!我们竟然让 root 的密码被 myuser1 给改变了!下次 root 回来竟无法登入系统...欲哭无泪~怎办? 所以我们必须要限制用户的指令参数!修改的方法为将上述的那行改一改先:

[root@study ~]# visudo <==注意是 root 身份
myuser1 ALL=(root) !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root

在设定值中加上惊叹号『 ! 』代表『不可执行』的意思。因此上面这一行会变成:可以执行『 passwd 任意字符』,但是『 passwd 』与『 passwd root 』这两个指令例外! 如此一来 myuser1 就无法 改变 root 的密码了!这样这位使用者可以具有 root 的能力帮助你修改其他用户的密码, 而且也 不能随意改变 root 的密码!很有用处的!

如上述第三点,如果我有 15 个用户需要加入刚刚的管理员行列,那么我是否要将上述那长长的 设定写入 15 行啊? 而且如果想要修改命令或者是新增命令时,那我每行都需要重新设定,很麻烦!有没有更简单的方式? 是有的!透过别名即可!我们 visudo 的别名可以是『指令别名、帐户别名、主机别名』等。不过这里我们仅介绍帐户别名, 其他的设定值有兴趣的话,可以自行玩玩!

假设我的 pro1, pro2, pro3 与 myuser1, myuser2 要加入上述的密码管理员的 sudo 列表中, 那我可以创立一个帐户别名称为 ADMPW 的名称,然后将这个名称处理一下即可。处理的方式如下:

[root@study ~]# visudo <==注意是 root 身份
User_Alias ADMPW = pro1, pro2, pro3, myuser1, myuser2
Cmnd_Alias ADMPWCOM = !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root 
ADMPW ALL=(root) ADMPWCOM

我透过 User_Alias 建立出一个新账号,这个账号名称一定要使用大写字符来处理,包括Cmnd_Alias(命令别名)、Host_Alias(来源主机名别名) 都需要使用大写字符的!这个 ADMPW 代表后面接的那些实际账号。而该账号能够进行的指令就如同 ADMPWCOM 后面所指定的那样! 上表最后一行则写入这两个别名 (账号与指令别名),未来要修改时,我只要修改 User_Alias 以 及 Cmnd_Alias 这两行即可!设定方面会比较简单有弹性喔!

最后修改:2019 年 10 月 03 日 11 : 02 PM

发表评论