step-ssh: Automatically issue/renew SSH host certs
The `ssh-bootstrap` script, which is run by the *ssh-bootstrap.service* systemd unit, requests SSH host certificates for each of the existing SSH host keys. The certificates are issued by the *POST /sshkeys/sign* operation of *dch-webhooks* web service. The *step-ssh-renew* timer/service runs `step ssh renew`, in a container, on a weekly basis to renew the SSH host certificate. A host certificate must already exist, and its private key is used to authenticate to the CA server. Since `step ssh renew` can only operate on one certificate/key file at a time, the `step-ssh-renew@.container` defines a template unit. The template instance specifies the key type (i.e. `rsa`, `ecdsa`, or `ed25519`), which in turn defines which certificate and private key file to use. The timer unit activates a target unit, which depends on the concrete service units. Note that the target unit must have `StopWhenUnneeded=yes` so that it can be restarted again the next time the timer fires.master
parent
4048e5cc0a
commit
88f165363d
|
@ -0,0 +1,13 @@
|
||||||
|
# vim: set ft=systemd :
|
||||||
|
[Service]
|
||||||
|
Description=Bootstrap SSH host certificates
|
||||||
|
ConditionPathExistsGlob=!/etc/ssh/ssh_host_*_key-cert.pub
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/bin/sh /etc/ssh/bootstrap.sh
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# vim: set sw=4 ts=4 sts=4 et :
|
||||||
|
|
||||||
|
gen_sshd_config() {
|
||||||
|
{
|
||||||
|
for x in ssh_host_*_key-cert.pub; do
|
||||||
|
printf 'HostCertificate /etc/ssh/%s\n' "${x}"
|
||||||
|
done
|
||||||
|
} > sshd_config.d/10-hostcertificate.conf
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_response() {
|
||||||
|
jq -r '.certificates | to_entries | .[] | .key + " " + .value' \
|
||||||
|
| while read filename contents; do
|
||||||
|
[ -n "${filename}" ] || continue
|
||||||
|
echo "${contents}" > "${filename}" || return
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
request_sign() {
|
||||||
|
set -- \
|
||||||
|
https://bootstrap.pyrocufflink.blue/sshkeys/sign \
|
||||||
|
-H 'Accept: application/json' \
|
||||||
|
-F hostname=$(hostname -f)
|
||||||
|
for f in /etc/ssh/ssh_host_*_key.pub; do
|
||||||
|
set -- "$@" -F keys=@"${f}"
|
||||||
|
done
|
||||||
|
curl -fsSL "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /etc/ssh || exit
|
||||||
|
request_sign | parse_response
|
||||||
|
gen_sshd_config
|
||||||
|
|
||||||
|
systemctl reload sshd
|
|
@ -0,0 +1,3 @@
|
||||||
|
STEP_CA_URL=https://ca.pyrocufflink.blue:32599
|
||||||
|
STEP_ROOT=/etc/pki/ca-trust/source/anchors/dch-root-ca.crt
|
||||||
|
STEP_PROVISIONER=sshpop
|
|
@ -0,0 +1,6 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Renew SSH host certificates
|
||||||
|
StopWhenUnneeded=yes
|
||||||
|
Wants=step-ssh-renew@ed25519.service
|
||||||
|
Wants=step-ssh-renew@ecdsa.service
|
||||||
|
Wants=step-ssh-renew@rsa.service
|
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Periodically renew SSH host certificates
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
Unit=%N.target
|
||||||
|
OnCalendar=Tue *-*-* 00:00:00
|
||||||
|
RandomizedDelaySec=48h
|
||||||
|
Persistent=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
|
@ -0,0 +1,20 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Renew SSH host %I certificate
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
ConditionPathExists=/etc/ssh/ssh_host_%I_key-cert.pub
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
ContainerName=step-ssh-renew-%I
|
||||||
|
Image=docker.io/smallstep/step-cli:0.25.0
|
||||||
|
EnvironmentFile=/etc/sysconfig/step-ssh-renew
|
||||||
|
Exec=step ssh renew -f /etc/ssh/ssh_host_%I_key-cert.pub /etc/ssh/ssh_host_%I_key
|
||||||
|
Volume=/etc/ssh:/etc/ssh:rw
|
||||||
|
Volume=/etc/pki:/etc/pki:ro
|
||||||
|
# Required in order to be able to write to /etc/ssh
|
||||||
|
SecurityLabelDisable=true
|
||||||
|
User=0
|
||||||
|
Group=0
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
|
@ -0,0 +1,29 @@
|
||||||
|
variant: fcos
|
||||||
|
version: 1.4.0
|
||||||
|
|
||||||
|
storage:
|
||||||
|
files:
|
||||||
|
- path: /etc/ssh/bootstrap.sh
|
||||||
|
mode: 0755
|
||||||
|
contents:
|
||||||
|
local: ssh-bootstrap.sh
|
||||||
|
- path: /etc/containers/systemd/step-ssh-renew@.container
|
||||||
|
mode: 0644
|
||||||
|
contents:
|
||||||
|
local: step-ssh-renew@.container
|
||||||
|
- path: /etc/sysconfig/step-ssh-renew
|
||||||
|
mode: 0600
|
||||||
|
contents:
|
||||||
|
local: step-ssh-renew.env
|
||||||
|
- path: /etc/systemd/system/ssh-bootstrap.service
|
||||||
|
mode: 0644
|
||||||
|
contents:
|
||||||
|
local: ssh-bootstrap.service
|
||||||
|
- path: /etc/systemd/system/step-ssh-renew.target
|
||||||
|
mode: 0644
|
||||||
|
contents:
|
||||||
|
local: step-ssh-renew.target
|
||||||
|
- path: /etc/systemd/system/step-ssh-renew.timer
|
||||||
|
mode: 0644
|
||||||
|
contents:
|
||||||
|
local: step-ssh-renew.timer
|
Loading…
Reference in New Issue