2

We have a Galera cluster operational on CentOS 7 with sysv, and are looking into migrating to systemd. We are invoking a wsrep_notify_cmd to notify our application of changes in the node states, and we need to combine this with sudo because our application is in a directory with another user/group which mysql does not have access to.

With sysv init this is working fine as the command/script is initiated as root. With systemd, the command/script is initiated under the mysql user - so we need to configure sudoers in order to make it work. Or so we thought.

After switching to systemd, I kept seeing sudo: unable to change to sudoers gid: Operation not permitted in our logs, so I did some testing/debugging with the idea to first start a script which mysql DOES have rights to, and that script will in turn pass on the wsrep_notify_cmd arguments to another script (/data/app/notify.sh) using sudo.

Note: SELinux is disabled.

MySQL server config

MySQL server (test) configuration: wsrep_notify_cmd='/mysql/notify.sh'

Sudoers config

/etc/sudoers.d/mysql is configured as follows:

Defaults:mysql !requiretty
Defaults:mysql umask=0007

Cmnd_Alias NOTIFY = /bin/bash /data/app/notify.sh*
mysql ALL=(app_user) NOPASSWD: NOTIFY

Manual test

Now, sudo su - mysql and then manually running /mysql/notify.sh works fine:

[mysql@testhost /mysql]$ /bin/sudo -u app_user /bin/bash /data/app/notify.sh --status Synced
[mysql@testhost /mysql]$ 

The /data/app/notify.sh script, being ran as app_user writes all passed on parameters to a file - and successfully does when running the above command manually:

[root@testhost /data/app]# cat output.log 
--status Synced

Same thing, but from within systemd mysql service init

However, when doing service mysql start, the /mysql/notify.sh script will not do its job as it should and instead will deny access to any sudo command: sudo: unable to change to sudoers gid: Operation not permitted.

I am running this script using #!/bin/bash -xv and redirecting stderr to a log file:

[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

As you can see, the same command which I was able to run manually from the mysql user shell is NOT working when being invoked from the same script when being ran as part of systemd service mysql start.

What could cause this?

1

If you want to defeat systemd security here, you can modify the Unit's capabilities, eg:

# 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

Note that fewer Capabilities may be required, this was just a quick test

Don't modify that actual file, use eg /etc/systemd/system/mariadb.service.d/MY_SPECIAL.conf

1
  • While setting additional capabilities is needed, it is not sufficient. See my answer for details.
    – Juergen
    May 2 '19 at 15:32
0

Setting capabilities as described in the other answer is needed, but not sufficient, at least if MariaDB is used instead of mySQL.
In addition to adding capabilities, NoNewPrivileges must be false (or no).
Because NoNewPrivileges is implied by PrivateDevices which is set in mariadb.service, we must override this to false.

I was successful in Ubuntu 18 LTS (where Galera doesn't work with the supplied mysql package) with these settings in /etc/systemd/system/mariadb.service.d/mariadb-sudo.conf (there is no need to edit the original mariadb.service):
[Service] CapabilityBoundingSet=CAP_SETUID CapabilityBoundingSet=CAP_SETGID CapabilityBoundingSet=CAP_AUDIT_WRITE PrivateDevices=false

Because mariadb.service has Alias=mysql.service, it can be started with
service mysql start so this seems to match the original question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.