Skip to content

Instantly share code, notes, and snippets.

@initialed85
Last active May 8, 2023 01:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save initialed85/afc97fc40e4a2715d831fd69a9629659 to your computer and use it in GitHub Desktop.
Save initialed85/afc97fc40e4a2715d831fd69a9629659 to your computer and use it in GitHub Desktop.
A helper for generating a self-signed .key and .pem / a .key and .csr for external signing

generate-ssl-key-and-csr-and-pem.sh

A script to take some of the toil out of generating a self-signed .key and .pem / a .key and a .csr for external signing.

Limitations

  • Richer detail (country, organisation, etc) not exposed

Usage

Setup

  • Download generate-ssl-key-and-csr-and-pem.sh and probably chmod +x it

Generate a self-signed .key and .pem

# will output ssl.key and ssl.pem
SELF_SIGNED=1 FQDN=some-server.some-domain.org.au ./generate-ssl-key-and-csr-and-pem.sh

Generate a .key and .csr for external signing

# will output ssl.key and ssl.csr
SELF_SIGNED=0 FQDN=some-server.some-domain.org.au ./generate-ssl-key-and-csr-and-pem.sh

Environment variables

Confirm with ./generate-ssl-key-and-csr-and-pem.sh --help; but in summary:

  • SELF_SIGNED - toggle between a self-signed .key and .pem or a .key and a .csr for external signing
  • FQDN - the FQDN to generate .key / .pem / .csr files for
  • DAYS - the number of days to generate .key / .pem / .csr files for (default 397)
  • SSL_KEY - path for .key (default ssl.key)
  • SSL_PEM - path for .key (default ssl.pem)
  • SSL_CSR - path for .key (default ssl.csr)
  • RSA_BITS - path for .key (default 4096)

One-liner download and execute for the brave / trusting

SELF_SIGNED=1 FQDN=some-server.some-domain.org.au bash <(curl -s -L 'https://gist.githubusercontent.com/initialed85/afc97fc40e4a2715d831fd69a9629659/raw/4c755bf09296a0dfae5eb60c13c9afeb9b79dbdc/generate-ssl-key-and-csr-and-pem.sh')
#!/usr/bin/env bash
set -e
SSL_KEY="${SSL_KEY:-ssl.key}"
SSL_PEM="${SSL_PEM:-ssl.pem}"
SSL_CSR="${SSL_CSR:-ssl.csr}"
RSA_BITS="${RSA_BITS:-4096}"
DAYS="${DAYS:-397}"
if [[ ${*} != "" ]]; then
echo -e "$(basename "${0}")\n\na script to help generated a self-signed ${SSL_KEY} and ${SSL_PEM} / a ${SSL_KEY} and a ${SSL_CSR}"
echo -e "\nusage (self-signed ${SSL_KEY} and ${SSL_PEM}):"
echo "SELF_SIGNED=1 FQDN=your.domain.org [CLEAN=0 DAYS=${DAYS} SSL_KEY=${SSL_KEY} SSL_PEM=${SSL_PEM} SSL_CSR=${SSL_CSR} RSA_BITS=${RSA_BITS}] ./$(basename "${0}")"
echo -e "\nusage (${SSL_KEY} and ${SSL_CSR})"
echo "SELF_SIGNED=0 FQDN=your.domain.org [CLEAN=0 DAYS=${DAYS} SSL_KEY=${SSL_KEY} SSL_PEM=${SSL_PEM} SSL_CSR=${SSL_CSR} RSA_BITS=${RSA_BITS}] ./$(basename "${0}")"
exit 1
fi
PLATFORM=$(uname)
export PLATFORM
echo "PLATFORM=$(uname)"
openssl_config=""
if [[ "${PLATFORM}" == "Darwin" ]]; then
openssl_config="/System/Library/OpenSSL/openssl.cnf"
elif [[ "${PLATFORM}" == "Linux" ]]; then
openssl_config="/etc/ssl/openssl.cnf"
else
echo -e "\nerror: unsupported platform: ${PLATFORM}"
exit 1
fi
SELF_SIGNED=${SELF_SIGNED:-}
if [[ "${SELF_SIGNED}" == "" ]]; then
echo "SELF_SIGNED env var empty or unset"
exit 1
fi
export SELF_SIGNED
echo "SELF_SIGNED=${SELF_SIGNED}"
FQDN=${FQDN:-}
if [[ "${FQDN}" == "" ]]; then
echo "FQDN env var empty or unset"
exit 1
fi
export FQDN
echo "FQDN=${FQDN}"
DAYS=${DAYS:-${DAYS}}
export DAYS
echo "DAYS=${DAYS}"
if [[ -e ${SSL_KEY} ]] || [[ -e ${SSL_CSR} ]] || [[ -e ${SSL_PEM} ]]; then
if [[ "${CLEAN}" != "1" ]]; then
echo -e "\nerror: one or more of ${SSL_KEY}, ${SSL_CSR}, ${SSL_PEM} already exist (hint: use CLEAN=1 if they're unimportant)"
exit 1
else
# shellcheck disable=SC2038
echo -e "\nwarning: CLEAN=1 set; deleting $(find . -maxdepth 1 -type f -name 'ssl.*' | xargs)"
rm -fv ssl.* >/dev/null 2>&1
fi
fi
if [[ "${SELF_SIGNED}" == "1" ]]; then
echo -e "\nGenerating self-signed ${SSL_KEY} and ${SSL_PEM} files...\n"
openssl req \
-newkey rsa:"${RSA_BITS}" \
-x509 \
-nodes \
-keyout "${SSL_KEY}" \
-new \
-out "${SSL_PEM}" \
-subj /CN="${FQDN}" \
-reqexts SAN \
-extensions SAN \
-config <(cat ${openssl_config} \
<(printf "[SAN]\nsubjectAltName=DNS:%s" "${FQDN}")) \
-sha256 \
-days "${DAYS}"
echo -e "\nVerifying ssl.* files:\n"
echo "./${SSL_KEY}"
openssl rsa -check -in "${SSL_KEY}"
echo "./${SSL_PEM}"
openssl x509 -text -noout -in "${SSL_PEM}"
else
echo -e "\nGenerating ${SSL_KEY} and ${SSL_CSR} files...\n"
openssl req \
-newkey rsa:"${RSA_BITS}" \
-nodes \
-keyout "${SSL_KEY}" \
-out "${SSL_CSR}" \
-subj /CN="${FQDN}" \
-reqexts SAN \
-extensions SAN \
-config <(cat ${openssl_config} \
<(printf "[SAN]\nsubjectAltName=DNS:%s" "${FQDN}")) \
-sha256 \
-days "${DAYS}"
echo -e "\nVerifying ssl.* files:\n"
echo "./${SSL_KEY}"
openssl rsa -check -in "${SSL_KEY}"
echo "./${SSL_CSR}"
openssl req -text -noout -verify -in "${SSL_CSR}"
fi
echo -e "\nGenerated ssl.* file content:\n"
# shellcheck disable=SC2156
find . -maxdepth 1 -type f -name 'ssl.*' -exec sh -c 'echo "# {}"; cat {}; echo ""' \;
echo -e "Generated ssl.* files:\n"
find . -maxdepth 1 -type f -name 'ssl.*'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment