diff --git a/signer.sh b/signer.sh new file mode 100755 index 0000000..98eaf73 --- /dev/null +++ b/signer.sh @@ -0,0 +1,180 @@ +#!/bin/sh + +DIR_ETC=./etc/ + +HOST_CA_PRIV=${DIR_ETC}private/host/meutel_host_ca +USER_CA_PRIV=${DIR_ETC}private/user/meutel_user_ca +HOST_CONFIG_ROOT=${DIR_ETC}public/host/ +USER_CONFIG_ROOT=${DIR_ETC}public/user/ + +ARGS_COUNT=$# +# public key file +PUBKEY=$1 +# certificate type: user/host +TYPE=$2 +# config name +NAME=$3 +# certificate validity duration +VALIDITY=$4 +# principals for user cert +PRINCIPALS=$5 +if [ "$ARGS_COUNT" -gt 5 ] +then + shift 5 + # certificate options + OPTS=$@ + echo "options: $OPTS" +fi +CERT="${PUBKEY%.pub}-cert.pub" +TS=$( date '+%Y%m%d%H%M.%S' ) + +usage() +{ + echo "signer.sh ()" +} + +check_pubkey() +{ + if [ ! -f $PUBKEY ]; then + echo "missing public key: $PUBKEY" >&2 + usage + exit 1 + fi +} + +check_ca_key() +{ + CA_PRIV=$1 + if [ ! -f $CA_PRIV ]; then + echo "missing private CA key: $CA_PRIV" >&2 + exit 2 + fi +} + +check_config() +{ + CONFIG_DIR=$1 + mkdir -p $CONFIG_DIR + if [ "$?" -neq 0 ] ; then + echo "cannot create config: $CONFIG_DIR" >&2 + exit 3 + fi +} + +next_serial() +{ + CONFIG=$1 + if ls $CONFIG/*-cert.pub 2>/dev/null > /dev/null ; then + SERIAL=$(( $( ls $CONFIG/*-cert.pub | wc -l ) + 1 )) + else + SERIAL=1 + fi +} + +user_cert() +{ + check_ca_key $USER_CA_PRIV + USER_CONFIG=${USER_CONFIG_ROOT}${NAME} + check_config $USER_CONFIG + if [ -z "$PRINCIPALS" ]; then + echo "missing principals" >&2 + usage + exit 1 + fi + if [ -z "$VALIDITY" ]; then + echo "missing validity duration" >&2 + usage + exit 1 + fi + next_serial $USER_CONFIG + CERT_ID="User cert $NAME for $PRINCIPALS generated at $TS" + USER_PUB_KEY="$USER_CONFIG/key-${TS}.pub" + # save key + cp -f "$PUBKEY" "$USER_PUB_KEY" + + echo "Generate user certificate" + echo " key: $PUBKEY" + echo " serial: $SERIAL" + echo " ID: $CERT_ID" + echo " principals: $PRINCIPALS" + echo " validity: $VALIDITY" + + gen_user_cert_opts + if [ "$?" -eq 0 ] ; then + cp "${USER_PUB_KEY%.pub}-cert.pub" "$CERT" + else + exit 4 + fi +} + +gen_user_cert_opts() +{ + for opt in $OPTS + do + set -- "$@" "-O" + set -- "$@" "$opt" + done + + ssh-keygen -I "$CERT_ID" -s "$USER_CA_PRIV" -n "$PRINCIPALS" -V "$VALIDITY" -z "$SERIAL" $@ "${USER_PUB_KEY}" +} + +host_cert() +{ + check_ca_key $HOST_CA_PRIV + HOST_CONFIG=${HOST_CONFIG_ROOT}${NAME} + check_config $HOST_CONFIG + + if [ -z "$PRINCIPALS" ]; then + echo "missing hostname" >&2 + usage + exit 1 + fi + if [ -z "$VALIDITY" ]; then + echo "missing validity duration" >&2 + usage + exit 1 + fi + next_serial $HOST_CONFIG + CERT_ID="Host cert $NAME for $PRINCIPALS generated at $TS" + HOST_PUB_KEY="$HOST_CONFIG/key-${TS}.pub" + # save key + cp -f "$PUBKEY" "$HOST_PUB_KEY" + + echo "Generate host certificate" + echo " key: $PUBKEY" + echo " serial: $SERIAL" + echo " ID: $CERT_ID" + echo " hostnames: $PRINCIPALS" + echo " validity: $VALIDITY" + + ssh-keygen -h -I "$CERT_ID" -s "$USER_CA_PRIV" -n "$PRINCIPALS" -V "$VALIDITY" -z "$SERIAL" "${HOST_PUB_KEY}" + if [ "$?" -eq 0 ] ; then + cp "${HOST_PUB_KEY%.pub}-cert.pub" "$CERT" + else + exit 4 + fi +} + +if [ "$ARGS_COUNT" -lt 4 ]; then + usage + exit 1 +fi +check_pubkey +case $TYPE in + "user") + user_cert + ;; + "host") + host_cert + ;; + *) + echo "unknown certificate type" >&2 + usage + exit 1 + ;; +esac +echo "==== CERTIFICATE DATA ====" +ssh-keygen -L -f "$CERT" +echo "==========================" +echo ">>>> CERTIFICATE FILE: $CERT" +