From 7092874729417f7b8032520af21f97375d570d3a Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Thu, 21 Feb 2019 17:12:59 -0500 Subject: [PATCH] Enable sd_listen_fds(3)-style socket-activation support I've added straightforward systemd unit files in system/socket-activation/ that make use of this approach, and a README.md in the same location that describes the tradeoffs. --- dkimpy_milter/__init__.py | 11 ++++++- system/socket-activation/README.md | 32 +++++++++++++++++++ .../socket-activation/dkimpy-milter.service | 11 +++++++ system/socket-activation/dkimpy-milter.socket | 12 +++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 system/socket-activation/README.md create mode 100644 system/socket-activation/dkimpy-milter.service create mode 100644 system/socket-activation/dkimpy-milter.socket diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 3f9eef9..4c64891 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -355,7 +355,16 @@ def main(): miltername = 'dkimpy-filter' socketname = milterconfig.get('Socket') if socketname is None: - socketname = 'local:/var/run/dkimpy-milter/dkimpy-milter.sock' + if int(os.environ.get('LISTEN_PID', '0')) == os.getpid(): + lfds = os.environ.get('LISTEN_FDS') + if lfds is not None: + if lfds != '1': + syslog.syslog('LISTEN_FDS is set to "{0}", but we only know how to deal with "1", ignoring it'. + format(lfds)) + else: + socketname = 'fd:3' + if socketname is None: + socketname = 'local:/var/run/dkimpy-milter/dkimpy-milter.sock' own_socketfile(milterconfig, socketname) drop_privileges(milterconfig) sys.stdout.flush() diff --git a/system/socket-activation/README.md b/system/socket-activation/README.md new file mode 100644 index 0000000..b4410ac --- /dev/null +++ b/system/socket-activation/README.md @@ -0,0 +1,32 @@ +This directory contains example systemd unit files for running a +supervised, socket-activated instance of dkimpy-milter. + +There are several advantages of using socket activation: + +- dkimpy-milter never runs with elevated privileges, they are dropped + before any dkimpy-milter code is executed. + +- The socket is opened before dkimpy-milter runs. This means that + clients can connect() to the socket immediately. So even if there + is a delay in dkimpy-milter startup, or in libmilter itself, the + connection will not fail. + +- You can set the privileges of a listening Unix-domain socket by an + override of ListenGroup= in dkimpy-milter.socket (see + systemd.unit(5) for how to override). This lets you control who has + access to the daemon with finer granularity than is available with + dkimpy-milter on its own. + +- dkimpy-milter will not consume system resources if it is not used. + +- A fully-supervised dkimpy-milter needs no PIDFile, UMask, UserID, or + Socket configuation. This eliminates common race conditions and + startup failures, and simplifies the resulting configuration file. + +There is one downside to using socket activation: + +- it will only work on systems where libmilter can support connection + strings like "fd:3". This has been supported on Debian and derived + systems since sendmail 8.14.4-6 (before Debian Jessie, in early + 2014), see for example: + https://sources.debian.org/src/sendmail/8.15.2-8/debian/patches/socket_activation.patch/ diff --git a/system/socket-activation/dkimpy-milter.service b/system/socket-activation/dkimpy-milter.service new file mode 100644 index 0000000..2116bb7 --- /dev/null +++ b/system/socket-activation/dkimpy-milter.service @@ -0,0 +1,11 @@ +[Unit] +Description=DKIMpy Milter +Documentation=man:dkimpy-milter(8) man:dkimpy-milter.conf(5) +Requires=dkimpy-milter.socket + +[Service] +ExecStart=/usr/bin/dkimpy-milter /etc/dkimpy-milter.conf +User=dkimpy-milter + +[Install] +Also=dkimpy-milter.socket diff --git a/system/socket-activation/dkimpy-milter.socket b/system/socket-activation/dkimpy-milter.socket new file mode 100644 index 0000000..d4338a3 --- /dev/null +++ b/system/socket-activation/dkimpy-milter.socket @@ -0,0 +1,12 @@ +[Unit] +Description=DKIMpy Milter socket +Documentation=man:dkimpy-milter(8) man:dkimpy-milter.conf(5) + +[Socket] +ListenStream=/run/dkimpy-milter/dkimpy-milter.sock +SocketMode=0660 +# override SocketGroup to grant access to members of another system group: +SocketGroup=dkimpy-milter + +[Install] +WantedBy=sockets.target