SSH CA - signer

This commit is contained in:
Meutel 2024-02-12 06:54:18 +01:00
parent 214c50bd06
commit e566ad0d17

180
signer.sh Executable file
View File

@ -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 <pubkey_file> <user|host> <name> <validity> <principals|hostname> (<options...>)"
}
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"