Skip to content

Commit

Permalink
feat(systemd): Add certhub-cert-send service with configurable destin…
Browse files Browse the repository at this point in the history
…ations (#42)
  • Loading branch information
znerol committed Jul 4, 2019
1 parent c156168 commit dc6f819
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ install-doc: doc $(man1_installed) $(man8_installed)
ln -s -f certhub-cert-expiry@.service.8 $(DESTDIR)$(mandir)/man8/certhub-cert-expiry@.timer.8
ln -s -f certhub-cert-export@.service.8 $(DESTDIR)$(mandir)/man8/certhub-cert-export@.path.8
ln -s -f certhub-cert-reload@.service.8 $(DESTDIR)$(mandir)/man8/certhub-cert-reload@.path.8
ln -s -f certhub-cert-send@.service.8 $(DESTDIR)$(mandir)/man8/certhub-cert-send@.path.8
ln -s -f certhub-repo-push@.service.8 $(DESTDIR)$(mandir)/man8/certhub-repo-push@.path.8

install-bin: bin $(scripts_installed) $(entrypoints_installed) $(units_installed) $(dropins_installed)
Expand All @@ -133,6 +134,7 @@ uninstall:
-rm -f $(DESTDIR)$(mandir)/man8/certhub-cert-expiry@.timer.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-cert-export@.path.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-cert-reload@.path.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-cert-send@.path.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-certbot-run@.path.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-dehydrated-run@.path.8
-rm -f $(DESTDIR)$(mandir)/man8/certhub-lego-run@.path.8
Expand Down
85 changes: 85 additions & 0 deletions doc/certhub-cert-send@.service.8.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
certhub-cert-send@.service
==========================

Synopsis
--------

**certhub-cert-send@.service**

**certhub-cert-send@.path**


Description
-----------

A service which a sends certificate to predefined destinations. The specified
command line is executed once for each destination with the certificate piped
to stdin.

A path unit which runs the service unit whenever the exported certificate has
changed on the filesystem.

The instance name (systemd instance string specifier ``%i``) is used as the
basename of the configuration and the certificate file.


Environment
-----------

.. envvar:: CERTHUB_CERT_SEND_SRC

Path to the certificate file to be sent. Defaults to:
``/var/lib/certhub/certs/%i.fullchain.pem``

.. envvar:: CERTHUB_CERT_SEND_CONFIG

Path to a file containing destinations for the certificate send service.
``/etc/certhub/%i.destinations-send.txt``

.. envvar:: CERTHUB_CERT_SEND_COMMAND

Command to execute for each predefined destination. Use ``%i`` to reference
the instance name. The command is run once for each line in the
``%i.destinations-send.txt`` config file, the line can be referenced with
the ``{DESTINATION}}`` placeholder.

Defaults to: ``mail -s '[Certhub] Issue/renew %i' {DESTINATION}``


Examples
--------

Configuration file (placed in ``/etc/certhub/%i.destinations-send.txt``)
containing one destination to send the certificate to ``root@localhost``
whenever a new one has been exported.

::

root@localhost


Files
-----

.. envfile:: /etc/certhub/env

Optional environment file shared by all instances and certhub services.

.. envfile:: /etc/certhub/%i.env

Optional per-instance environment file shared by all certhub services.

.. envfile:: /etc/certhub/certhub-cert-send.env

Optional per-service environment file shared by all certhub service
instances.

.. envfile:: /etc/certhub/%i.certhub-cert-send.env

Optional per-instance and per-service environment file.


See Also
--------

:manpage:`certhub-cert-export@.service(8)`
1 change: 1 addition & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
('certhub-cert-expiry@.service.8', 'certhub-cert-expiry@.service', 'Certhub Documentation', [author], 8),
('certhub-cert-export@.service.8', 'certhub-cert-export@.service', 'Certhub Documentation', [author], 8),
('certhub-cert-reload@.service.8', 'certhub-cert-reload@.service', 'Certhub Documentation', [author], 8),
('certhub-cert-send@.service.8', 'certhub-cert-send@.service', 'Certhub Documentation', [author], 8),
('certhub-repo-push@.service.8', 'certhub-repo-push@.service', 'Certhub Documentation', [author], 8),
('certhub-docker-entry.8', 'certhub-docker-entry', 'Certhub Documentation', [author], 8),
('certhub-hook-lexicon-auth.8', 'certhub-hook-lexicon-auth', 'Certhub Documentation', [author], 8),
Expand Down
1 change: 1 addition & 0 deletions doc/man.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Man Pages
certhub-cert-expiry@.service.8
certhub-cert-export@.service.8
certhub-cert-reload@.service.8
certhub-cert-send@.service.8
certhub-repo-push@.service.8
certhub-docker-entry.8
certhub-hook-lexicon-auth.8
Expand Down
10 changes: 10 additions & 0 deletions integration-test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ all: \
test-cert-expiry \
test-cert-export \
test-cert-reload \
test-cert-send\
test-repo-push \
test-certbot \
test-lego \
Expand Down Expand Up @@ -66,6 +67,14 @@ test-cert-reload: node
# Stop containers
docker stop $($@_CONTAINER)

test-cert-send: node
# Start containers
$(eval $@_CONTAINER := $(shell docker run $(dockerargs) -d certhub-integration-node /sbin/init))
# Run the test
docker exec -i $($@_CONTAINER) /bin/sh < test/cert-send-test.sh
# Stop containers
docker stop $($@_CONTAINER)

