diff options
Diffstat (limited to 'client_maker_erg.sh')
-rwxr-xr-x | client_maker_erg.sh | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/client_maker_erg.sh b/client_maker_erg.sh new file mode 100755 index 0000000..ed153f1 --- /dev/null +++ b/client_maker_erg.sh @@ -0,0 +1,316 @@ +#!/usr/bin/env bash +############################################################################## +# HEADER # +############################################################################## +# Script for generating SSL certificates. +############################################################################## +# END_OF_HEADER # +############################################################################## + +usage() { + echo "Script name: $0"; + echo ""; + echo "Usage: $0 --key-type [ RSA | EC | EX25519 ]"; + echo " --curve [ P-256 | P-384 | P512 ]"; + echo " --rsa-bits [ 2048 | 4096 ]"; + echo " --days <n>"; + echo ""; + echo "Options: "; + echo " --key-type [ RSA | EC | EC25519 ]"; + echo " Note: Pico W can use EC or RSA keys only, not EC25519,"; + echo " and Tasmota can only use 2048 bit RSA keys."; + echo " --curve [ P-256 | P-384 | P512 ]"; + echo " --rsa-bits [ 2048 | 4096 ]"; + echo " --days [ <integer> ]"; + echo " --dir [ <mosquitto directory> ]"; + echo " --output-format [ PEM | DER ]"; + echo " --user <string>"; + echo " --config <path-to-cnf-file>"; + echo " --ca_key <path-to-CA_key>"; + echo " --ca_cert <path-to-CA_cert>"; + } + +TEMP="$(getopt -o hkcrd --long help,key-type:,curve:,rsa-bits:,days:,dir:,output-format:,user:,config:,ca_key:,ca_cert: -- "$@")" + +eval set -- "$TEMP" + +if [ $# == 0 ] ; then + usage; + exit 1; +fi + +KEY_TYPE="EC" +CURVE="P-256" +RSA_BITS=2048 +DAYS=365 +MOSQUITTO_DIR="/home/erg/cert_test" +OUTPUT_FORMAT= +MOSQUITTO_USER= +PKEYOPT= +SSL_CNF= +SSL_CA_KEY= +SSL_CA_CRT= + +while true +do + case "$1" in + -h|--help) + usage + exit 0; + ;; + --key-type) KEY_TYPE="$2"; echo "Key type: $KEY_TYPE"; shift 2;; + # Note: Pico W can use EC or RSA keys only, not EC25519, and Tasmota can only use 2048 bit RSA keys. + # Default choice of Key Types: RSA, EC, or ED25519 + --curve) CURVE="$2"; echo "Curve: $CURVE"; shift 2;; + # Choice of NIST Curves for EC Keys: P-256, P-384 or P-521 + --rsa-bits) RSA_BITS="$2"; echo "RSA bits: $RSA_BITS"; shift 2;; + # Choice of Bits for RSA Keys: 2048 or 4096 + --days) DAYS="$2"; echo "Valid for: $DAYS"; shift 2;; + # How many days is the Cert valid for? + --dir) MOSQUITTO_DIR="$2"; echo "Working directory: $MOSQUITTO_DIR"; shift 2;; + --output-format) OUTPUT_FORMAT="$2"; echo "Output format: $OUTPUT_FORMAT"; shift 2;; + --user) MOSQUITTO_USER="$2"; echo "Mosquitto user: $MOSQUITTO_USER"; shift 2;; + --config) SSL_CNF="$2"; shift 2;; + --ca_key) SSL_CA_KEY="$2"; shift 2;; + --ca_cert) SSL_CA_CRT="$2"; shift 2;; + -- ) shift; break;; + * ) break;; + esac +done + +############################################################################## +# Checks that sane arguments passed: # +############################################################################## + +# Check key type: +if [ "$KEY_TYPE" != 'EC' ] && [ "$KEY_TYPE" != 'RSA' ] && [ "$KEY_TYPE" != 'EC25519' ]; then + echo "Wrong key type specified: '$KEY_TYPE'" + echo "Valid keys: [ EC | RSA | EC25519 ]" + usage + exit 1; +fi + +# Set the specific PKEYOPT for the chosen algorithm (BLANK for ED25519) +if [ "${KEY_TYPE}" == "EC" ]; then + echo 'Create EC Key' + PKEYOPT="-pkeyopt ec_paramgen_curve:${CURVE}" +elif [ "${KEY_TYPE}" == "RSA" ]; then + echo 'Create RSA Key' + PKEYOPT="-pkeyopt rsa_keygen_bits:${RSA_BITS}" +elif [ "${KEY_TYPE}" == "ED25519" ]; then + echo 'Create ED25519 Key' + PKEYOPT="" +else + echo "Setting -PKEYOPT to defaults: -pkeyopt ec_paramgen_curve:${CURVE}" +fi + +# Check curve: +if [ "$CURVE" != 'P-256' ] && [ "$CURVE" != 'P-384' ] && [ "$CURVE" != 'P-521' ]; then + echo "Wrong NIST curve specified: '$CURVE'" + echo "Curve must be one of: [ P-256 | P-384 | P-521 ]" + usage + exit 1; +fi + +# Check RSA bits: +if [ "$RSA_BITS" != '2048' ] && [ "$RSA_BITS" != '4096' ]; then + echo "Wrong RSA bits specified: '$RSA_BITS'" + echo "Must be one of: [ 2048 | 4096 ]" + usage + exit 1; +fi + +# Check days parameter is a number: +if [ -n "$DAYS" ] && [ "$DAYS" -eq "$DAYS" ] 2>/dev/null; then + echo "Certificate will be valid for: '$DAYS' days" +else + echo "Not a number: $DAYS" + usage + exit 1; +fi + +# Check output format: +if [ "${OUTPUT_FORMAT}" == 'PEM' ] || [ "${OUTPUT_FORMAT}" == 'pem' ]; then # I: Double quote to prevent globbing and word splitting. + OUTPUT_FORMAT="pem" +elif [ "$OUTPUT_FORMAT" == 'DER' ] || [ "$OUTPUT_FORMAT" == 'der' ]; then # I: Double quote to prevent globbing and word splitting. + OUTPUT_FORMAT="der" +else echo "Incorrect certificate format type specified: $OUTPUT_FORMAT"; + usage + exit 1; +fi + +# Check user supplied: +if [ -z "$MOSQUITTO_USER" ] && [ "$MOSQUITTO_USER" != " " ]; then + echo "Specified: '$MOSQUITTO_USER' as user." + echo "Need to specify a non-empty username for the certificate!"; + usage + exit 1; +fi + +# Check CA key and cert exist: +if [ ! -f ${SSL_CA_CRT} ] || [ ! -f ${SSL_CA_KEY} ]; then + echo "CA certificate does not exist, exiting!" + exit 1 +fi +# Check CA certificate is still valid: +# Date format we get from openssl: +# Nov 18 13:47:56 2034 GMT +# %b %d %H:%M:%S %Y %Z +# compare dates from the CA cert and current one: +CERT_VALID_UNTIL=$(openssl x509 -enddate -noout -in "${SSL_CA_CRT}" | cut -d'=' -f2) +echo "CA certificate valid until: ${CERT_VALID_UNTIL}" +if [ ! $(($(date -d "$CERT_VALID_UNTIL" +"%s") > $(date +"%s"))) ];then + echo "CA certificate expired, exiting!" + exit 1 +fi + + +############################################################################## +# Set up variables # +############################################################################## + +# Set the algorithm +ALGORITHM="-algorithm ${KEY_TYPE}" + +# Output client key, CSR request and certificate +CLIENT_KEY="${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}/${MOSQUITTO_USER}_key.${OUTPUT_FORMAT}" +CLIENT_CSR="${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}/${MOSQUITTO_USER}_req.csr" +CLIENT_CERT="${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}/${MOSQUITTO_USER}_crt.${OUTPUT_FORMAT}" + +############################################################################## +# Locks # +############################################################################## + +LOCK_FILE=/tmp/$SUBJECT.lock +if [ -f "$LOCK_FILE" ]; then + echo "Script is already running" + exit +fi + +trap 'rm -f $LOCK_FILE' EXIT +touch "$LOCK_FILE" + +############################################################################## +# Backup existing certs and create dir structure # +############################################################################## + +# If our user certs dir already exists, rename it so we don't +# overwrite anything important. + +time_stamp=$(date +"%Y-%m-%d_%H-%M") +mv "${MOSQUITTO_DIR}/certs/csr_files/${MOSQUITTO_USER}_req.csr" "${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}" 2>/dev/null +mv "${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}req" "${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}-${time_stamp}" 2>/dev/null + +mkdir -p "${MOSQUITTO_DIR}/certs/clients/${MOSQUITTO_USER}" + +############################################################################## +# Create the key in the requested format # +############################################################################## + +echo "Running:" +echo " +openssl genpkey ${ALGORITHM} ${PKEYOPT} \ +-outform ${OUTPUT_FORMAT} \ +-out ${CLIENT_KEY} \ +-config ${SSL_CNF} +" + +openssl genpkey ${ALGORITHM} ${PKEYOPT} \ + -outform "${OUTPUT_FORMAT}" \ + -out "${CLIENT_KEY}" \ + -config "${SSL_CNF}" + +retval=$? +if [ $retval -ne 0 ]; then + echo "Generating key failed!" + exit $retval +fi +printf '\n\n' +echo "#######################################################################" +printf '\n\n' +echo "Successfully generated client key." +############################################################################## +# Create the cert signing request # +############################################################################## + + +echo "Running:" +echo " +openssl req \ +-new \ +-nodes \ +-key $CLIENT_KEY \ +-subj /CN=${MOSQUITTO_USER} \ +-out $CLIENT_CSR \ +-config ${SSL_CNF} +" +openssl req \ + -new \ + -nodes \ + -key "${CLIENT_KEY}" \ + -subj "/CN=${MOSQUITTO_USER}" \ + -out "${CLIENT_CSR}" \ + -config "${SSL_CNF}" + +retval=$? +if [ $retval -ne 0 ]; then + echo "Generating CSR request failed!" + exit $retval +fi +echo "Successfully generated CSR request" + +printf '\n\n' +echo "#######################################################################" +printf '\n\n' + +############################################################################## +# Cert signing and creation # +############################################################################## + +echo "Running:" +echo "openssl x509 \ +-req \ +-in ${CLIENT_CSR} \ +-CA ${SSL_CA_CRT} \ +-CAkey ${SSL_CA_KEY} \ +-CAcreateserial \ +-out ${CLIENT_CERT} \ +-outform ${OUTPUT_FORMAT} \ +-days ${DAYS} \ +-config ${SSL_CNF} +" +openssl x509 \ + -req \ + -in "${CLIENT_CSR}" \ + -CA "${SSL_CA_CRT}" \ + -CAkey "${SSL_CA_KEY}" \ + -CAcreateserial \ + -out "${CLIENT_CERT}" \ + -outform "${OUTPUT_FORMAT}" \ + -days "${DAYS}" \ + +retval=$? +if [ $retval -ne 0 ]; then + echo "Signing CSR and certificate creation failed!" + exit $retval +fi +echo "Successfully signed CSR and created client certificate." + +printf '\n\n' +echo "#######################################################################" +printf '\n\n' + +############################################################################## +# Check the cert # +############################################################################## + +printf '# This is your new client certificate\n\n\n' + +openssl x509 \ + -text \ + -in "${CLIENT_CERT}" \ + -noout + +printf '\n\n' +echo "#######################################################################" +printf '\n\n' |