6

I'm trying to allow a group of users to gain some control over an instance of a dhcpcd service. In other words I would like to have them be able to run:

systemctl (start,stop,...) dhcpcd@eth0.service

without being prompted for a password but only on dhcpcd@eth0.service. I have already come across ways of doing that, however they require enumeration of every subcommand in its own line.

%mygroup ALL=NOPASSWD: /usr/bin/systemctl start dhcpcd@eth0.service, /usr/bin/systemctl stop dhcpcd@eth0.service, ...

Is there a more elegant method of doing this?

  • Also, systemd can use PolicyKit to authenticate users, and it offers more granular control than plain sudo. Here's an example on how to achieve exactly what you want. – André Borie Jul 3 '16 at 15:17
  • I had a look at policykit, and found where I could implement the required behaviour with my own regex. But my lack of confidence in my regex being explicit and modifying a new part of the system made me favour a small enumeration / shell script method. Thank you for your suggestion, now I know another method to control user policies. – XYZ Rose Jul 4 '16 at 11:20
7

Sudoers wildcards are only supported with globbing (man glob, man fnmatch). Yet, the start, stop, restart (, etc.) commands for systemctl cannot be globbed since they are not files.

The fact that you need to enumerate every command is a good thing from a security standpoint. If dhcpcd@eth0.service is updated with a command, say shutdown-machine on a system update your sudo users will not be able to use it (thankfully).

There is a note about this in the sudoers manual:

 Wildcards in command line arguments should be used with care.
 Command line arguments are matched as a single, concatenated string.  This mean a wildcard character such as ‘?’ or
 ‘*’ will match across word boundaries, which may be unexpected.  For example, while a sudoers entry like:

     %operator ALL = /bin/cat /var/log/messages*

 will allow command like:

     $ sudo cat /var/log/messages.1

 It will also allow:

     $ sudo cat /var/log/messages /etc/shadow

 which is probably not what was intended.  In most cases it is better to do command line processing outside of the
 sudoers file in a scripting language.

On the other hand, if you want to save on typing you can do exactly what the manual suggests: use a scripting language. For example you could wirte something like this in, say, /usr/local/sbin/sudoers-dhcpd.sh:

#!/bin/sh

case "$1" in
  start)
    systemctl start dhcpcd@eth0.service
    ;;
  stop)
    systemctl stop dhcpcd@eth0.service
    ;;
  restart)
    systemctl restart dhcpcd@eth0.service
    ;;
  *)
    echo You are not allowed to do that!
    ;;
esac

And add a sudoers line as follows:

%mygroup ALL=NOPASSWD: /usr/local/sbin/sudoers-dhcpd.sh
  • 1
    You could also add a case with start|stop|restart) and use $1 in the command. But from the security standpoint you're then depending that there are no exploitable bugs in the | operator in the case matches. – grochmal Jul 3 '16 at 13:48
  • 1
    Or just define the exact 3 specific commands allowed in sudoers without any wildcards. Just as OP described. It may not be elegant but it is secure. – anthony Jun 7 '18 at 7:37

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.