[systemd-devel] Design patterns for privilege separating systemd services?
Colin Walters
walters at verbum.org
Wed Feb 17 17:50:32 UTC 2021
I'm having a debate with the SSSD team over here around multiple systemd units and privilege separation: https://github.com/SSSD/sssd/issues/3412
And we also had a related topic come up in Fedora CoreOS where we have a privileged service (rpm-ostreed.service) and we want a separate unprivileged management service (zincati.service) to be able to perform privileged operations; right now we install a polkit rule to authorize the `zincati` user, but I think that's quite hacky. I'd actually like to use DynamicUser=yes for zincati.
I think what I want is a way to tell systemd to create something like a private socketpair() between the two services dynamically. So the "privileged" part of zincati.service is just a systemd drop-in like:
/usr/lib/systemd/system/rpm-ostreed.service.d/
```
[Unit]
DynamicSocketPair=zincati.service
```
Then when either service starts for the first time, systemd creates a socketpair() and hands off one end to the activating service. And there'd be an extension of sd_listen_fds() that gives me the tuple (fd, "zincati.service") or so?
Perhaps a pattern that can be implemented today for this is for the privileged helper to create an "inaccessible directory" e.g. /run/rpm-ostree/privapi (last component mode 0700) with a .socket unit there, and then in zincati.service uses WorkingDirectory=/run/rpm-ostree/privapi to traverse it and access /run/rpm-ostree/privapi/rpmostree.socket or so.
The main goal here is to make this communication channel truly private to the participating services - as opposed to e.g. exposing a DBus service or globally-accessible socket, since that brings in the problems of authorization and increases attack surface generally.
More information about the systemd-devel
mailing list