You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
5.7 KiB

6 years ago
#!/bin/sh
# Filename: gencert.sh
6 years ago
# Description: This script generates x509 server certificate (with all IPs in
# SAN) signed by a self-signed CA.
6 years ago
# Version: 0.2 - 2018 July 03
6 years ago
# Author: Andrey Arapov <andrey.arapov@nixaid.com>
# License: GPLv3
ME=$(printf '%s\n' "${0##*/}")
6 years ago
print_help() {
printf "[${ME}] HELP: I accept following arguments:
6 years ago
--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
--nosan - do not write SAN records\n"
6 years ago
}
# Parse command line arguments
##
6 years ago
# 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:,nosan," \
6 years ago
--name "$(basename "$0")" \
--options "" \
-- "$@"
)
eval set --$opts
6 years ago
while [ $# -gt 0 ]; do
6 years ago
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
;;
--nosan)
ARG_NOSAN=1
shift 2
;;
6 years ago
*)
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
# echo ARG_NOSAN=$ARG_NOSAN
6 years ago
# prepare common variables
##
6 years ago
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
# install openssl
##
install_openssl() {
set +e
type openssl >/dev/null 2>&1
if [ $? -eq 0 ]; then
return;
fi
if [ $(id -u) -ne 0 ]; then
echo "This script must be run as root in order to install openssl package."
echo "If you cannot run this script as root, then make sure you have the openssl package."
exit 1
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
}
# generate openssl config
##
6 years ago
gen_openssl_config() {
6 years ago
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
6 years ago
extendedKeyUsage = serverAuth"
6 years ago
6 years ago
if [ -z $ARG_NOSAN ]; then
# Gather IPs for SAN
i=1
IPS="$(getent ahostsv4 $(hostname) | awk '{print $1}' |sort | uniq)"
echo "[${ME}] Found these IPs: " ${IPS}
6 years ago
PAYLOAD="subjectAltName = @alt_names\n[ alt_names ]\n$(for IP in $IPS; do echo "IP.${i} = ${IP}" ; i=$((i + 1)); done)"
fi
6 years ago
6 years ago
printf "${OPENSSL_CONFIG_CONTENT}\n${PAYLOAD}\n" > "${OPENSSL_CONFIG}"
6 years ago
}
# generate CA certificate
##
6 years ago
gen_ca() {
6 years ago
echo "[${ME}] Generating new CA: ${CA_KEY} / ${CA_CERT} ..."
6 years ago
openssl ecparam -name prime256v1 -genkey -noout -out "${CA_KEY}"
6 years ago
chmod 0600 "${CA_KEY}"
openssl req -x509 -new -sha256 -nodes -key "${CA_KEY}" -days "${CA_DAYS}" -out "${CA_CERT}" \
6 years ago
-subj "/CN=my-CA" -extensions v3_ca -config "${OPENSSL_CONFIG}"
6 years ago
}
# generate server certificate
##
6 years ago
gen_server_x509() {
6 years ago
echo "[${ME}] Generating new server x509: ${SERVER_KEY} / ${SERVER_CERT} ..."
6 years ago
openssl ecparam -name prime256v1 -genkey -noout -out "${SERVER_KEY}"
6 years ago
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}" \
6 years ago
-extensions v3_req_server -extfile "${OPENSSL_CONFIG}"
6 years ago
}
6 years ago
start() {
6 years ago
echo "[${ME}] Started in ${PWD} directory."
6 years ago
install_openssl;
6 years ago
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
6 years ago
openssl x509 -in "${CA_CERT}" -noout -checkend 2592000 >/dev/null
if [ $? -ne 0 ]; then
6 years ago
echo "[${ME}] WARNING! Your CA certificate will expire in less than 30 days."
fi
6 years ago
openssl x509 -in "${CA_CERT}" -noout -checkend 1 >/dev/null
if [ $? -ne 0 ]; then
6 years ago
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\ "
}
# script starts here
##
6 years ago
start;