理解 sudoers

 

sudoers 是默认的 sudo 策略插件,它确定用户的 sudo 权限,其策略在 /etc/sudoers 文件或 LDAP 中定义。

sudoers 语法

sudoers options

sudo 的行为可以通过 Default_Entry 行进行修改

  • 输入密码后 30 分钟内不需要再次输入密码
Defaults            timestamp_timeout=30
  • 不再需要用户 peter 输入密码
Defaults:peter      !authenticate

User specifications

User_Sepc

常用的格式

USERS HOSTS=(RUNAS) [NOPASSWD:]COMMANDS
  • 所有属于 wheel 用户组的用户可以无密码运行任何命令
%wheel ALL=(ALL) NOPASSWD:ALL
  • 用户 peter 可以无密码运行任何命令
peter ALL=(ALL) NOPASSWD:ALL

当多个条目匹配一个用户时,将按顺序应用这些条目。如果有多个匹配项,则使用最后一个匹配项。

SUDOERS FILE FORMAT

When multiple entries match for a user, they are applied in order. Where there are multiple matches, the last match is used (which is not necessarily the most specific match).

  • 允许用户 peter在 hostA 主机上执行所有命令,并且允许其以 root 身份在所有主机执行 /usr/bin/dnf 命令
peter hostA=(ALL) ALL
peter ALL=(root) NOPASSWD:/usr/bin/dnf

注意:这里的顺序很重要,不同的顺序会导致最后生效的匹配结果不同。

学习更多例子可以查看 man sudoersEXAMPLE 章节,。

为特定用户配置 sudoers

使用 sudo visudo 命令会直接编辑系统默认配置,对于普通用户,更好的方法是在 /etc/sudoers.d 目录下单独添加配置文件,文件名可以使用用户名

sudo visudo /etc/sudoers.d/$USER

使用 sudo

切换到不同用户

# root user
sudo -i

# foo user
sudo -i -u foo

以不同用户执行命令

# run dnf update command as root user
sudo dnf update

# run ls -l command as foo user
sudo -u foo ls -l

sudoers EBNF

使用 Railroad Diagram Generator 加载以下 sudo EBNF 生成轨道图

The User specification is the part that actually determines who may run what.

EBNF Tags

Alias ::= 'User_Alias'  User_Alias (':' User_Alias)* |
          'Runas_Alias' Runas_Alias (':' Runas_Alias)* |
          'Host_Alias'  Host_Alias (':' Host_Alias)* |
          'Cmnd_Alias'  Cmnd_Alias (':' Cmnd_Alias)*

User_Alias ::= NAME '=' User_List

Runas_Alias ::= NAME '=' Runas_List

Host_Alias ::= NAME '=' Host_List

Cmnd_Alias ::= NAME '=' Cmnd_List

NAME ::= [A-Z]([A-Z][0-9]_)*

User_List ::= User |
              User ',' User_List

User ::= '!'* user_name |
         '!'* '#' uid |
         '!'* '%' group |
         '!'* '%#' gid |
         '!'* '+' netgroup |
         '!'* '%:' nonunix_group |
         '!'* '%:#' nonunix_gid |
         '!'* User_Alias

Runas_List ::= Runas_Member |
               Runas_Member ',' Runas_List

Runas_Member ::= '!'* user_name |
                 '!'* '#' uid |
                 '!'* '%' group |
                 '!'* '%#' gid |
                 '!'* '%:' nonunix_group |
                 '!'* '%:#' nonunix_gid |
                 '!'* '+' netgroup |
                 '!'* Runas_Alias

Host_List ::= Host |
              Host ',' Host_List

Host ::= '!'* host_name |
         '!'* ip_addr |
         '!'* network('/'netmask)? |
         '!'* '+' netgroup |
         '!'* Host_Alias

Cmnd_List ::= Cmnd |
              Cmnd ',' Cmnd_List

command_name ::= file_name |
                 file_name args |
                 file_name '""'

Cmnd ::= '!'* command_name |
         '!'* directory |
         '!'* "sudoedit" |
         '!'* Cmnd_Alias

Default_Type ::= 'Defaults' |
                 'Defaults' '@' Host_List |
                 'Defaults' ':' User_List |
                 'Defaults' '!' Cmnd_List |
                 'Defaults' '>' Runas_List

Default_Entry ::= Default_Type Parameter_List

Parameter_List ::= Parameter |
                   Parameter ',' Parameter_List

Parameter ::= Parameter '=' Value |
              Parameter '+=' Value |
              Parameter '-=' Value |
              '!'* Parameter

User_Spec ::= User_List Host_List '=' Cmnd_Spec_List 
              (':' Host_List '=' Cmnd_Spec_List)*

Cmnd_Spec_List ::= Cmnd_Spec |
                   Cmnd_Spec ',' Cmnd_Spec_List

Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd

Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'

SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')

Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' |
              'SETENV:' | 'NOSETENV:' | 'LOG_INPUT:' | 'NOLOG_INPUT:' |
              'LOG_OUTPUT:' | 'NOLOG_OUTPUT:')

参考文档