天天看点

sudoers文件说明 - sudo免密码 - 限制sudo执行特殊命令

作者:江沪白
sudoers文件说明 - sudo免密码 - 限制sudo执行特殊命令

注意:

sudoers文件非常重要, 如果编辑错误有可能使你的系统无法正常启动. 或者你再也无法进行到特权级别. 此时你有可能需要恢复你的操作系统. 请谨慎操作!

文件位置

sudoers文件位于:/etc/sudoers里面存储了sudo权限相关的配置. 默认配置下,里面存储了root用户以及adm用户组,sudo用户组相关的权限说明:

# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

# Allow members of group sudo to execute any command (sudo group do not need passwd by lijianhong)
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d
           

默认只配置了1个用户,两个组:

  • root用户: 系统的最高管理权限者.
  • admin组: 这是一个历史用户组, 目前在Ubuntu中已经没有使用:在 Ubuntu 中,默认情况下确实没有名为 admin 的用户组。然而,在较早的 Ubuntu 版本中,存在一个名为 admin 的用户组,该用户组用于管理系统的超级用户权限。在 sudoers 文件中看到的 %admin ALL=(ALL) ALL 配置是为了向后兼容性和支持。即使在新的 Ubuntu 版本中没有 admin 用户组,但为了确保向后兼容性,并允许 sudo 权限的分配给 admin 组的成员,这个配置仍然存在。因此,如果你的 Ubuntu 系统中没有 admin 用户组,你可以忽略这个配置,它对系统的实际权限没有影响。你可以使用其他用户组或指定特定的用户来配置 sudoers 文件,以满足你的实际需求。
  • sudo 组: 这个是就正常的sudo用户所在的组, 一般的Ubuntu的默认安装的使用用户.就会在这个sudo组里面. 这样用户就可以有sudo执行权限.
注: 在sudoers文件中, 每一行配置的第一个字段. 如果不是以%开头,表示一般用户. 如果是以%打头,则表示为用户组. 对照上面的默认内容: root是默认用户, 而admin和sudo是默认的两个用户组.

添加sudo权限

我们可以修改 sudoers文件单独添加一个用户的sudo权限.或者是添加一个用户组的sudo权限. 这样就可以做到既可以控制某一个具体的用户.也可以控制一个特定的权限组,这样在有新的用户加入进来的时候,不需要不断的来修改这个sudoers文件来添加权限. 只需要把相应的用户添加到具体相应的权限组即可. 这个有点像ldap的权限管理.

为单个用户添加sudo权限

这个也是最简单,最基本的使用方式. 比如我们要为一个叫jim用户添加sudo权限. 这样这个用户就可以执行sudo命令. 可以直接参考默认的root的配置. 直接在原来的root配置下再添加一条具体用户的配置即可.

# User privilege specification
root    ALL=(ALL:ALL) ALL
jim     ALL=(ALL:ALL) ALL
           

这条指令的解释为:

  • jim 要配置的用户名
  • ALL=(ALL:ALL):表示授予 root 用户在任何主机上、使用任何用户身份(即以任何用户身份)执行任何命令的权限。ALL:表示允许在任何主机上执行命令。=(ALL:ALL):表示以任何用户身份(即以任何用户身份)执行命令。
  • ALL:表示允许执行任何命令。

我们画一个图来解释一下:

sudoers文件说明 - sudo免密码 - 限制sudo执行特殊命令

为一个组添加sudo权限

这个操作与单个用户一样简单,只需要把用户名换为具体的组名. 同时,记住: 组名是以%为标识符号进行标识的. 也就是说组名的前面需要添加一个%表示一个组. 比如我们添加一个minsudev 的组来表示一个开发组. 进入这个开发组的用户都可以执行sudo权限. 于是我们可以这样配置:

#pdev
%minsudev ALL=(ALL) ALL
           

这样所有在组minsudev的用户都有sudo权限了. 不过每个用户在执行sudo相关的命令时,还是要输入密码的,至于密码是什么,那就每个用户自己的事情了.

sudo权限免密码

