Skip to content

Instantly share code, notes, and snippets.

@Stenerson
Created November 5, 2019 18:57
Show Gist options
  • Save Stenerson/264bd842643c7e4d48da0fe682cb04a8 to your computer and use it in GitHub Desktop.
Save Stenerson/264bd842643c7e4d48da0fe682cb04a8 to your computer and use it in GitHub Desktop.
Certbot post deploy hook to safely copy certificates into web application directory
#!/bin/bash
bash /path/to/ssl-deploy-hook -d example.com -p "NEW-PASSPHRASE-FOR-CERTIFICATE-PRIVATE-KEY"
# Example Crontab
# 36 2,14 * * * root /opt/certbot-auto -q renew --deploy-hook /path/to/call-ssl-deploy-hook # this script
#!/bin/bash
set -e
PROGNAME=$(basename $0)
function error_exit
{
# ----------------------------------------------------------------
# Function for exit due to fatal program error
# Accepts 1 argument:
# string containing descriptive error message
# ----------------------------------------------------------------
echo "${PROGNAME}: ${1:-"Unknown Error"}" 1>&2
exit 1
}
function echo_help
{
echo "This script copies SSL certificates into the Application"
echo "So they can be used to prove identity for integration partners."
echo ""
echo "Usage: ssl-deploy-hook -d example.com -p s0m3V3rys3cUr3phR@s3"
echo ""
echo "**Required Environment Variables:**"
echo "This script is meant to run as a certbot hook and as such depends on the"
echo "environment variables set by certbot."
echo "More info: https://certbot.eff.org/docs/using.html#renewing-certificates"
echo ""
echo "RENEWED_DOMAINS will contain a space-delimited list of renewed certificate"
echo " domains (for example, example.com www.example.com)"
echo "RENEWED_LINEAGE will point to the config live subdirectory (for example,"
echo " /etc/letsencrypt/live/example.com) containing the new"
echo " certificates and keys"
echo ""
echo "Options:"
echo " -d | --domain *Required*: Set the renewed domain for this server"
echo " -p | --passphrase *Required*: Set the private keys passphrase"
echo " -h | --help Show this help"
echo ""
}
# Default command line options
TARGET_DOMAIN=""
PASSPHRASE=""
# Parse command line options
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-h|--help)
echo_help
exit 0
;;
-d|--domain)
TARGET_DOMAIN="$2"
if [[ "$TARGET_DOMAIN" == "" ]]; then
# echo_help
error_exit "Target Domain (-d|--domain) is a required option"
fi
shift 2 # past argument & value
;;
-p|--passphrase)
PASSPHRASE="$2"
if [[ "$PASSPHRASE" == "" ]]; then
# echo_help
error_exit "Passphrase (-p|--passphrase) is a required option"
fi
shift 2 # past argument & value
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
for domain in $RENEWED_DOMAINS; do
case $domain in
"$TARGET_DOMAIN")
application_cert_dir="/var/www/path/to/application/cert/dir"
# Make sure the certificate and private key files are
# never world readable, even just for an instant while
# we're copying them into application_cert_dir.
umask 077
# Copy certificate and certificate chain to certs directory
cp "$RENEWED_LINEAGE/cert.pem" "$application_cert_dir/cert.pem"
cp "$RENEWED_LINEAGE/fullchain.pem" "$application_cert_dir/fullchain.pem"
# Encript the private key with the passphrase and export to certs directory
openssl rsa \
-des3 \
-in "$RENEWED_LINEAGE/privkey.pem" \
-passout "pass:$PASSPHRASE" \
-out "$application_cert_dir/privkey.pem"
# Apply the proper file ownership and permissions for
# Apache to read its certificate and key.
chown www-data \
"$application_cert_dir/cert.pem" \
"$application_cert_dir/fullchain.pem" \
"$application_cert_dir/privkey.pem"
# provide read only access to www-data and no access to anyone else
chmod 400 \
"$application_cert_dir/cert.pem" \
"$application_cert_dir/fullchain.pem" \
"$application_cert_dir/privkey.pem"
;;
esac
done
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment