Last active
March 12, 2017 20:11
-
-
Save floreo/8f73b99935b3755b7f776b2525568193 to your computer and use it in GitHub Desktop.
bash script to generate Let's Encrypt certificates through Acme Tiny
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
## README ## | |
# | |
# * Whats does it require ? | |
# To download or clone https://github.com/diafygi/acme-tiny inside _LE_ACME_DIR | |
# | |
# * How to write a correct conf file ? | |
# Write a file named myname.conf inside _LE_CONF_DIR | |
# hHre's the content: | |
# DIR="the documentroot of your website" | |
# DOMAIN="youdomainname another another" | |
# | |
## CONFIGURATION ## | |
_LE_ACME_DIR="/root/scripts/acme-tiny/" | |
_LE_ROOT_DIR="/root/LE/" | |
_LE_CONF_DIR="${_LE_ROOT_DIR}conf/" | |
_LE_KEY_DIR="${_LE_ROOT_DIR}key/" | |
_LE_CRT_DIR="${_LE_ROOT_DIR}crt/" | |
_LE_CSR_DIR="${_LE_ROOT_DIR}csr/" | |
_LE_PEM_DIR="${_LE_ROOT_DIR}pem/" | |
_LE_ACCOUNT_KEY="${_LE_CONF_DIR}account.key" | |
_LE_INTERMEDIATE_PEM="${_LE_CONF_DIR}intermediate.pem" | |
# time in seconds before expiration date to renew | |
_LE_RENEWAL_BEFORE="1296000" | |
# mail for error messages | |
_LE_MAILTO="" | |
# <empty>, apache2, nginx or haproxy | |
_LE_WEBSERVER="apache2" | |
## MAIN ## | |
mkdir -p ${_LE_ROOT_DIR} ${_LE_CONF_DIR} ${_LE_KEY_DIR} ${_LE_CRT_DIR} ${_LE_CSR_DIR} ${_LE_PEM_DIR} | |
# Get intermediate | |
if [ ! -s "${_LE_INTERMEDIATE_PEM}" ] ; then | |
wget -qO - "https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem" >"${_LE_INTERMEDIATE_PEM}" | |
fi | |
# Generate account key | |
if [ ! -s "${_LE_ACCOUNT_KEY}" ] ; then | |
openssl genrsa 4096 >"${_LE_ACCOUNT_KEY}" &>/dev/null | |
fi | |
# Loop through each configuration file | |
while read _conf | |
do | |
unset DIR DOMAIN | |
. ${_conf} | |
if [ -z "${DIR}" -o -z "${DOMAIN}" ] ; then | |
echo "No variables found for \"${_conf}\" ..." | |
continue | |
fi | |
DIR="${DIR}/.well-known/acme-challenge" | |
CN="$( echo "${DOMAIN}" | awk '{ print $1 }' )" | |
KEY="${_LE_KEY_DIR}${CN}.key" | |
CSR="${_LE_CSR_DIR}${CN}.csr" | |
PEM="${_LE_PEM_DIR}${CN}.pem" | |
CRT="${_LE_CRT_DIR}${CN}_$(date +'%F_%T').crt" | |
CRT_LINK="${_LE_CRT_DIR}${CN}.crt" | |
CRT_FULL="${_LE_CRT_DIR}${CN}-full.crt" | |
echo -n "Doing \"${CN}\" " | |
# Check for renewal | |
if [ -s "${CRT_LINK}" ] ; then | |
openssl x509 -checkend "${_LE_RENEWAL_BEFORE}" -noout -in "${CRT_LINK}" | |
if [ "$?" -eq 0 ] ; then | |
echo -e "... not needed ... \e[32mOK\e[39m" | |
continue | |
fi | |
fi | |
STATUS=0 | |
ACME_ERROR_FILE="$(mktemp)" | |
WEBSERVER_ERROR_FILE="$(mktemp)" | |
mkdir -p "${DIR}" | |
# Generating key | |
if [ ! -s "${KEY}" ] ; then | |
openssl genrsa 4096 >${KEY} 2>/dev/null | |
fi | |
# Generating csr | |
if [ ! -s "${CSR}" ] ; then | |
if [ "$(echo "${DOMAIN}" | grep -o " " | wc -c)" -ge 2 ] ; then | |
SAN="$(echo "${DOMAIN}" | awk 'BEGIN{ ORS=""; print "[SAN]\nsubjectAltName="; ORS=","; }{ for(i = 1; i <= NF; i++) { if(i == NF){ ORS="" } print "DNS:"$i; } }')" | |
openssl req -new -sha256 -key ${KEY} -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(echo "${SAN}")) >${CSR} 2>/dev/null | |
unset SAN | |
else | |
openssl req -new -sha256 -key ${KEY} -subj "/CN=${DOMAIN}" >${CSR} 2>/dev/null | |
fi | |
fi | |
# Generating crt | |
python "${_LE_ACME_DIR}acme_tiny.py" \ | |
--account-key "${_LE_ACCOUNT_KEY}" \ | |
--csr "${CSR}" \ | |
--acme-dir "${DIR}" \ | |
> "${CRT}" 2>${ACME_ERROR_FILE} | |
if [ "$?" == 0 ] ; then | |
# Linking certificate | |
rm -f "${CRT_LINK}" && ln -s "${CRT}" "${CRT_LINK}" | |
# Doing full certificate (nginx) | |
cat "${CRT}" "${_LE_INTERMEDIATE_PEM}" >"${CRT_FULL}" | |
# Doing pem (haproxy) | |
cat "${CRT}" "${_LE_INTERMEDIATE_PEM}" "${KEY}">"${PEM}" | |
# Reload service | |
case "${_LE_WEBSERVER}" in | |
"apache2") | |
service apache2 reload &>/dev/null | |
;; | |
"nginx") | |
service nginx reload &>/dev/null | |
;; | |
"haproxy") | |
service haproxy reload &>/dev/null | |
;; | |
*) | |
echo "No webserver defined or service not known : \"${_LE_WEBSERVER}\"" | |
;; | |
esac | |
# Check webserver | |
if [ "$?" != 0 ] ; then | |
STATUS=2 | |
fi | |
else | |
STATUS=1 | |
fi | |
if [ "${STATUS}" -eq 0 ] ; then | |
echo -e "\e[32mOK\e[39m" | |
else | |
echo -e "\e[31mNOK\e[39m" | |
cat "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}" | |
if [ -n "${_LE_MAILTO}" ] ; then | |
cat "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}" | mail -s "LE.sh --- error generating ${DOMAIN}" ${_LE_MAILTO} | |
fi | |
fi | |
# Cleaning | |
rm -- "${ACME_ERROR_FILE}" "${WEBSERVER_ERROR_FILE}" | |
find "${_LE_CRT_DIR}" -type f -empty -exec rm {} \; | |
done < <( ls ${_LE_CONF_DIR}/*.conf ) | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment