这安全吗?
echo "Defaults insults" >> /etc/sudoers
如果是,我可以这样做吗?
echo "## First line" >> /etc/sudoers
echo "### Second line" >> /etc/sudoers
echo "Defaults insults" >> /etc/sudoers
echo "### Totally the last line" >> /etc/sudoers
有没有更好的方法来做到这一点visudo
?
我正在制作一个 bash 脚本,这部分需要打开和关闭侮辱。
答案1
至少有 3 种方式可能造成危险:
如果
/etc/sudoers
不以换行符结尾(其中sudo
并visudo
允许),例如,如果它以非终止#includedir /etc/sudoers.d
行结尾,则您的命令将使其:#includedir /etc/sudoers.dDefaults insults
这会破坏它并使其
sudo
无法使用。echo
可能无法写入完整的字符串,例如文件系统已满。例如,它可能只能写Defaults in
。这又会破坏你的sudoers
文件。- 在具有多个管理员的计算机上,如果两者都尝试
/etc/sudoers
同时修改,则他们写入的数据可能会交错。
visudo
避免了这些问题,因为它允许您编辑临时文件 ( /etc/sudoers.tmp
),检测文件是否被修改(不幸的是,如果文件被修改则不会)成功地修改,因为它似乎没有检查编辑器的退出状态),检查语法,并执行rename
(原子操作)将新文件移动到位。因此,它将要么成功更新文件(前提是您的编辑器在无法写入新文件的情况下也保持文件不变),要么如果不能或语法无效则失败。
visudo
还可以防止多人sudoers
同时编辑文件。
现在,visudo
以自动方式可靠地使用也很棘手。这样做有几个问题:
visudo
您可以使用环境变量指定编辑器命令VISUAL
(优先于EDITOR
),但前提是该env_editor
选项尚未禁用。- 我的版本
visudo
至少在某些条件下编辑/etc/sudoers
它包含的所有文件($VISUAL
为所有文件运行)。所以你必须确保你$VISUAL
只修改/etc/sudoers
. - 如上所示,它不检查编辑器的退出状态。因此,您需要确保编辑器保存的文件已成功写入或根本没有修改。
- 如果出现问题,它会提示用户。
解决所有这些问题有点棘手。您可以这样做:
NEW_TEXT='Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
umask 077
{
cat /etc/sudoers.tmp && printf "\n%s\n" "$NEW_TEXT"
} > /etc/sudoers.tmp.tmp &&
mv -f /etc/sudoers.tmp.tmp /etc/sudoers.tmp
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
env_editor
如果未设置则不起作用。
在 GNU 系统上,更好的替代方法是使用which ,如果无法编写较新的版本,sed -i
则应保持不变:sudoers.tmp
添加insults
:
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Default/s/!*\(insults\)/\1/g
$q
}
$a\Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
消除侮辱:
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Defaults/s/!*\(insults\)/!\1/g
$q
}
$a\Defaults !insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
答案2
我查了一下,似乎很久以前includedir
就可以提供支持sudo
(据我所知大约是 2001 年),所以 RHEL 5 应该支持它。在 sudoers 中查找包含指令:
sudo grep '#includedir' /etc/sudoers
如果您得到结果,那么理想情况下您应该在该目录中添加和删除文件,通常是/etc/sudoers.d
.在 shell 脚本中可能很难确定该路径。
无论如何,假设sudoers.d
,您最多应该0600
在该目录中添加具有权限的文件。就像是:
sudo sh -c '
umask 0177;
filename="/etc/sudoers.d/$1";
echo 'Defaults insults' > "$filename";
visudo -cf "$filename" || rm "$filename"
' _ 99-insults
(99-insults
其中要创建的文件的名称在哪里sudoers.d
。)然后删除设置就像这样简单:
sudo rm /etc/sudoers.d/99-insults
事实上,这就是sh -c
命令的最后一部分的作用 - 如果检查失败,则删除此文件visudo
,这样您就不会留下损坏的sudoers
.
您可以使用tee -a
:EDITOR
$ sudo VISUAL='tee -a' visudo <<<"Defaults insults"
Defaults insults
$ sudo tail /etc/sudoers
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
Defaults insults
我不知道 EL5 是否sudo
支持includedir
,但如果支持,请在其中创建新文件visudo -f
。