【BASH】回顾与知识点梳理(二十四)

该系列目录 --> 【BASH】回顾与知识点梳理(目录)

二十四. 权限规划和身份切换

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

24.1 主机的细部权限规划: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 吧!

如何启动 ACL

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

[root@study ~]# dmesg | grep -i acl
[ 0.330377] systemd[1]: systemd 208 running in system mode. (+PAM +LIBWRAP +AUDIT
+SELINUX +IMA +SYSVINIT +LIBCRYPTSETUP +GCRYPT +ACL +XZ)
[ 0.878265] SGI XFS with ACLs, security attributes, large block/inode numbers, no
debug enabled

瞧!至少 xfs 已经支持这个 ACL 的功能啰!

24.2 ACL 的设定技巧: getfacl, setfacl

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

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

先让我们来瞧一瞧 setfacl 如何使用吧!

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 ~]# touch acl_test1
[root@study ~]# ll acl_test1
-rw-r--r--. 1 root root 0 Jul 21 17:33 acl_test1
[root@study ~]# setfacl -m u:vbird1:rx acl_test1
[root@study ~]# ll acl_test1
-rw-r-xr--+ 1 root root 0 Jul 21 17:33 acl_test1
# 权限部分多了个 + ,且与原本的权限 (644) 看起来差异很大!但要如何查阅呢?
[root@study ~]# setfacl -m u::rwx acl_test1
[root@study ~]# ll acl_test1
-rwxr-xr--+ 1 root root 0 Jul 21 17:33 acl_test1
# 设定值中的 u 后面无使用者列表,代表设定该文件拥有者,所以上面显示 root 的权限成为 rwx 了!

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

getfacl 指令用法
[root@study ~]# getfacl filename
选项与参数:
	getfacl 的选项几乎与 setfacl 相同!所以鸟哥这里就免去了选项的说明啊!

# 请列出刚刚我们设定的 acl_test1 的权限内容:
[root@study ~]# 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 的权限啦!这样看的懂吗? 如果看的懂的话,接下来让我们在测试其他类型的 setfacl 设定吧!

特定的单一群组的权限设定:『 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: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 ~]# setfacl -m m:r acl_test1
[root@study ~]# getfacl acl_test1
# file: acl_test1
# owner: root
# group: root
user::rwx
user:vbird1:r-x 		#effective:r-- 	<==vbird1+mask 均存在者,仅有 r 而已,x 不会生效
group::r--
group:mygroup1:r-x 	#effective:r--
mask::r--
other::r--

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

将前一小节任务二中 /srv/projecta 这个目录,让 myuser1 可以进入查阅,但 myuser1 不具有修改的权力。
答:由于 myuser1 是独立的使用者与群组,因此无法使用传统的 Linux 权限设定。此时使用 ACL 的设定如下:

