Galera + systemd:wsrep_notify_cmd 因 sudo 失败(无法更改为 sudoers gid:不允许操作)

Galera + systemd:wsrep_notify_cmd 因 sudo 失败(无法更改为 sudoers gid:不允许操作)

我们有一个 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 -xvstderr 运行此脚本并将其重定向到日志文件:

[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中暗示了PrivateDeviceswhich 被设置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.servicehas Alias=mysql.service,所以可以从 开始,
service mysql start所以这似乎与原来的问题相符。

相关内容