diff --git a/ssh-bootstrap.service b/ssh-bootstrap.service new file mode 100644 index 0000000..9833057 --- /dev/null +++ b/ssh-bootstrap.service @@ -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 diff --git a/ssh-bootstrap.sh b/ssh-bootstrap.sh new file mode 100644 index 0000000..1a8d891 --- /dev/null +++ b/ssh-bootstrap.sh @@ -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 diff --git a/step-ssh-renew.env b/step-ssh-renew.env new file mode 100644 index 0000000..fe30f16 --- /dev/null +++ b/step-ssh-renew.env @@ -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 diff --git a/step-ssh-renew.target b/step-ssh-renew.target new file mode 100644 index 0000000..7e7b2a1 --- /dev/null +++ b/step-ssh-renew.target @@ -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 diff --git a/step-ssh-renew.timer b/step-ssh-renew.timer new file mode 100644 index 0000000..f7344a6 --- /dev/null +++ b/step-ssh-renew.timer @@ -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 diff --git a/step-ssh-renew@.container b/step-ssh-renew@.container new file mode 100644 index 0000000..117576b --- /dev/null +++ b/step-ssh-renew@.container @@ -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 diff --git a/step-ssh.yaml b/step-ssh.yaml new file mode 100644 index 0000000..6856ba2 --- /dev/null +++ b/step-ssh.yaml @@ -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