# 1. 先测试看看,使用 myuser1 能否进入该目录?
[myuser1@study ~]$ cd /srv/projecta
-bash: cd: /srv/projecta: Permission denied <==确实不可进入!
# 2. 开始用 root 的身份来设定一下该目录的权限吧!
[root@study ~]# setfacl -m u:myuser1:rx /srv/projecta
[root@study ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: projecta
# flags: -suser::rwx
user:myuser1:r-x <==还是要看看有没有设定成功喔!
group::rwx
mask::rwx
other::---
# 3. 还是得要使用 myuser1 去测试看看结果!
[myuser1@study ~]$ cd /srv/projecta
[myuser1@study projecta]$ ll -a
drwxrws---+ 2 root projecta 4096 Feb 27 11:29 . <==确实可以查询档名
drwxr-xr-x 4 root root 4096 Feb 27 11:29 ..
[myuser1@study projecta]$ touch testing
touch: cannot touch `testing': Permission denied <==确实不可以写入!

请注意,上述的 1, 3 步骤使用 myuser1 的身份,2 步骤才是使用 root 去设定的!

上面的设定我们就完成了之前任务二的后续需求喔!这么简单呢!接下来让我们来测试一下,如果我用 root 或者是 pro1 的身份去 /srv/projecta 增加文件或目录时,该文件或目录是否能够具有 ACL 的设定? 意思就是说,ACL 的权限设定是否能够被次目录所『继承?』先试看看:

[root@study ~]# cd /srv/projecta
[root@study ~]# touch abc1
[root@study ~]# mkdir abc2
[root@study ~]# ll -d abc*
-rw-r--r--. 1 root projecta 0 Jul 21 17:49 abc1
drwxr-sr-x. 2 root projecta 6 Jul 21 17:49 abc2

你可以明显的发现,权限后面都没有 + ,代表这个 acl 属性并没有继承喔!如果你想要让 acl 在目录底下的数据都有继承的功能,那就得如下这样做了!

使用默认权限设定目录未来文件的 ACL 权限继承『 d:[u|g]:[user|group]:权限 』
# 4. 针对预设权限的设定方式:
# 设定规范:『 d:[ug]:使用者列表:[rwx] 』

# 让 myuser1 在 /srv/projecta 底下一直具有 rx 的预设权限!
[root@study ~]# setfacl -m d:u:myuser1:rx /srv/projecta
[root@study ~]# getfacl /srv/projecta
# file: srv/projecta
# owner: root
# group: projecta
# flags: -suser::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 ~]# 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 Jul 21 17:50 zzz1
drwxrws---+ 2 root projecta 6 Jul 21 17:51 zzz2
# 看吧!确实有继承喔!然后我们使用 getfacl 再次确认看看!
[root@study projecta]# getfacl zzz2
# file: zzz2
# owner: root
# group: projecta
# flags: -suser::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 ~]# getfacl /srv/projecta | grep myuser1
user:myuser1:r-x
default:user:myuser1:r-x
# 1.2 针对每个设定值来处理,注意,取消某个账号的 ACL 时,不需要加上权限项目!
[root@study ~]# setfacl -x u:myuser1 /srv/projecta
[root@study ~]# setfacl -x d:u:myuser1 /srv/projecta

# 2.1 开始让 pro3 这个用户无法使用该目录啰!
[root@study ~]# setfacl -m u:pro3:- /srv/projecta

只需要留意,当设定一个用户/群组没有任何权限的 ACL 语法中,在权限的字段不可留白,而是应该加上一个减号(-) 才是正确的作法!

24.3 使用者身份切换

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

  • 使用一般账号:系统平日操作的好习惯,避免作错一些严重的指令,例如恐怖的『 rm -rf /* 』(千万作不得!)
  • 用较低权限启动系统服务
  • 软件本身的限制

由于上述考虑,所以我们都是使用一般账号登入系统的,等有需要进行系统维护或软件更新时才转为root 的身份来动作。 那如何让一般使用者转变身份成为 root 呢?主要有两种方式喔:

  • 以『 su - 』直接将身份变成 root 即可,但是这个指令却需要 root 的密码,也就是说,如果你要以 su 变成 root 的话,你的一般使用者就必须要有 root 的密码才行;
  • 以『 sudo 指令 』执行 root 的指令串,由于 sudo 需要事先设定妥当,且 sudo 需要输入用户自己的密码,因此多人共管同一部主机时, sudo 要比 su 来的好喔!至少 root 密码不会流出去!
su

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

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

这个 su 的用法当中,有没有加上那个减号『-』差很多喔! 因为涉及 login-shell 与 non-login shell 的变量读取方法。

# 范例一:假设你原本是 dmtsai 的身份,想要使用 non-login shell 的方式变成 root
[dmtsai@study ~]$ su <==注意提示字符,是 dmtsai 的身份喔!
Password: <==这里输入 root 的密码喔!
[root@study dmtsai]# id <==提示字符的目录是 dmtsai 喔!
uid=0(root) gid=0(root) groups=0(root) context=unconf.... <==确实是 root 的身份!
[root@study dmtsai]# env | grep 'dmtsai'
USER=dmtsai <==竟然还是 dmtsai 这家伙!
PATH=...:/home/dmtsai/.local/bin:/home/dmtsai/bin <==这个影响最大!
MAIL=/var/spool/mail/dmtsai <==收到的 mailbox 是 vbird1
PWD=/home/dmtsai <==并非 root 的家目录
LOGNAME=dmtsai
# 虽然你的 UID 已经是具有 root 的身份,但是看到上面的输出讯息吗?
# 还是有一堆变量为原本 dmtsai 的身份,所以很多数据还是无法直接利用。
[root@study dmtsai]# exit <==这样可以离开 su 的环境!

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

所以切换身份时,请务必使用如下的范例二:

# 范例二:使用 login shell 的方式切换为 root 的身份并观察变量
[dmtsai@study ~]$ su -
Password: <==这里输入 root 的密码喔!
[root@study ~]# env | grep root
USER=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
HOME=/root
LOGNAME=root
# 了解差异了吧?下次变换成为 root 时,记得最好使用 su - 喔!
[root@study ~]# exit <==这样可以离开 su 的环境!

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

# 范例三:dmtsai 想要执行『 head -n 3 /etc/shadow 』一次,且已知 root 密码
[dmtsai@study ~]$ head -n 3 /etc/shadow
head: cannot open `/etc/shadow' for reading: Permission denied
[dmtsai@study ~]$ su - -c "head -n 3 /etc/shadow"
Password: <==这里输入 root 的密码喔!
root:$6$wtbCCce/PxMeE5wm$KE2IfSJr.YLP7Rcai6oa/T7KFhOYO62vDnqfLw85...:16559:0:99999:7:::
bin:*:16372:0:99999:7:::
daemon:*:16372:0:99999:7:::
[dmtsai@study ~]$ <==注意看,身份还是 dmtsai 喔!继续使用旧的身份进行系统操作!

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

# 范例四:原本是 dmtsai 这个使用者,想要变换身份成为 vbird1 时?
[dmtsai@study ~]$ su -l vbird1
Password: <==这里输入 vbird1 的密码喔!
[vbird1@study ~]$ su -
Password: <==这里输入 root 的密码喔!
[root@study ~]# id sshd
uid=74(sshd) gid=74(sshd) groups=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
[root@study ~]# exit <==离开第二次的 su
[vbird1@study ~]$ exit <==离开第一次的 su
[dmtsai@study ~]$ exit <==这才是最初的环境!

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

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

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

sudo

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

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

sudo 的指令用法

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

Tips 还记得在安装 CentOS 7 时,在设定一般账号的项目中,有个『让这位使用者成为管理员』的选项吧?如果你有勾选该选项的话, 那除了 root 之外,该一般用户确实是可以使用 sudo 的喔(以鸟哥的例子来说, dmtsai 预设竟然可以使用 sudo 了!)!这是因为建立账号的时候,默认将此用户加入 sudo 的支持中了!详情本章稍后告知!

[root@study ~]# sudo [-b] [-u 新使用者账号]
选项与参数:
-b :将后续的指令放到背景中让系统自行执行,而不与目前的 shell 产生影响
-u :后面可以接欲切换的使用者,若无此项则代表切换身份为 root 。
# 范例一:你想要以 sshd 的身份在 /tmp 底下建立一个名为 mysshd 的文件
[root@study ~]# sudo -u sshd touch /tmp/mysshd
[root@study ~]# ll /tmp/mysshd
-rw-r--r--. 1 sshd sshd 0 Jul 21 23:37 /tmp/mysshd
# 特别留意,这个文件的权限是由 sshd 所建立的情况喔!

# 范例二:你想要以 vbird1 的身份建立 ~vbird1/www 并于其中建立 index.html 文件
[root@study ~]# sudo -u vbird1 sh -c "mkdir ~vbird1/www; cd ~vbird1/www; \
> echo 'This is index.html file' > index.html"
[root@study ~]# ll -a ~vbird1/www
drwxr-xr-x. 2 vbird1 vbird1 23 Jul 21 23:38 .
drwx------. 6 vbird1 vbird1 4096 Jul 21 23:38 ..
-rw-r--r--. 1 vbird1 vbird1 24 Jul 21 23:38 index.html
# 要注意,建立者的身份是 vbird1 ,且我们使用 sh -c "一串指令" 来执行的!

sudo 可以让你切换身份来进行某项任务,例如上面的两个范例。

  • 范例一中,我们的 root 使用 sshd 的权限去进行某项任务! 要注意,因为我们无法使用『 su - sshd 』去切换系统账号 (因为系统账号的shell 是 /sbin/nologin), 这个时候 sudo 真是他 X 的好用了!立刻以 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 去修改这个文件喔!

visudo 与 /etc/sudoers

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

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

  • I. 单一用户可进行 root 所有指令,与 sudoers 文件语法:
    假如我们要让 vbird1 这个账号可以使用 root 的任何指令,基本上有两种作法,第一种是直接透过修改 /etc/sudoers ,方法如下:

    [root@study ~]# 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
    [vbird1@study ~]$ sudo tail -n 1 /etc/shadow <==透过 sudo
    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 vbird1: <==注意啊!这里输入的是『 vbird1 自己的密码 』
    pro3:$6$DMilzaKr$OeHeTDQPHzDOz/u5Cyhq1Q1dy...:16636:0:99999:7:::
    # 看!vbird1 竟然可以查询 shadow !
    

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

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

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

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

    [pro1@study ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro1
    ....(前面省略)....
    [sudo] password for pro1: <==输入 pro1 的密码喔!
    pro3:$6$DMilzaKr$OeHeTDQPHzDOz/u5Cyhq1Q1dy...:16636:0:99999:7:::
    [pro2@study ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro2
    [sudo] password for pro2: <==输入 pro2 的密码喔!
    pro2 is not in the sudoers file. This incident will be reported.
    # 仔细看错误讯息他是说这个 pro2 不在 /etc/sudoers 的设定中!
    

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

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

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

    重点是那个 NOPASSWD 啦!该关键词是免除密码输入的意思喔!

  • III. 有限制的指令操作
    上面两点都会让使用者能够利用 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 的密码!很有用处的!

  • IV. 透过别名建置 visudo
    如上述第三点,如果我有 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 这两行即可!设定方面会比较简单有弹性喔!

  • V. sudo 的时间间隔问题
    或许您已经发现了,那就是,如果我使用同一个账号在短时间内重复操作 sudo 来运作指令的话,在第二次执行 sudo 时,并不需要输入自己的密码!sudo 还是会正确的运作喔!为什么呢? 第一次执行 sudo 需要输入密码,是担心由于用户暂时离开座位,但有人跑来你的座位使用你的账号操作系统之故。 所以需要你输入一次密码重新确认一次身份。

    两次执行 sudo 的间隔在五分钟内,那么再次执行 sudo 时就不需要再次输入密码了, 这是因为系统相信你在五分钟内不会离开你的作业,所以执行 sudo 的是同一个人!呼呼!真是很人性化的设计啊~ ^_^。不过如果两次 sudo 操作的间隔超过 5 分钟,那就得要重新输入一次你的密码了

  • VI. sudo 搭配 su 的使用方式
    很多时候我们需要大量执行很多 root 的工作,所以一直使用 sudo 觉得很烦ㄟ!那有没有办法使用 sudo 搭配 su , 一口气将身份转为 root ,而且还用用户自己的密码来变成 root 呢?是有的!而且方法简单的会让你想笑! 我们建立一个 ADMINS 帐户别名,然后这样做:

[root@study ~]# visudo
User_Alias ADMINS = pro1, pro2, pro3, myuser1
ADMINS ALL=(root) /bin/su -

接下来,上述的 pro1, pro2, pro3, myuser1 这四个人,只要输入『 sudo su - 』并且输入『自己的密码』后, 立刻变成 root 的身份!不但 root 密码不会外流,用户的管理也变的非常方便! 这也是实务上面多人共管一部主机时常常使用的技巧呢!这样管理确实方便,不过还是要强调一下大前提, 那就是『这些你加入的使用者,全部都是你能够信任的用户』!

该系列目录 --> 【BASH】回顾与知识点梳理(目录)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值