为了在使用sudo命令的时候更加的丝滑,不需要被不停的输入密码打断. 那我们可以使用特殊的配置给相应的用户或者组添加一些额外的配置. 这样就可以在使用sudo命令时,不用输入密码了.

这个配置其实也非常简单, 可以给单个人配置,也可以给相应的组配置. 前面我们解释了配置中最后一个ALL是代表可以执行任何命令. 那如果想要免密使用sudo, 那就可以在ALL前面加一个前缀: NOPASSWD , 前缀与指令之间用:分隔开.

我们还是对我们假想的开发组:minsudev组配置免密sudo权限. 相应的配置可以修改为:

%minsudev ALL=(ALL) NOPASSWD:ALL
           

当然, 最一般的配置. 大家阅读这篇文章可能用的最基本的配置就是,直接给sudo用户组添加免密sudo权限,其配置如下:

# Allow members of group sudo to execute any command (sudo group do not need passwd by lijianhong)
%sudo   ALL=(ALL:ALL) NOPASSWD:ALL
           

一般用户可能阅读到此就可以结束了, 以下内容一般可能不会涉及. 下面我们会再探讨一些更深入的内容. 看着尝试怎么限制特定用户组的特殊指令权限. 比如关机.

限制特权级命令

在用户分级的系统里面我们想到的是,最原始的想法就是不给相应的用户sudo权限, 这样万事皆休对吧. 但是上面我们讨论了要给用户sudo权限, 而且还要更方便的不输入密码形式的sudo指令执行. 那这就带来了另外一个问题, 我虽然给了某些开发一些比较高级的指令,可以执行sudo, 那我可不可以再限制一些高危操作呢. 或者说是一个运维维护命令呢. 比如:

  • reboot: 这个可不好, 直接主用户重启主机了. 那谁都可以操作的确有些危险. (一般的运维好像没有做得这么细. 曾经我也在某公司的时候记得是可以reboot的).
  • apt install / yum install 此类的包安装命令. 这个可能就是开发吐槽最多的禁止命令了, 一般运维怕开发乱搞机器.那有可能会限制乱安装包. 也有可能是为了数据安全. 禁止了包安装的命令等.

那上面的这些要求怎么办呢? 我们在上面反复提到的指令最后一个字段:ALL, 这个表示是可以执行所有的命令的. 那是不是可以例一些例外? 答案是可以的:

语法

语法也很简单. 直接在ALL的后面添加新的指令, 指令之间用逗号分隔. 不同的是,后面的指令是用!来取反,表示不可执行. 比如我们要限制用户的关机命令:

%minsudev ALL=(ALL) NOPASSWD:ALL,!/usr/bin/reboot
           
注: 这里对指令的列举是使用的全路径. 这样才能准确的限制一个特定的命令而不产生歧义.

这样我们在执行reboot命令的时候,就会提示:

reboot
Failed to set wall message, ignoring: Interactive authentication required.
Failed to reboot system via logind: Interactive authentication required.
Failed to open initctl fifo: Permission denied
           

这个是本身权限不足,非root用户在执行reboot时需要sudo权限. 我们再用sudo权限试试:

[nasdev@homeNas]:~$ sudo reboot
Sorry, user nasdev is not allowed to execute '/usr/sbin/reboot' as root on homeNas.
           

实际可以重启的命令不止一个,我们添加命令:/sbin/reboot

%minsudev ALL=(ALL) NOPASSWD:ALL,!/usr/bin/reboot,!/sbin/reboot
           

这样我们添加了两个可以. 实际上可以关机的命令不止这两个. 如果要限止全还需要添加更多的命令.

限制sudo用户提权为root用户

这是一个非常正常的需要,如果一个用户是普通用户. 但是我们给了他sudo权限. 此时,如果不限制如sudo su这样的命令执行, 那用户还是可以提权到root权限执行. 因此,最常见的普通用户的限制就是限止提权,其实现如下:

%minsudev ALL=(ALL) NOPASSWD:ALL,!/bin/su
           

这样用户在执行 sudo su 进行提权的时候就会被禁止.

命令集与别名

