sudo 免密授权

日常使用自动化脚本的时候常常会出现这种问题: 如果创建专用系统账户如果执行系统服务命令要么需要 sudo 输入密码, 要么就是无法使用命令

像是这种情况在日常当中也是十分常见, 好处也是很明显直接低配权限防止被入侵的时候完全掌控服务器:

1
2
3
4
5
6
# 如果想以非 root 用户重启 nginx, 以下命令是无法生效
# 如果你的用户组正好是 sudo 组, 则会提示你必须手动输入用户密码确认启动
systemctl restart nginx

# sudo 组则是需要通过以下方式
sudo systemctl restart nginx

但是在自动化运维的时候就很麻烦了, 引入不可能调用这些命令还要让你手动输入密码, 毕竟都自动化了肯定不能这样操作

所以这里就衍生出 visudoNOPASSWD 概念, 通过配置可以让指定用户或用户组执行 sudo 命令时无需输入密码:

1
2
# 进入 sudo 配置菜单, 注意调用的默认编辑其是 nano 而非 vi/vim
sudo visudo

这里内部每一行就是定义权限:

1
2
3
4
5
6
7
8
9
10
username ALL=(ALL) NOPASSWD: ALL
# 按照配置顺序依次解释如下:
# - username [指定的系统用户, 替换成实际用户名, 如果以 % 开头的就代表用户组]
# - ALL [限制该规则生效的访问主机, 默认所有主机 ALL 访问即可]
# - (ALL) [限制用户可切换到的用户或组, 比如 devops/root 之类切换允许对应组]
# - NOPASSWD: [指定后续命令无需输入密码即可执行, 如果不带该标识则需要输入授权密码]
# - ALL [限制允许执行的命令, ALL 表示所有命令, 若指定路径如 /usr/bin/apt 则仅允许该命令]
# 这里命令是允许多条共存, 如下给专属账号配置专用, 但是后定义的规则优先级更高所以一般默认命令应该放置到最后
# 最好实践就是专门创建个执行组来做命令执行调用, 比如如下配置就设定只有 devops 用户组的用户才能无密码调用这些命令
%devops ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/systemctl

另外有的发行版追加了 /etc/sudoers.d 目录用于专门放置扩展, 如果可以可以直接在这个目录生成我们自己的权限规则:

1
2
3
4
sudo touch /etc/sudoers.d/devops # 创建文件
sudo chown root:root /etc/sudoers.d/devops # 绑定归属
# 赋予权限, 注意先修改完成之后在更改权限, 否则会导致文件一直只读
sudo chmod 0440 /etc/sudoers.d/devops

然后内容就按照之前定义追加就可以, 注意上面提示 chmod 必须在修改后再处理:

1
2
# 系统维护组, 让他 sudo 运行系统命令 apt 和 systemctl 无需密码  
%devops ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/systemctl

可以通过 sudo -l 就能看到目前用户的生效规则, 虽然是个很方便特性, 但是安全授权还是要注意, 不要分配多余的权限.

上面的方法其实会导致整个 systemctl 都被掌控, 这是很危险的权限, 所以需要指定精细化命令:

1
2
# 主允许 apt 更新和 systemctl 重载 nginx 配置
%devops ALL=(ALL) NOPASSWD: /usr/bin/apt update, /usr/bin/systemctl reload nginx

这种授权操作必须谨慎操作