How to allow non-root users to control a systemd service with instances

not-root-usersudosystemd

I need to allow users in the dba group to control the database@ services. The answer to this related question is to just list all systemctl "verbs" that I want to allow in the sudoers file, however, that does not apply to my case because I don't know beforehand what databases might exist in the system. For example, if I list

%dba = /usr/bin/systemctl start database@awsesomeapp
%dba = /usr/bin/systemctl start database@anotherawsesomeapp
%dba = /usr/bin/systemctl start database@yetanotherawsesomeapp
%dba = /usr/bin/systemctl start database@wowyetanotherawsesomeapp
# ... other "verbs" omitted for brevity

that doesn't cover instances that might exist in the future, and a dba won't be able to

$ sudo systemctl start database@omgwowyetanotherawsesomeapp

Anyway, I'm thtinking more in terms of packaging than in fidling with a specific system.

Note that, as shown in this amazing answer to another related question, using sudo globs for this is ultimately insecure:

%dba ALL = /usr/bin/systemctl start database@[a-z]* # UNSAFE!

does allow

$ sudo systemctl start database@awsesomeapp unrelatedservice

I suspect using sudo is not going to solve my problem (although I sure hope I'm wrong). Is there any other way to allow non-root users to control systemd services?

For what it's worth, I need to do this in a CentOS 7 system, and RHEL7 systems in the future. I would also be interested in solutions that work on Arch Linux.

Best Answer

Sudoers file won't work like that, or so it seems to me. Sudoers file is intended to give a specific command access, not to the specify the arguments that can go with that command.

Create a script that runs as root and executes this:

/usr/bin/systemctl start database@

Make the script take an argument such as anotherawesomeapp so it executes this:

Script executes: /usr/bin/systemctl start database@anotherawsesomeapp

Give your users permission to run the script.sh file with /etc/sudoers.

scriptuser ALL=(ALL) NOPASSWD: /path/to/script.sh

User can run it like this:

sh script.sh anotherawsesomeapp

Example:

AppName=$1

/usr/bin/systemctl start database@$AppName;
if [ $? != "0" ] 
then; 
    echo "$AppName could not be started. Are you using the right application name?";
fi
Related Question