本文翻译自 Abhijit Menon-Sen撰写的“ Understanding sudoers(5) syntax ”。
原文地址:http://toroid.org/sudoers-syntax
这个简单的sudo配置指南适用于任何不想在sudoers(5)联机帮助中看到“
Don’t despair (不要绝望)”、“ Quick guide to EBNF (EBNF快速指南)”的人。
提示:sudoers文件语法描述为 Extended Backus-Naur Form (EBNF)格式,联机帮助中有“如果你不懂EBNF的话,不要绝望”。以及“EBNF快速指南字样”。
Sudo(su“do”)允许管理员委派权限,使某些用户(或用户组)能够以root或其他用户的身份运行某些(或所有)命令,同时提供命令及其参数的审计跟踪。
本指南旨在补充联机帮助页。不包括各种环境、安全性和日志记录选项;联机帮助页中的说明很容易理解。
前90%
你可能仅仅需要了解的是:
%adm ALL = (ALL) NOPASSWD: ALL
上面这段意味着“任何主机上的adm组中的任何用户可以任何用户的身份运行任何命令且不需要密码”。第一个ALL
表示主机,第二个表示目标用户,最后一个表示允许的命令。如果省略NOPASSWD:
,则需要密码。
用户规范(User specifications)
/etc/sudoers
文件包含“用户规范”,用于定义用户可执行的命令。调用sudo
时,将按顺序检查这些规范,并使用最后一个匹配项。基本的用户规范看起来像这样:
User Host = (Runas) Command
可以解释为:“User可以在Host上以Runas身份运行Command命令”。
以上的任何或所有都可以被替换为特殊关键字ALL,代表匹配任何值。
User
和Runas
可以是用户名,以%为前缀的组名,以#为前缀的数字UID
,或以%#为前缀的数字GID
,Host
可以是主机名,IP
地址或整个网络(例如192.0.2.0/24
),但不可是127.0.0.1
。
运行为(Runas)
这个可选子句控制sudo将要以何种目标用户(或组)的身份运行命令,换句话说,它将接受哪种-u
和-g
参数的组合。
如果省略该子句,则允许用户以root
身份运行命令。如果您指定用户名,例如(postgres
),sudo
将接受-u postgres
并以该用户身份运行命令。这两种情况下,sudo
都不接受-g
。
如果你还指定了目标组,例如(postgres:postgres
),则sudo
将接收列出的用户和组的任意组合(请参阅下面的别名部分)。如果你只指定目标组,如(:postgres
),则sudo
将接受并执行-g postgres
,但仅将命令以调用用户的权限运行。
这就是你经常在90%的例子中看到(ALL:ALL
)的原因。
命令(Commands)
在最简单的情况下,命令是可执行文件的完整路径,允许使用任何参数运行。你可以在允许命令的路径后指定参数列表,只允许使用确切的参数,或者写””以允许在没有任何参的情况下执行。
命令也可以是完整的路径(包括结尾的/)。这允许执行该目录中的所有文件,但不允许在子目录中执行。
ams ALL=/bin/ls, /bin/df -h /, /bin/date "", \
/usr/bin/, sudoedit /etc/hosts, \
OTHER_COMMANDS
关键字sudoedit
也会被识别为命令,并且可以像其他命令一样指定参数。建议使用这种方式而不是使用sudo
运行特定的编辑器,因为它以普通用户身份运行编辑器,而只将编辑器输出的文件以root
(或其他指定用户)的身份保存到指定位置。
如上所示,可以指定逗号分隔的命令和别名列表。命令也可以在路径或参数表中使用shell
通配符(但请参阅下面关于后者的警告)。
sudo
非常灵活,细粒度的设置非常诱人,但很难理解复杂设置的后果,并且最终可能会出现意外问题。请尽量保持简单。
选项(Options)
在命令之前,你可以指定零个或多个选项来控制它的执行方式。最重要的选项是NOPASSWD(无需密码)和SETENV(允许用户为命令设置环境变量)。
ams ALL=(ALL) NOPASSWD: SETENV: /bin/ls
其他可用选项包括NOEXEC
,LOG_INPUT
和LOG_OUTPUT
,以及SELinux
角色和类型规范。这些都记录在联机帮助页中。
摘要(Digests)
二进制文件的路径(即不是目录名和别名)也可以使用摘要作为前缀:
ams ALL=(ALL) sha224:IkotndXGTmZtH5ZNFtRfIwkG0WuiuOs7GoZ+6g== /bin/ls
只有与摘要匹配时,才会执行指定的二进制文件。可以接受hex
或Base64
格式的224
、256
、384
和512
位SHA-2
摘要。可以只用例如sha512sum
或openssl
生成。
别名(Aliases)
除了上面列出的之外,User
,Host
,Runas
或命令可以是别名,这是一个对应类型的逗号分隔值命名列表。别名可以用在任何的用户,主机,Runas或命令上。总是以大写命名,并可以参考下面的例子定义:
# Type_Alias NAME = a, b : NAME_2 = c, d, …
User_Alias TRUSTED = %admin, !ams
Runas_Alias LEGACYUSERS = oldapp1, oldapp2
Runas_Alias APPUSERS = app1, app2, LEGACYUSERS
Host_Alias PRODUCTION = www1, www2, \
192.0.2.1/24, !192.0.2.222
Cmnd_Alias DBA = /usr/pgsql-9.4/bin, \
/usr/local/bin/pgadmin
别名定义还可以包括相同类型的另外一个别名(例如,上面的LEGACYUSERS
)。你不能在命令别名中包含NOPASSWD
等选项。
列表中的任何项都可以在前面加上!表示否定。这可以用于包括某个组但排除某个用户,或排除网络中的某个地址等。否定也可以在命令列表中使用,但注意联机帮助页的警告:尝试从ALL
中使用!“排除”命令一般是不会生效的。
要涉及多个用户、主机或命令的规则时,请使用别名。
默认选项(Default options)
sudo
有许多选项,其值可以在配置文件中设置,无条件覆盖默认设置,或仅针对给定用户,主机或命令。默认值是合理的,因此除非你正在做一些特殊的事情,否则你不需要关心这些选项。
选项值在一个或多个Default
开头的行中指定。下面的示例打开env_reset
,关闭insults
(!insults
意味着not insults
),将password_tries
设置为4
,以此类推。所有的值设置为无条件,即适用于每个用户。
Defaults env_reset, !insults, password_tries=4, \
lecture=always
Defaults passprompt="Password for %p:"
也可以仅为特定主机,用户或命令设置选项,如下所示。Defaults@host
设置特定主机的选项,Defaults:user
用于(调用)用户,Defaults!command
用于命令,Defaults>user
用于目标用户,你也可以在这些定义中使用别名。
Defaults@localhost insults
Defaults:ams insults, !lecture
Defaults>root mail_always, mailto="foo@example.org"
Cmnd_Alias FOO = /usr/bin/foo, /usr/bin/bar, \
/usr/local/bin/baz
Defaults!FOO always_set_home
首先解析无条件默认值,然后是主机和用户默认值,然后是Runas
默认值,最后是命令的默认值。
手册中介绍了非常多的可用选项。
一些复杂的问题(Complications)
除了别名机制之外,User
,Host
,Runas
和Command
可以是对应类型的逗号分隔列表。此外,用户规范可能对单个用户包含多个主机和命令集。请谨慎使用这种语法,一旦出现意外你可能必需从头开始检查。
用户和主机也可以是+netgroup
或更加深奥的东西,具体取决于插件。主机名也可以使用shell
通配符(请参阅fqdn
选项)。
如果省略Runas
但是不省略(),则sudo
将拒绝-u
和-g
并进将命令作为调用用户运行。
你可以在命令路径和参数中使用通配符,但他们的含义是不同的。在路径中,*
将不包括/
,因此/usr/bin/*
将包括/usr/bin/who
但不包括/usr/bin/X11/xterm
。在参数中*
会包括/
;另外,参数匹配为单个字符串(不是单独的单词列表),因此*
可以跨单词匹配。联机帮助也包含以下有问题的示例,该示例允许将其他参数无限制的传递给/bin/cat
:
%operator ALL = /bin/cat /var/log/messages*