[PATCH v2] dirmngr: Implement --supervised command (for systemd, etc).

Daniel Kahn Gillmor dkg at fifthhorseman.net
Wed Aug 10 17:16:04 CEST 2016


* dirmngr/dirmngr.c (main): Add new --supervised command, which is
  a mode designed for running under a process supervision system
  like systemd or runit.
* doc/dirmngr.texi: document --supervised and its interaction with
  --log-file.
* dirmngr/systemd-user/{README,dirmngr.{socket,service}}: New. System
  integration notes and configuration for socket-activated dirmngr on
  machines that run systemd.
* dirmngr/Makefile.am: Add systemd-user/ directory to EXTRA_DIST.

--

"dirmngr --supervised" is a way to invoke dirmngr such that a system
supervisor like systemd can provide socket-activated startup, log
management, and scheduled shutdown.

When running in this mode, dirmngr:

 * Does not open its own listening socket; rather, it expects to be
   given a listening socket on file descriptor 3.

 * Does not open or manage any logfile; instead, it logs to stdout
   and/or stderr.

 * Does not detach from the invoking process, staying in the
   foreground instead.

The dirmngr/systemd-user directory contains a brief README and some
configuration files that enable socket-activated and
cleanly-terminated dirmngr system integration on machines that run
systemd.

Signed-off-by: Daniel Kahn Gillmor <dkg at fifthhorseman.net>
---
 dirmngr/Makefile.am                  |  4 +++-
 dirmngr/dirmngr.c                    | 26 +++++++++++++++++++++++
 dirmngr/systemd-user/README          | 40 ++++++++++++++++++++++++++++++++++++
 dirmngr/systemd-user/dirmngr.service | 10 +++++++++
 dirmngr/systemd-user/dirmngr.socket  | 10 +++++++++
 doc/dirmngr.texi                     | 11 +++++++++-
 6 files changed, 99 insertions(+), 2 deletions(-)
 create mode 100644 dirmngr/systemd-user/README
 create mode 100644 dirmngr/systemd-user/dirmngr.service
 create mode 100644 dirmngr/systemd-user/dirmngr.socket

diff --git a/dirmngr/Makefile.am b/dirmngr/Makefile.am
index 64bc058..15ca7b6 100644
--- a/dirmngr/Makefile.am
+++ b/dirmngr/Makefile.am
@@ -19,7 +19,9 @@
 
 ## Process this file with automake to produce Makefile.in
 
-EXTRA_DIST = OAUTHORS ONEWS ChangeLog-2011 tls-ca.pem
+EXTRA_DIST = OAUTHORS ONEWS ChangeLog-2011 tls-ca.pem \
+             systemd-user/README systemd-user/dirmngr.socket \
+             systemd-user/dirmngr.service
 dist_pkgdata_DATA = sks-keyservers.netCA.pem
 
 bin_PROGRAMS = dirmngr dirmngr-client
