5

My company set up some software it develops to run as a service using init.d on an older version of SLES. We recently created started setting up a new environment on a SLES 12 instance in Amazon's EC2 and discovered that SLES 12 now uses systemd rather than init.d. However it looks as though services defined in init.d scripts (i.e. in /etc/init.d) can still be started as normal because systemd performs some magic in the background to handle pre-existing init.d scripts which is great.

However we don't want to run our service as the root user - instead we create a new user to run our service. The problem is that when we try to start our service as the non-root user then whatever systemd does to prepare itself to run an old init.d service requests root authentication which we don't think should be necessary. On the older SLES environment (using actual init.d) we can start the service as the non-root user without trouble. As far as I can tell our non-root user permissions and file ownerships are the same in both environments.

The reason I think this is in the under-the-hood handling of old init.d stuff by systemd is that the script to start our service echoes a line of text immediate before the actual command to start/stop the service but that line isn't output i.e. we're being asked for root auth before the echo statement. The authentication is required for a certain package/module buried in systemd but I can't remember its name at the moment.

Note that we'd like to avoid creating a service specific .service file for our service if possible - we want to stick with the init.d script we have and just run it as the non-root user. Also, we'd like to run the service without the use of sudo (we don't need sudo in the old environment).

Apologies for the lack of specifics in this question - I'll update it with more specific details once I get back to the office and can grab the specific details etc. This seems like it might be a common problem though so I'm hoping someone can shed some light on this.

Specifically: we want to run a service defined with an old init.d script as a non-root user using systemd on SLES 12.

(update 1) The exact result of trying to run our script /etc/init.d/my_service stop is:

/etc/init.d/my_service stop
redirecting to systemctl stop electrum-gateway-main.service
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units === Authentication is required to stop 'my_service.service'.
Authenticating as: root
Password:

The service wasn't running when we tried to stop it but that's not relevant to the auth issue.

I've done a little more digging in our script and the script reaches the following line before asking for auth:

. /etc/rc.status

So this is where the trouble lies. Should one need root privileges to call /etc/rc.status?

6

In systemd (and other modern init systems), service startup is strictly separated into two steps:

  1. User tools (e.g. systemctl) remotely ask init (pid 1) to start a particular service.
  2. Init reads the service's configuration, sets up environment (including switching to the desired user account), and runs the executable.

Due to this indirection, services are guaranteed to always have the same environment regardless of who and how started them. (Previously, user environment like locale, path, or SELinux contexts leaking into services used to be a common problem.)

(For init.d scripts, the distro's lsb-functions file contains the magic redirects to 'systemctl start', so they also receive the same indirection.)

This also means that you cannot start a service "as the same user" – you must configure a specific username in the relevant systemd .service file (and if there is none, you really should write one).

The 'start service' call is normally privileged, but you can write a polkit rule allowing it per-user or per-service (if the systemd version is recent enough):

/* /etc/polkit-1/rules.d/allow-whatever.rules */

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units") {
        var verb = action.lookup("verb");
        var unit = action.lookup("unit");
        if (subject.user == "manager"
            && unit == "app.service"
            && (verb == "start" || verb == "stop" || verb == "restart"))
        {
            return polkit.Result.YES;
        }
    }
});

Alternatively, it might be possible to opt out of indirection in the init.d script, but then you would also lose systemd's service tracking entirely – your daemon will look like a regular user process.

  • So, because I haven't specified a user via a .service file, systemd ends up trying to start the service using root for the start service command? – user5860663 Nov 16 '16 at 9:02
  • Yes. But that has absolutely nothing to do with your shown password prompt. You need root (or polkit permissions) to ask systemd to start a service. – grawity Nov 16 '16 at 9:56
  • Works like a charm! – flotto May 10 '17 at 10:00
0

Running your services as a non-root user is a good idea. Besides the Polkit suggestion in the other answer, there are a couple of more conventional ways to start a service not as root:

  1. Use sudo. A sudo rule can allow a specific user to run the start and restart commands for a particular service, but do no actions as root, providing the same kind of limited privilege.
  2. Use the systemd user mode. systemd offers users the ability to manage services under the user's control with a per-user systemd instance, enabling users to start, stop, enable, and disable their own units.

I think the systemd user mode may exist more with desktop use-cases in mind. For a server, I recommend allowing using the sudo solution. In the systemd .service file, you can also set the User= directive to specify the user the service runs as-- possible the same user you've been the ability to start it.

The "polkit" solution is an action-at-distance solution-- it seems difficult to realize what's allowing the user to start the service. However, with sudo you are clearly calling calling sudo, and with systemd user mode, you are clearly using that feature.

If I was an in environment where the Polkit solution was set up, I would have no clue to track down why starting the service was even working unless a co-worker left some documentation about it.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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