![Galera + systemd:wsrep_notify_cmd 因 sudo 失败(无法更改为 sudoers gid:不允许操作)](https://linux22.com/image/83995/Galera%20%2B%20systemd%EF%BC%9Awsrep_notify_cmd%20%E5%9B%A0%20sudo%20%E5%A4%B1%E8%B4%A5%EF%BC%88%E6%97%A0%E6%B3%95%E6%9B%B4%E6%94%B9%E4%B8%BA%20sudoers%20gid%EF%BC%9A%E4%B8%8D%E5%85%81%E8%AE%B8%E6%93%8D%E4%BD%9C%EF%BC%89.png)
我们有一个 Galera 集群在带有 sysv 的 CentOS 7 上运行,并且正在考虑迁移到 systemd。我们调用 awsrep_notify_cmd
来通知我们的应用程序节点状态的更改,并且我们需要将其与 结合起来,sudo
因为我们的应用程序位于另一个mysql
无权访问的用户/组的目录中。
使用 sysv init 可以正常工作,因为命令/脚本是作为 root 启动的。使用 systemd,命令/脚本是在用户下启动的mysql
- 因此我们需要配置 sudoers 才能使其工作。或者说我们是这么认为的。
切换到 systemd 后,我不断地sudo: unable to change to sudoers gid: Operation not permitted
在日志中查看,因此我做了一些测试/调试,想法是首先启动一个mysql
有权限的脚本,然后该脚本wsrep_notify_cmd
将/data/app/notify.sh
使用sudo
.
笔记:SELinux 已禁用。
MySQL 服务器配置
MySQL服务器(测试)配置:wsrep_notify_cmd='/mysql/notify.sh'
Sudoers配置
/etc/sudoers.d/mysql
配置如下:
Defaults:mysql !requiretty
Defaults:mysql umask=0007
Cmnd_Alias NOTIFY = /bin/bash /data/app/notify.sh*
mysql ALL=(app_user) NOPASSWD: NOTIFY
手动测试
现在,sudo su - mysql
然后手动运行/mysql/notify.sh
就可以了:
[mysql@testhost /mysql]$ /bin/sudo -u app_user /bin/bash /data/app/notify.sh --status Synced
[mysql@testhost /mysql]$
/data/app/notify.sh
运行的脚本将所有app_user
传递的参数写入文件 - 并在手动运行上述命令时成功执行:
[root@testhost /data/app]# cat output.log
--status Synced
同样的事情,但是从 systemd mysql 服务 init 内部进行
然而,当执行 时service mysql start
,/mysql/notify.sh
脚本不会完成其应有的工作,而是会拒绝访问任何 sudo
命令:sudo: unable to change to sudoers gid: Operation not permitted
。
我正在使用#!/bin/bash -xv
stderr 运行此脚本并将其重定向到日志文件:
[mysql@testhost /mysql]$ cat debug.log
file=/mysql/args.log
+ file=/mysql/args.log
echo $USER
+ echo mysql
ARGS="$@"
+ ARGS='--status Synced'
/bin/sudo -K
+ /bin/sudo -K
sudo: unable to change to sudoers gid: Operation not permitted
/bin/sudo -u app_user /bin/bash /data/app/notify.sh $ARGS
+ /bin/sudo -u app_user /bin/bash /data/app/notify.sh --status Synced
sudo: unable to change to sudoers gid: Operation not permitted
正如您所看到的,我能够从mysql
用户 shell 手动运行的相同命令是不是当作为 systemd 的一部分运行时从同一脚本调用时工作service mysql start
。
什么可能导致这种情况?
答案1
如果你想在这里击败 systemd 安全性,你可以修改该单元的功能,例如:
# systemctl show mysql | grep Cap
-- CapabilityBoundingSet=16384
# vim /usr/lib/systemd/system/mariadb.service
-- CapabilityBoundingSet=CAP_IPC_LOCK CAP_SETGID CAP_NET_RAW CAP_NET_ADMIN CAP_SETUID CAP_SYS_ADMIN
systemctl daemon-reload
systemctl restart mysqld
systemctl show mysql | grep Cap
-- CapabilityBoundingSet=2126016
请注意,可能需要更少的功能,这只是一个快速测试
不要修改实际文件,使用例如 /etc/systemd/system/mariadb.service.d/MY_SPECIAL.conf
答案2
需要设置其他答案中描述的功能,但这还不够,至少在使用 MariaDB 而不是 mySQL 时是这样。
除了添加功能之外,NoNewPrivileges
必须为 false(或没有)。
因为NoNewPrivileges
中暗示了PrivateDevices
which 被设置mariadb.service
,所以我们必须将其覆盖为 false。
我在 Ubuntu 18 LTS(Galera 不支持提供的 mysql 软件包)中成功使用了这些设置/etc/systemd/system/mariadb.service.d/mariadb-sudo.conf
(无需编辑原始文件mariadb.service
):
[Service] CapabilityBoundingSet=CAP_SETUID CapabilityBoundingSet=CAP_SETGID CapabilityBoundingSet=CAP_AUDIT_WRITE PrivateDevices=false
因为mariadb.service
has Alias=mysql.service
,所以可以从 开始,service mysql start
所以这似乎与原来的问题相符。