diff --git a/dirmngr/dirmngr.c b/dirmngr/dirmngr.c
index 007fa10..b57cd1e 100644
--- a/dirmngr/dirmngr.c
+++ b/dirmngr/dirmngr.c
@@ -94,6 +94,7 @@ enum cmd_and_opt_values {
 
   aServer,
   aDaemon,
+  aSupervised,
   aService,
   aListCRLs,
   aLoadCRL,
@@ -155,6 +156,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_c (aServer,   "server",  N_("run in server mode (foreground)") ),
   ARGPARSE_c (aDaemon,   "daemon",  N_("run in daemon mode (background)") ),
+  ARGPARSE_c (aSupervised, "supervised", N_("run under supervision (e.g. systemd)")),
 #ifdef USE_W32_SERVICE
   ARGPARSE_c (aService,  "service", N_("run as windows service (background)")),
 #endif
@@ -911,6 +913,7 @@ main (int argc, char **argv)
         {
         case aServer:
         case aDaemon:
+        case aSupervised:
         case aService:
         case aShutdown:
         case aFlush:
@@ -1093,6 +1096,29 @@ main (int argc, char **argv)
       start_command_handler (ASSUAN_INVALID_FD);
       shutdown_reaper ();
     }
+  else if (cmd == aSupervised)
+    {
+    /* In supervised mode, we expect file descriptor 3 to be an
+       already opened, listening socket.
+
+       We will also not detach from the controlling process or close
+       stderr, and we do not open any logfile; the supervisor should
+       handle all of that.
+
+       FIXME: should we try to extract the actual socket_name
+       from the file descriptor with getsockname(2) so that we
+       can return it in response to "GETINFO socket_name"?  This
+       isn't currently done when --socket-name is supplied.
+     */
+#if USE_LDAP
+      ldap_wrapper_launch_thread ();
+#endif /*USE_LDAP*/
+      cert_cache_init ();
+      crl_cache_init ();
+      handle_connections (3);
+      assuan_sock_close (3);
+      shutdown_reaper ();
+    }
   else if (cmd == aDaemon)
     {
       assuan_fd_t fd;
diff --git a/dirmngr/systemd-user/README b/dirmngr/systemd-user/README
new file mode 100644
index 0000000..938740e
--- /dev/null
+++ b/dirmngr/systemd-user/README
@@ -0,0 +1,40 @@
+Socket-activated dirmngr with systemd
+=====================================
+
+When used on a GNU/Linux system supervised by systemd, you can ensure
+that dirmngr is launched automatically the first time it's needed, and
+shut down cleanly at session logout by enabling the dirmngr user
+service via socket-activation.
+
+System distributors
+-------------------
+
+The dirmngr.service and dirmngr.socket (from this directory) should be
+placed in /usr/lib/systemd/user/ alongside other user-session services
+and sockets.
+
+To enable socket-activated dirmngr for all accounts on the system,
+use:
+
+    systemctl --user --global enable dirmngr.socket
+
+
+Individual users
+----------------
+
+A user on a system with systemd where this has not been installed
+system-wide can place these files in ~/.config/systemd/user/ to make
+them available.
+
+If it isn't installed system-wide, or it's installed system-wide but
+not globally enabled hasn't been done, individual users will still
+need to enable it:
+
+Users who want to enable socket-activated dirmngr for all future
+sessions can do so with:
+
+    systemctl --user enable dirmngr.socket
+
+To set up socket-activated dirmngr for the current session, use:
+
+    systemctl --user start dirmngr.socket
diff --git a/dirmngr/systemd-user/dirmngr.service b/dirmngr/systemd-user/dirmngr.service
new file mode 100644
index 0000000..8c4c496
--- /dev/null
+++ b/dirmngr/systemd-user/dirmngr.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=GnuPG network certificate management daemon
+Documentation=man:dirmngr(8)
+
+[Service]
+ExecStart=/usr/bin/dirmngr --supervised
+
+[Install]
+Also=dirmngr.socket
+WantedBy=default.target
diff --git a/dirmngr/systemd-user/dirmngr.socket b/dirmngr/systemd-user/dirmngr.socket
new file mode 100644
index 0000000..6621cf6
--- /dev/null
+++ b/dirmngr/systemd-user/dirmngr.socket
@@ -0,0 +1,10 @@
+[Unit]
+Description=dirmngr listening socket
+Documentation=man:dirmngr(8)
+
+[Socket]
+ListenStream=/run/user/%U/gnupg/S.dirmngr
+SocketMode=0600
+
+[Install]
+WantedBy=sockets.target
diff --git a/doc/dirmngr.texi b/doc/dirmngr.texi
index 033b5d3..3b64b19 100644
--- a/doc/dirmngr.texi
+++ b/doc/dirmngr.texi
@@ -90,6 +90,13 @@ Run in background daemon mode and listen for commands on a socket.
 Note that this also changes the default home directory and enables the
 internal certificate validation code.  This mode is deprecated.
 
+ at item --supervised
+ at opindex supervised
+Run in the foreground, sending logs to stderr, and listening on file
+descriptor 3, which must already be bound to a listening socket.  This
+is useful when running under systemd or other similar process
+supervision schemes.
+
 @item --list-crls
 @opindex list-crls
 List the contents of the CRL cache on @code{stdout}. This is probably
@@ -168,7 +175,9 @@ verbose commands to @sc{dirmngr}, such as @option{-vv}.
 @item --log-file @var{file}
 @opindex log-file
 Append all logging output to @var{file}.  This is very helpful in
-seeing what the agent actually does.
+seeing what the agent actually does.  This has no effect in
+ at code{--supervised} mode, as the process supervisor is expected to
+handle all logging (e.g., @code{journalctl --user -u dirmngr}).
 
 @item --debug-level @var{level}
 @opindex debug-level
-- 
2.8.1




More information about the Gnupg-devel mailing list