Skip to content

Instantly share code, notes, and snippets.

@neggles
Forked from tashian/init_aws_ca.sh
Created June 18, 2020 02:51
Show Gist options
  • Save neggles/194a9b19329d7636097ccfece618e61d to your computer and use it in GitHub Desktop.
Save neggles/194a9b19329d7636097ccfece618e61d to your computer and use it in GitHub Desktop.
#!/bin/bash
#
# This script will launch and configure a step-ca SSH Certificate Authority
# with OIDC and AWS provisioners
#
# See https://smallstep.com/blog/diy-single-sign-on-for-ssh/ for full instructions
OIDC_CLIENT_ID="[OAuth client ID]" # from Google
OIDC_CLIENT_SECRET="[OAuth client secret]" # from Google
ALLOWED_DOMAIN="[the domain name of accounts your users will use to sign to Google]"
CA_NAME="[A name for your CA]"
ROOT_KEY_PASSWORD="[A password for your CA's root key]"
EMAIL="your@email.address"
OPENID_CONFIG_ENDPOINT="https://accounts.google.com/.well-known/openid-configuration"
curl -sLO https://github.com/smallstep/certificates/releases/download/v0.14.4/step-certificates_0.14.4_amd64.deb
dpkg -i step-certificates_0.14.4_amd64.deb
curl -sLO https://github.com/smallstep/cli/releases/download/v0.14.3/step-cli_0.14.3_amd64.deb
dpkg -i step-cli_0.14.3_amd64.deb
# All your CA config and certificates will go into $STEPPATH.
export STEPPATH=/etc/step-ca
mkdir -p $STEPPATH
chmod 700 $STEPPATH
echo $ROOT_KEY_PASSWORD > $STEPPATH/password.txt
# Add a service to systemd for our CA.
cat<<EOF > /etc/systemd/system/step-ca.service
[Unit]
Description=step-ca service
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=1
User=root
Environment=STEPPATH=/etc/step-ca
ExecStart=/usr/bin/step-ca ${STEPPATH}/config/ca.json --password-file=${STEPPATH}/password.txt
[Install]
WantedBy=multi-user.target
EOF
LOCAL_HOSTNAME=`curl -s http://169.254.169.254/latest/meta-data/local-hostname`
LOCAL_IP=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`
PUBLIC_HOSTNAME=`curl -s http://169.254.169.254/latest/meta-data/public-hostname`
PUBLIC_IP=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
AWS_ACCOUNT_ID=`curl -s http://169.254.169.254/latest/dynamic/instance-identity/document | grep accountId | awk '{print $3}' | sed 's/"//g' | sed 's/,//g'`
# Set up our basic CA configuration and generate root keys
step ca init --ssh --name="$CA_NAME" \
--dns="$LOCAL_IP,$LOCAL_HOSTNAME,$PUBLIC_IP,$PUBLIC_HOSTNAME" \
--address=":443" --provisioner="$EMAIL" \
--password-file="$STEPPATH/password.txt"
# Add the Google OAuth provisioner, for user certificates
step ca provisioner add Google --type=oidc --ssh \
--client-id="$OIDC_CLIENT_ID" \
--client-secret="$OIDC_CLIENT_SECRET" \
--configuration-endpoint="$OPENID_CONFIG_ENDPOINT" \
--domain="$ALLOWED_DOMAIN"
# Add the AWS provisioner, for host bootstrapping
step ca provisioner add "Amazon Web Services" --type=AWS --ssh \
--aws-account=$AWS_ACCOUNT_ID
# The sshpop provisioner lets hosts renew their ssh certificates
step ca provisioner add SSHPOP --type=sshpop --ssh
# Use Google (OIDC) as the default provisioner in the end user's
# ssh configuration template.
sed -i 's/\%p$/%p --provisioner="Google"/g' /etc/step-ca/templates/ssh/config.tpl
service step-ca start
echo "export STEPPATH=$STEPPATH" >> /root/.profile
#!/bin/bash
#
# This script will get an SSH host certificate from our CA and add a weekly
# cron job to rotate the host certificate.
#
# See https://smallstep.com/blog/diy-single-sign-on-for-ssh/ 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]"
STEPCLI_VERSION="0.14.3"
curl -LO https://github.com/smallstep/cli/releases/download/v${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/ssh_user_key.pub` on the CA).
step ssh config --roots > $(step path)/certs/ssh_user_key.pub
# Get an SSH host certificate
HOSTNAME="$(curl -s http://169.254.169.254/latest/meta-data/public-hostname)"
LOCAL_HOSTNAME="$(curl -s http://169.254.169.254/latest/meta-data/local-hostname)"
# 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 ".payload.amazon.document" | base64 -d
# Ask the CA to exchange our instance token for an SSH host certificate
step ssh certificate $HOSTNAME /etc/ssh/ssh_host_ecdsa_key.pub \
--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/ssh_user_key.pub
# This is our host private key and certificate:
HostKey /etc/ssh/ssh_host_ecdsa_key
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
EOF
service ssh restart
# Now add a weekly cron script to rotate our host certificate.
cat <<EOF > /etc/cron.weekly/rotate-ssh-certificate
#!/bin/sh
export STEPPATH=/root/.step
cd /etc/ssh && step ssh renew ssh_host_ecdsa_key-cert.pub ssh_host_ecdsa_key --force 2> /dev/null
exit 0
EOF
chmod 755 /etc/cron.weekly/rotate-ssh-certificate
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment