Systemd Activatable Responders¶
Problem statement¶
SSSD has some responders which don’t have to be running all the time, but could
be socket-activated
or dbus-activated
instead on platforms where it’s
supported. That’s the case, for instance, for the IFP
, SSH
and Sudo
responders.
Making these responders socket-activated or dbus-activated would provide a better user experience, as these services could be started on-demand when a client needs them and exit after a period of inactivity.
Currently, the Administrator has to explicitly list all the services that might
be potentially needed in the services
line of [sssd]
section and those
processes will be running all the time.
Use cases¶
- sssctl: As more and more features had been added depending on the
IFP
responder being activated, leaving this responder to be started on-demand instead of having the admins explicitly setting them up is desired;- KCM: The KCM responder is only seldom needed, when libkrb5 needs to access the credentials store. At the same time, the KCM responder must be running if Kerberos credentials cache defaults to KCM. Socket-activating this responder would solve both of the cases;
- AutoFS: The AutoFS responder is typically needed only when a shared directory is about to be mounted.
Overview of the solution¶
The solution agreed on the mailing list is to add a new unit file for each one of the responders. Once a responder is started, it will communicated to the monitor in order to let the monitor know that it’s up and then the monitor will take care of registering the responder, which basically consists in marking the service as started, increasing the services’ counter, getting the responders’ configuration and finally adding the responder to the services’ list. A configurable idle timeout will be implemented the responders, in order to shut the process down in case it becomes idle.
Implementation details¶
In order to achieve our goal we will need some small modifications in the responders’ common code to make those ready for socket-activation, add a systemd unit file for each of the responders, add a new binary file to ensure that the Administrator won’t mix up those two methods of starting services (for the very same service) and finally do some changes in the monitor code for managing the socket-activated service.
The change in the responders’ common code is quite trivial and goes towards
calling activate_unix_sockets()
function instead of set_unix_socket()
.
The important part around this change is to avoid the responders’ file
descriptors to be set as -1 in all cases as it would cause the socket to be
unreachable in case the Administrator decides to move back from using the
socket-activated services to the default way.
- The systemd units for the responders will look like:
NSS responder: NSS is a really special case as it cannot have be run as unprivileged user. It happens because libc does initgroups on pretty much any account and initgroups checks all NSS modules in order to be precise, causing
nss_sss
to trigger theNSS responder
… so a cycle dependency would happen.sssd-nss.service:
[Unit] Description=SSSD NSS Service responder Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service RefuseManualStart=true [Install] Also=sssd-nss.socket [Service] ExecStart=@libexecdir@/sssd/sssd_nss --debug-to-files --socket-activated Restart=on-failure
sssd-nss.socket:
[Unit] Description=SSSD NSS Service responder socket Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service Before=sssd-autofs.socket sssd-pac.socket sssd-pam.socket sssd-ssh.socket sssd-sudo.socket DefaultDependencies=no Conflicts=shutdown.target [Socket] ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r nss ListenStream=@pipepath@/nss [Install] WantedBy=sssd.service
PAM responder: PAM is a little bit special as it has two sockets associated to itself.
sssd-pam.service:
[Unit] Description=SSSD PAM Service responder Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service RefuseManualStart=true [Install] Also=sssd-pam.socket sssd-pam-priv.socket [Service] ExecStartPre=-/bin/chown @SSSD_USER@:@SSSD_USER@ @logpath@/sssd_pam.log ExecStart=@libexecdir@/sssd/sssd_pam --debug-to-files --socket-activated Restart=on-failure User=@SSSD_USER@ Group=@SSSD_USER@ PermissionsStartOnly=true
sssd-pam.socket:
[Unit] Description=SSSD PAM Service responder socket Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service BindsTo=sssd-pam-priv.socket DefaultDependencies=no Conflicts=shutdown.target [Socket] ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r pam ListenStream=@pipepath@/pam SocketUser=root SocketGroup=root [Install] WantedBy=sssd.service
sssd-pam-private.socket:
[Unit] Description=SSSD PAM Service responder private socket Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service BindsTo=sssd-pam.socket DefaultDependencies=no Conflicts=shutdown.target [Socket] ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r pam Service=sssd-pam.service ListenStream=@pipepath@/private/pam SocketUser=root SocketGroup=root SocketMode=0600 [Install] WantedBy=sssd.service
AutoFS, PAC, Ssh and Sudo responders:
sssd-@responder@.service:
[Unit] Description=SSSD @responder@ Service responder Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service RefuseManualStart=true [Install] Also=sssd-@responder@.socket [Service] ExecStartPre=-/bin/chown @SSSD_USER@:@SSSD_USER@ @logpath@/sssd_autofs.log ExecStart=@libexecdir@/sssd/sssd_@responder@ --debug-to-files --socket-activated Restart=on-failure User=@SSSD_USER@ Group=@SSSD_USER@ PermissionsStartOnly=true
sssd-@responder@.socket:
[Unit] Description=SSSD @responder@ Service responder socket Documentation=man:sssd.conf(5) After=sssd.service BindsTo=sssd.service DefaultDependencies=no Conflicts=shutdown.target [Socket] ExecStartPre=@libexecdir@/sssd/sssd_check_socket_activated_responders -r @responder@ ListenStream=@pipepath@/@responder@ SocketUser=@SSSD_USER@ SocketGroup=@SSSD_USER@ [Install] WantedBy=sssd.service
IFP responder: While the other responders are going to be socket-activated, IFP will be dbus-activated:
sssd-ifp.service:
[Unit] Description=SSSD IFP Service responder Documentation=man:sssd-ifp(5) After=sssd.service BindsTo=sssd.service [Service] Type=dbus BusName=org.freedesktop.sssd.infopipe ExecStart=@libexecdir@/sssd/sssd_ifp --uid 0 --gid 0 --debug-to-files --dbus-activated Restart=on-failure
The newly added binary does nothing but check in the config files whether the
responder that is about to be activated is also listed in the services
of
the configuration file. In case it’s there, the services’ socket is not
started, fallbacking to the default way.
And, finally, the code on the monitor side will have to have some adjustments in order to properly deal with an empty list of services and, also, to register the service when it is stated.
As just the responders will be socket-activated (for now), the service type
will have to be exposed and passed through sbus when calling the
RegistrationService
method and then the monitor will properly do the
services’ registration when the method’s callback is triggered. As mentioned
before, the registration that has to be done consists in:
- Marking the service as started;
- Increasing the services’ counter;
- Getting the services’ configuration;
- Setting the services’ restart number;
- Adding the service to the services’ list;
Unregistering a socket-activated responder will also be done by the monitor when the connection between the service and the monitor is closed.
Configuration changes¶
After this design is implemented, the services
line in sssd.conf
will
become optional for platforms where systemd is present. Note that in order to
keep backward compatibility, if the services
line is present, the services
will behave exactly as they did before these changes.
How To Test¶
The easiest way to test is removing the service from sssd.conf’s services
line, enabling the service’s socket and trying to use SSSD normally.
See below an example of how to enable NSS and PAM sockets:
# systemctl enable sssd-nss.socket sssd-pam.socket
# systemctl start sssd-nss.socket sssd-pam.socket
Using sssctl tool without having the IFP responder set in the services
line
is another way to test.
How To Debug¶
The easiest way to debug this new feature is taking a look on the responders’ common initialization code and in the monitors’ client registration code.
Is worth to mention that disabling the systemd’s sockets will prevent the responders’ services to be started.
Authors¶
Fabiano Fidencio <fidencio@redhat.com>