Skip to content

Instantly share code, notes, and snippets.

@allex
Last active February 22, 2021 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save allex/c070a927b5ef5cb34a1f713a0f169dae to your computer and use it in GitHub Desktop.
Save allex/c070a927b5ef5cb34a1f713a0f169dae to your computer and use it in GitHub Desktop.
#!/bin/bash
# GistID: c070a927b5ef5cb34a1f713a0f169dae
# Directories
cur=$(pwd)
tmp=$(mktemp -d)
scriptName=$(basename "$0")
# Certificate Variables
OUTPATH="./"
VERBOSE=0
DURATION=3650 # 10 years
safeExit() {
if [ -d "$tmp" ]; then
if [ $VERBOSE -eq 1 ]; then
echo "Removing temporary directory '${tmp}'"
fi
rm -rf "$tmp"
fi
trap - INT TERM EXIT
exit
}
# Help Screen
help() {
echo -n "${scriptName} [OPTIONS] -c=US --state=California
Generate self-signed TLS certificate using OpenSSL
Options:
-c|--country Country Name (2 letter code)
-s|--state State/Province Name (full name)
-l|--locality Locality Name (eg, city)
-o|--organization Organization Name (eg, company)
-u|--unit Organizational Unit Name (eg, section)
-n|--common-name Common Name (e.g. server FQDN or YOUR name)
-e|--email Email Address
-p|--path Path to output generated keys
-d|--duration Validity duration of the certificate (in days)
-h|--help Display this help and exit
-v|--verbose Verbose output
"
}
# Test output path is valid
testPath() {
if [ ! -d $OUTPATH ]; then
echo "The specified directory \"${OUTPATH}\" does not exist"
exit 1
fi
}
# Process Arguments
while [ "$1" != "" ]; do
PARAM=$(echo "$1" | awk -F= '{print $1}')
VALUE=$(echo "$1" | awk -F= '{print $2}')
case $PARAM in
-h|--help) help; safeExit ;;
-c|--country) C=$VALUE ;;
-s|--state) ST=$VALUE ;;
-l|--locality) L=$VALUE ;;
-o|--organization) O=$VALUE ;;
-u|--unit) OU=$VALUE ;;
-n|--common-name) CN=$VALUE ;;
-e|--email) emailAddress=$VALUE ;;
-p|--path) OUTPATH=$VALUE; testPath ;;
-d|--duration) DURATION=$VALUE ;;
-v|--verbose) VERBOSE=1 ;;
*) echo "ERROR: unknown parameter \"$PARAM\""; help; exit 1 ;;
esac
shift
done
# Prompt for variables that were not provided in arguments
checkVariables() {
# Country
if [ -z "$C" ]; then
echo -n "[C] Country Name (2 letter code) [CN]: "
read -r C
fi
# State
if [ -z "$ST" ]; then
echo -n "[ST] State/Province Name (full name) [Beijing]: "
read -r ST
fi
# Locality
if [ -z "$L" ]; then
echo -n "[L] Locality Name (eg, city) []: "
read -r L
fi
# Organization
if [ -z "$O" ]; then
echo -n "[O] Organization Name (eg, company) [iallex]: "
read -r O
fi
# Organizational Unit
if [ -z "$OU" ]; then
echo -n "[OU] Organizational Unit Name (eg, section) []: "
read -r OU
fi
# Common Name
if [ -z "$CN" ]; then
echo -n "[CN] Common Name (e.g. server FQDN or YOUR name) []: "
read -r CN
fi
# Email Address
if [ -z "$emailAddress" ]; then
echo -n "Email Address []: "
read -r emailAddress
fi
}
# Show variable values
showVals() {
echo "Country: ${C}";
echo "State: ${ST}";
echo "Locality: ${L}";
echo "Organization: ${O}";
echo "Organization Unit: ${OU}";
echo "Common Name: ${CN}";
echo "Email: ${emailAddress}";
echo "Output Path: ${OUTPATH}";
echo "Certificate Duration (Days): ${DURATION}";
echo "Verbose: ${VERBOSE}";
}
# Init
init() {
cd "$tmp" || exit
pwd
}
# Cleanup
cleanup() {
echo "Cleaning up"
cd "$cur" || exit
rm -rf "$tmp"
}
buildCsrCnf() {
# ; csr config for server key
cat << EOF > "${tmp}/tmp.csr.cnf"
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C=${C}
ST=${ST}
L=${L}
O=${O}
OU=${OU}
CN=${CN}
emailAddress=${emailAddress}
EOF
"${VISUAL:-${EDITOR:-vi}}" -- "${tmp}/tmp.csr.cnf"
}
buildExtCnf() {
# ; extensions for server certificate
cat << EOF > "${tmp}/v3.ext"
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = ${CN}
DNS.2 = im.l
IP.1 = 127.0.0.1
EOF
"${VISUAL:-${EDITOR:-vi}}" -- "$tmp/v3.ext"
}
# Build TLS Certificate
build() {
# Santizie domain name for file name
FILENAME=`printf "${CN/\*\./}"|sed "s# \+#_#g"`
# Generate CA key & crt
openssl genrsa -out "${tmp}/tmp.key" 2048
openssl req -x509 -new -nodes \
-key "${tmp}/tmp.key" \
-sha256 \
-days "${DURATION}" \
-out "${OUTPATH}${FILENAME}_CA.pem" \
-subj "/C=${C}/${ST:+ST=${ST}/}${L:+L=${L}/}O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
# CSR Configuration
buildCsrCnf
# Create v3.ext configuration file
buildExtCnf
# Server key
openssl req -new -sha256 -nodes \
-out "${OUTPATH}${FILENAME}.csr" \
-newkey rsa:2048 -keyout "${OUTPATH}${FILENAME}.key" \
-config <( cat "${tmp}/tmp.csr.cnf" )
# Server certificate
openssl x509 -req \
-in "${OUTPATH}${FILENAME}.csr" \
-CA "${OUTPATH}${FILENAME}_CA.pem" \
-CAkey "${tmp}/tmp.key" \
-CAcreateserial \
-out "${OUTPATH}${FILENAME}.crt" \
-days "${DURATION}" \
-sha256 \
-extfile "${tmp}/v3.ext"
}
checkVariables
build
showVals
safeExit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment