-#! /bin/bash
-###
-### Update the site's SSH certificates.
-
-set -e
-cd "${0%/*}/.."
-
-###--------------------------------------------------------------------------
-### General setup stuff.
-
-## Read in a configuration file.
-if [ -f etc/config ]; then . etc/config; fi
-: ${keytypes="rsa:3072 dsa:1024"}
-: ${domain="your.site.example"}
-: ${cacomment="ssh-ca@$domain"}
-: ${scope="*.$domain"}
-: ${validity="-1d:+7d"}
-
-## The key types are adorned with bit lengths. Work out the raw key type
-## names.
-cakeytypes=""
-for kt in $keytypes; do
- cakeytypes="$cakeytypes ${kt%:*}"
-done
-
-## Make the keys if necessary.
-mkdir -p keys
-for kt in $keytypes; do
- case $kt in
- *:*) bits=-b${kt#*:} kt=${kt%:*} ;;
- *) bits="" ;;
- esac
- if [ ! -f keys/ca-$kt ]; then
- ssh-keygen -fkeys/ca-$kt -t$kt $bits -C"$cacomment" -N ""
- fi
- read pub <keys/ca-$kt.pub
- echo "@cert-authority $scope $pub" >keys/ca-$kt.entry
-done
-
-## Functions for managing concurrency.
-kids=""
-mkdir -p log
-run () {
- tag=$1; shift
- "$@" >log/$tag 2>&1&
- kids="$kids $tag:$!"
-}
-
-reap () {
- outcome=0
- for kid in $kids; do
- tag=${kid%:*}
- set +e; wait ${kid#*:}; rc=$?; set -e
- case $rc in
- 0) ;;
- *)
- echo >&2 "$0: $tag failed (rc = $rc)"
- sed 's,^,| ,' log/$tag
- outcome=1
- ;;
- esac
- done
- return $outcome
-}
-
-## Read the hosts.
-dohost () {
- host=$1; shift
-
- set -x
- hostkeytypes=$(
- ssh $host "
- cd /etc/ssh
- for kt in $cakeytypes; do
- if [ -f ssh_host_\${kt}_key.pub ]; then echo \$kt; fi
- done"
- )
- names=""
- for n in "$host" "$@"; do
- names=${names:+$names,}$n
- case "$n" in ".") ;; *) names=${names:+$names,}$n.$domain ;; esac
- done
- any=nil
- for kt in $hostkeytypes; do
- scp $host:/etc/ssh/ssh_host_${kt}_key.pub keys/$host-$kt.pub
- ssh-keygen -skeys/ca-$kt \
- -h -I"$cacomment:$host.$domain" -n$names \
- -V$validity \
- keys/$host-$kt.pub
- scp keys/$host-$kt-cert.pub $host:/etc/ssh/ssh_host_${kt}_key-cert.pub
- any=t
- done
- case "$any" in nil) echo >&2 "no matching key types"; exit 1 ;; esac
-}
-
-dotry () {
- host=$1; shift
- ping -c5 -q $host >/dev/null 2>&1 || return 0
- dohost "$host" "$@"
-}
-
-must () { run "$1" dohost "$@"; }
-try () { run "$1" dotry "$@"; }
-
-. etc/hosts
-reap
-
-last=%%%
-for i in keys/*.pub; do
- case "$i" in *-cert.pub) continue ;; esac
- host=${i%-*}
- case "$host" in "$last") ;; *) echo; echo "$host" ;; esac
- last=$host
- ssh-keygen -lv -f "$i" | sed 's,^,| ,'
-done >distorted-host-keys.new
-mv distorted-host-keys.new distorted-host-keys