Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
# This script will get an SSH host certificate from our CA and add a weekly
# cron job to rotate the host certificate. It should be run as root.
# See for full instructions
CA_URL="[Your CA's URL]"
# Obtain your CA fingerprint by running this on your CA:
# # step certificate fingerprint $(step path)/certs/root_ca.crt
CA_FINGERPRINT="[Your CA"s Fingerprint]"
curl -LO${STEPCLI_VERSION}/step-cli_${STEPCLI_VERSION}_amd64.deb
dpkg -i step-cli_${STEPCLI_VERSION}_amd64.deb
# Configure `step` to connect to & trust our `step-ca`.
# Pull down the CA's root certificate so we can talk to it later with TLS
step ca bootstrap --ca-url $CA_URL \
--fingerprint $CA_FINGERPRINT
# Install the CA cert for validating user certificates (from /etc/step-ca/certs/` on the CA).
step ssh config --roots > $(step path)/certs/
# Get an SSH host certificate
HOSTNAME="$(curl -s"
LOCAL_HOSTNAME="$(curl -s"
# This helps us avoid a potential race condition / clock skew issue
# "x509: certificate has expired or is not yet valid: current time 2020-04-01T17:52:51Z is before 2020-04-01T17:52:52Z"
sleep 1
# The TOKEN is a JWT with the instance identity document and signature embedded in it.
TOKEN=$(step ca token $HOSTNAME --ssh --host --provisioner "Amazon Web Services")
# To inspect $TOKEN, run
# $ echo $TOKEN | step crypto jwt inspect --insecure
# To inspect the Instance Identity Document embedded in the token, run
# $ echo $TOKEN | step crypto jwt inspect --insecure | jq -r "" | base64 -d
# Ask the CA to exchange our instance token for an SSH host certificate
step ssh certificate $HOSTNAME /etc/ssh/ \
--host --sign --provisioner "Amazon Web Services" \
--principal $HOSTNAME --principal $LOCAL_HOSTNAME \
--token $TOKEN
# Configure and restart `sshd`
tee -a /etc/ssh/sshd_config > /dev/null <<EOF
# SSH CA Configuration
# This is the CA's public key, for authenticatin user certificates:
TrustedUserCAKeys $(step path)/certs/
# This is our host private key and certificate:
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/
service ssh restart
# Now add a weekly cron script to rotate our host certificate.
cat <<EOF > /etc/cron.weekly/rotate-ssh-certificate
export STEPPATH=/root/.step
cd /etc/ssh && step ssh renew ssh_host_ecdsa_key --force 2> /dev/null
exit 0
chmod 755 /etc/cron.weekly/rotate-ssh-certificate
Copy link

mafrosis commented Jul 13, 2020

A couple of suggestions:

  • Create a new file in /etc/ssh/sshd_config.d instead of using tee -a (EDIT: see author comment below that this is intentional 😄)
  • Probably worth adding a line (either here or in section 3 of the blog post) that this script should be run as root

That aside awesome work! This has been instrumental for me learning how smallstep CA works :)

Copy link

tashian commented Jul 13, 2020

Thanks @mafrosis! :D

Copy link

tashian commented Jul 14, 2020

@mafrosis the inclusion of /etc/ssh/sshd_config.d/*.conf files is Debian-specific, so we edit sshd_config for broader compatibility.

Copy link

avoidik commented Jan 30, 2022

arm support?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment