#!/bin/sh # Filename: gencert.sh # Description: This script generates x509 server certificate (with all IPs in # SAN) signed by a self-signed CA. # Version: 0.1 - 30 June 2018 # Author: Andrey Arapov # License: GPLv3 ME=$(printf '%s\n' "${0##*/}") print_help() { printf "[${ME}] HELP: I accept following arguments: --help - show this message --cn - certificate's CN name\t\t(MANDATORY) --key - server key name\t\t\t(default: private.key) --cert - server cert name\t\t\t(default: public.crt) --days - server cert expiration in days\t(default: 365) --cakey - CA key name\t\t\t(default: ca.key) --ca - CA cert name\t\t\t(default: ca.crt) --cadays - CA cert expiration in days\t(default: 3650)\n" } # A POSIX variable OPTIND=1 # Reset in case getopts has been used previously in the shell. # read arguments opts=$(getopt \ --longoptions "help,cn:,key:,cert:,days:,cakey:,ca:,cadays:," \ --name "$(basename "$0")" \ --options "" \ -- "$@" ) eval set --$opts while [ $# -gt 0 ]; do case "$1" in --help) print_help; exit 0 ;; --cn) ARG_CN=$2 shift 2 ;; --key) ARG_KEY=$2 shift 2 ;; --cert) ARG_CERT=$2 shift 2 ;; --days) ARG_DAYS=$2 shift 2 ;; --cakey) ARG_CAKEY=$2 shift 2 ;; --ca) ARG_CA=$2 shift 2 ;; --cadays) ARG_CADAYS=$2 shift 2 ;; *) break ;; esac done if [ -z "${ARG_CN}" ]; then echo "[${ME}] ERROR: Please specify CN, example \"--cn your.site.com\"" print_help; exit 1 fi # For debugging purposes # echo ARG_CN=$ARG_CN # echo ARG_KEY=$ARG_KEY # echo ARG_CERT=$ARG_CERT # echo ARG_DAYS=$ARG_DAYS # echo ARG_CAKEY=$ARG_CAKEY # echo ARG_CA=$ARG_CA # echo ARG_CADAYS=$ARG_CADAYS OPENSSL_CONFIG="openssl.cnf" CA_KEY="${ARG_CAKEY:-ca.key}" CA_CERT="${ARG_CA:-ca.crt}" CA_DAYS="${ARG_CADAYS:-3650}" SERVER_KEY="${ARG_KEY:-private.key}" SERVER_CERT="${ARG_CERT:-public.crt}" DAYS="${ARG_DAYS:-365}" # set -x set -e gen_openssl_config() { OPENSSL_CONFIG_CONTENT="[ req ] distinguished_name = req_distinguished_name [req_distinguished_name] [ v3_ca ] basicConstraints = critical, CA:TRUE keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign [ v3_req_server ] basicConstraints = CA:FALSE keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ alt_names ]" # Gather IPs for SAN i=1 IPS="$(getent ahostsv4 $(hostname) | awk '{print $1}' |sort | uniq)" echo "[${ME}] Found these IPs: " ${IPS} PAYLOAD="$(for IP in $IPS; do echo "IP.${i} = ${IP}" ; i=$((i + 1)); done)" printf "${OPENSSL_CONFIG_CONTENT}\n${PAYLOAD}\n" > "${OPENSSL_CONFIG}" } gen_ca() { echo "[${ME}] Generating new CA: ${CA_KEY} / ${CA_CERT} ..." openssl ecparam -name prime256v1 -genkey -noout -out "${CA_KEY}" chmod 0600 "${CA_KEY}" openssl req -x509 -new -sha256 -nodes -key "${CA_KEY}" -days "${CA_DAYS}" -out "${CA_CERT}" \ -subj "/CN=my-CA" -extensions v3_ca -config "${OPENSSL_CONFIG}" } gen_server_x509() { echo "[${ME}] Generating new server x509: ${SERVER_KEY} / ${SERVER_CERT} ..." openssl ecparam -name prime256v1 -genkey -noout -out "${SERVER_KEY}" chmod 0600 "${SERVER_KEY}" openssl req -new -sha256 -key "${SERVER_KEY}" -subj "/CN=${ARG_CN}" \ | openssl x509 -req -sha256 -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial \ -out ${SERVER_CERT} -days "${DAYS}" \ -extensions v3_req_server -extfile "${OPENSSL_CONFIG}" } install_openssl() { set +e type openssl >/dev/null 2>&1 if [ $? -eq 0 ]; then return; fi if [ -f /etc/debian_version ]; then echo "[${ME}] Installing openssl in Debian/Ubuntu" export DEBIAN_FRONTEND=noninteractive apt-get update apt-get -y install openssl elif [ -f /etc/alpine-release ]; then echo "[${ME}] Installing openssl in Alpine" apk add --update openssl elif [ -f /etc/centos-release ]; then echo "[${ME}] Installing openssl in CentOS" yum -y install openssl fi type openssl >/dev/null if [ $? -ne 0 ]; then echo "[${ME}] ERROR: Could not install openssl. Exitting." exit 1 fi set -e } start() { echo "[${ME}] Started in ${PWD} directory." install_openssl; gen_openssl_config; if [ ! -f "${CA_KEY}" ]; then echo "[${ME}] Could not find ${CA_KEY} file so I will generate a new one." gen_ca; fi openssl x509 -in "${CA_CERT}" -noout -checkend 2592000 >/dev/null if [ $? -ne 0 ]; then echo "[${ME}] WARNING! Your CA certificate will expire in less than 30 days." fi openssl x509 -in "${CA_CERT}" -noout -checkend 1 >/dev/null if [ $? -ne 0 ]; then echo "[${ME}] WARNING! Your CA certificate has expired, so we will generate a new one." gen_ca; fi # Generate a new server certificate with the detected IPs. gen_server_x509; echo "[${ME}] The certificates have been generated in ${PWD} directory." CERT_INFO="$(openssl x509 -in "${SERVER_CERT}" -noout -text)" echo "${CERT_INFO}" | grep -E "CN=|IP Address|Not\ " } start;