实际我们在应用时, 可能会定制很多的命令集. 比如上面提到的重启相关的命令可能就不止有一个. 那我们如果在配置每一个用户或者用户组的时候都把相应的命令往sudoers文件直接写, 那简直就是维护的噩梦. 这个时候我们就可以用到sudoers文件相关的扩展特性了.

Linux相关的所有的配置文件基本都有扩展功能. 这个sudoders文件也不例外. 实际我们在/etc目录下有一个与sudoers相关的目录:/etc/sudoers.d/

~$ sudo ls -lash /etc/sudoers.d/
total 28K
4.0K drwxr-xr-x   2 root root 4.0K 5月  27 21:10 .
 12K drwxr-xr-x 134 root root  12K 5月  27 21:42 ..
4.0K -r--r-----   1 root root  958 2月   3  2020 README
           

我们可以在这里自定义一些扩展的sudoers相关文件. 然后在主文件: /etc/sudoers中会进行默认加载. 这个我们从 sudoers文件最后的内容可以得知:

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d
           

注意最后一个# 实际并不是注释的意思,这个是包含指令的写法, 如果不存在文件这个包含就不生效. 如果有就进行加载的意思.

我们可以在这里定义一个专门定义命令别名的文件: sudoers_cmdalias

# add by jianhongl , mail: [email protected]
# this file define the command alias which can not be executed by common developer.
# date: 2020-04-17

Cmnd_Alias     SHUTDOWN = /sbin/shutdown,/usr/bin/poweroff,/sbin/poweroff
Cmnd_Alias     HALT = /usr/sbin/halt
Cmnd_Alias     REBOOT = /usr/bin/reboot,/sbin/reboot,/sbin/init
Cmnd_Alias     SHELLS = /bin/sh,/bin/bash,/usr/bin/csh, /usr/bin/ksh, \
                        /usr/local/bin/tcsh, /usr/bin/rsh, \
                        /usr/local/bin/zsh
Cmnd_Alias     NETWORK = /etc/init.d/network,/sbin/ifconfig,/sbin/ip,/bin/hostname,/sbin/ifup,/sbin/ifdown
Cmnd_Alias     PASSWORD = /usr/bin/passwd
Cmnd_Alias     USERS = /usr/sbin/usermod,/usr/sbin/adduser,/usr/sbin/userdel,/usr/sbin/useradd,/usr/sbin/vipw,/usr/sbin/visudo,/usr/bin/gpasswd
Cmnd_Alias     DISKS = /sbin/fdisk,/sbin/parted
# this is end
           

另外我们在开发组的信息维护中,我们添加一个扩展文件:sudoers_minsu这个文件的内容如下:

%minsudev ALL=(ALL) NOPASSWD:ALL,!SHELLS,!HALT,!SHUTDOWN,!REBOOT,!NETWORK,!PASSWORD,!DISKS,!USERS
           

这样, 我们的sudoer的组的权限定义就有了一个比较规范的结构. 在minsudev的权限定义中, 我们就可以直接引用上面定义的命令别名. 这样可以简写我们的配置. 同时也让配置更具备可读性.

其它未尽事宜

以下是一些未详细说明到的一些细节. 如果你想更好的管理sudoers文件, 可以继续阅读完后面部分.

使用visudo命令编辑

上面我们都是直接用vi进行编辑的. 但是这个文件的内容非常重要, 如果文件内容损坏或者格式不正确就有可能导致无法进入系统. 所以最佳实践是使用visudo命令进行编辑, 此命令在退出时候会校验文件内容是否正确. 这样可以保证在退出编辑时文件内容是正确的.

使用visudo校验文件

我们也有可能使用一些扩展文件. 此时我们可以使用命令: visudo -c -f /path/to/file验证我们的文件内容是否正确.

扩展指令的文件名与加载顺序

上面的内容扩展时没有特别提, 实际这个加载是按字典序进行加载的. 因此 sudoers_cmdalias是先于: sudoers_minsu 加载的,这个没有什么问题. 如果你的 配置是先于别名加载, 那就有可能报错. 因此. 在起名时一定要注意加载顺序,否则可能出错.

继续阅读