理解sudoers(5)语法

本文翻译自 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,代表匹配任何值。

UserRunas可以是用户名,以%为前缀的组名,以#为前缀的数字UID,或以%#为前缀的数字GIDHost可以是主机名,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

其他可用选项包括NOEXECLOG_INPUTLOG_OUTPUT,以及SELinux角色和类型规范。这些都记录在联机帮助页中。

摘要(Digests)

二进制文件的路径(即不是目录名和别名)也可以使用摘要作为前缀:

ams ALL=(ALL) sha224:IkotndXGTmZtH5ZNFtRfIwkG0WuiuOs7GoZ+6g== /bin/ls

只有与摘要匹配时,才会执行指定的二进制文件。可以接受hexBase64格式的224256384512SHA-2摘要。可以只用例如sha512sumopenssl生成。

别名(Aliases)

除了上面列出的之外,UserHostRunas或命令可以是别名,这是一个对应类型的逗号分隔值命名列表。别名可以用在任何的用户,主机,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)

除了别名机制之外,UserHostRunasCommand可以是对应类型的逗号分隔列表。此外,用户规范可能对单个用户包含多个主机和命令集。请谨慎使用这种语法,一旦出现意外你可能必需从头开始检查。

用户和主机也可以是+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*
警告
如果/etc/sudoers包含语法错误,则sudo将无法工作,因此你应该只使用visudo进行编辑,它执行基本的健全性检查,并且只有正确解析时才更新文件。
另一个警告
如果你认真对待手册页中的EBNF,你会发现实际的配置并不遵守它。你可以通过链接到本文而不是尝试自己编写来避免这种悲剧。Happy sudoing!
上一篇
下一篇