test-repo-push: controller node
# Start containers
$(eval $@_NODE := $(shell docker run $(dockerargs) -d certhub-integration-node /sbin/init))
Expand Down Expand Up @@ -160,6 +169,7 @@ controller: base controller/context
test-cert-expiry \
test-cert-export \
test-cert-reload \
test-cert-send\
test-repo-push \
test-certbot \
test-dehydrated \
Expand Down
70 changes: 70 additions & 0 deletions integration-test/test/cert-send-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/sh

set -e
set -u
set -x

MAILBIN=/usr/local/bin/mail
test ! -e "${MAILBIN}"

WORKDIR=$(mktemp -d)
MAILOUT="${WORKDIR}/mail.out"
cleanup() {
# Show logs from systemd unit
journalctl -u certhub-cert-send@send-test-with-multi.service
# Remove working directory
rm -rf "${WORKDIR}"
rm -f "${MAILBIN}"
}
trap cleanup EXIT

chgrp certhub "${WORKDIR}"
chmod 770 "${WORKDIR}"

systemctl daemon-reload

# Generate fake self-signed certificates.
openssl req -x509 -nodes -batch -newkey rsa:1024 -keyout /dev/null -out "/var/lib/certhub/certs/send-test-with-multi.fullchain.pem"

# Generate a fake mail-command.
cat <<EOF > "${MAILBIN}"
#!/bin/sh
echo "Fake mail-command called with args: \${@}" >&2
set -e
set -u
{
printf "%q " "\${@}"
echo
cat
} >> "${MAILOUT}"
EOF
chmod +x "${MAILBIN}"

# Generate expected output from fake-mail.
MAILEXPECT="${WORKDIR}/mail.expect"
{
printf "%q " "-s" "[Certhub] Issue/renew send-test-with-multi" "root@localhost"
echo
cat "/var/lib/certhub/certs/send-test-with-multi.fullchain.pem"
printf "%q " "-s" "[Certhub] Issue/renew send-test-with-multi" "admin@example.com"
echo
cat "/var/lib/certhub/certs/send-test-with-multi.fullchain.pem"
} > "${MAILEXPECT}"

# Configuration file.
cat <<EOF > /etc/certhub/send-test-with-multi.destinations-send.txt
root@localhost
admin@example.com
EOF

# Expect send output for send-test-with-multi absent
test ! -e "${MAILOUT}"

# Run certhub-cert-send
systemctl start certhub-cert-send@send-test-with-multi.service

# Expect send output for send-test-with-multi present
diff -s "${MAILOUT}" "${MAILEXPECT}"
5 changes: 5 additions & 0 deletions lib/systemd/certhub-cert-send@.path
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Unit]
Description=Send certificates to predefined destinations when certificate changed

[Install]
WantedBy=paths.target
1 change: 1 addition & 0 deletions lib/systemd/certhub-cert-send@.path.d/export.path.conf
13 changes: 13 additions & 0 deletions lib/systemd/certhub-cert-send@.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Unit]
Description=Send certificates to predefined destinations

[Service]
Type=oneshot

ExecStart=/usr/bin/env \
xargs -a ${CERTHUB_CERT_SEND_CONFIG} -I{DESTINATION} \
certhub-send-file ${CERTHUB_CERT_SEND_SRC} $CERTHUB_CERT_SEND_COMMAND

SyslogIdentifier=certhub-cert-send
StandardOutput=syslog
StandardError=syslog
1 change: 1 addition & 0 deletions lib/systemd/certhub-cert-send@.service.d/certhub-user.conf
1 change: 1 addition & 0 deletions lib/systemd/certhub-cert-send@.service.d/send.conf
10 changes: 10 additions & 0 deletions lib/systemd/dropins/certhub-paths.conf
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,13 @@ Environment=CERTHUB_CERT_EXPORT_DEST=/var/lib/certhub/certs/%i.fullchain.pem
# Path to a file containing the services to reload.
#
Environment=CERTHUB_CERT_RELOAD_CONFIG=/etc/certhub/%i.services-reload.txt

# CERTHUB_CERT_SEND_SRC
# Path to the certificate file to be sent.
#
Environment=CERTHUB_CERT_SEND_SRC=/var/lib/certhub/certs/%i.fullchain.pem

# CERTHUB_CERT_SEND_CONFIG
# Path to a file containing destinations for the certificate send service.
#
Environment=CERTHUB_CERT_SEND_CONFIG=/etc/certhub/%i.destinations-send.txt
1 change: 1 addition & 0 deletions lib/systemd/dropins/export.path.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

# Export path watched by:
# - certhub-cert-reload@.path
# - certhub-cert-send@.path
PathChanged=/var/lib/certhub/certs/%i.fullchain.pem
8 changes: 8 additions & 0 deletions lib/systemd/dropins/send.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[Service]

# CERTHUB_CERT_SEND_COMMAND
# Command to execute for each predefined destination. Use ``%i`` to reference
# the instance name. The command is run once for each line in the
# ``%i.destinations-send.txt`` config file, the line can be referenced with the
# ``{DESTINATION}}`` placeholder.
Environment="CERTHUB_CERT_SEND_COMMAND=mail -s '[Certhub] Issue/renew %i' {DESTINATION}"

0 comments on commit dc6f819

Please sign in to comment.