|
#!/bin/bash |
|
### |
|
# https://gist.github.com/killerbees19/2f3595eed8ce7b26e9a445b712bd09d4 |
|
### |
|
set -euf -o pipefail |
|
|
|
CN=$(hostname -f) |
|
SAN="$CN,www.$CN" |
|
DATE=$(date +%Y%m%d-%H%M%S) |
|
DIR="/etc/ssl/certbot" |
|
WEB="/var/www/html" |
|
ARGS= # --staging |
|
RENEWAL=31 |
|
|
|
LATEST_KEY=".key" |
|
LATEST_CSR=".csr" |
|
LATEST_CERT=".pem" |
|
LATEST_CHAIN=".chain.pem" |
|
LATEST_FULLCHAIN=".fullchain.pem" |
|
|
|
CURRENT_KEY=".$DATE.key" |
|
CURRENT_CSR=".$DATE.csr" |
|
CURRENT_CERT=".$DATE.pem" |
|
CURRENT_CHAIN=".$DATE.chain.pem" |
|
CURRENT_FULLCHAIN=".$DATE.fullchain.pem" |
|
|
|
NEXT_KEY=".next.key" |
|
NEXT_CSR=".next.csr" |
|
|
|
# TODO: Check if CN/SAN changed? (csr != crt) |
|
# ... |
|
|
|
# TODO: Cleanup old files? |
|
# ... |
|
|
|
if [ ! -d "$DIR" ] |
|
then |
|
echo "Error: $DIR not found!" 1>&2 |
|
exit 1 |
|
fi |
|
|
|
generate_csr() |
|
{ |
|
OLDIFS="$IFS" |
|
IFS=","; san= |
|
for dns in $SAN |
|
do |
|
if [[ "$san" != "" ]] |
|
then |
|
san+=", " |
|
fi |
|
|
|
san+="DNS:$dns" |
|
done; IFS="$OLDIFS" |
|
|
|
if [[ "$san" != "" ]] |
|
then |
|
san="subjectAltName = \"$san\"" |
|
fi |
|
|
|
openssl genrsa -out "$DIR/rsa$CURRENT_KEY" 4096 2>/dev/null |
|
openssl req -new -sha256 -key "$DIR/rsa$CURRENT_KEY" -out "$DIR/rsa$CURRENT_CSR" -subj "/CN=$CN" -addext "$san" |
|
|
|
openssl ecparam -genkey -name secp384r1 | openssl ec -out "$DIR/ecc$CURRENT_KEY" 2>/dev/null |
|
openssl req -new -sha256 -key "$DIR/ecc$CURRENT_KEY" -out "$DIR/ecc$CURRENT_CSR" -subj "/CN=$CN" -addext "$san" |
|
|
|
ln -s -f "./rsa$CURRENT_KEY" "$DIR/rsa$NEXT_KEY" |
|
ln -s -f "./rsa$CURRENT_CSR" "$DIR/rsa$NEXT_CSR" |
|
|
|
ln -s -f "./ecc$CURRENT_KEY" "$DIR/ecc$NEXT_KEY" |
|
ln -s -f "./ecc$CURRENT_CSR" "$DIR/ecc$NEXT_CSR" |
|
|
|
echo "Notice: New key/csr pair generated." 1>&2 |
|
echo "It'll be used for new certificates." 1>&2 |
|
} |
|
|
|
generate_crt() |
|
{ |
|
if [ ! -e "$DIR/rsa$NEXT_KEY" ] || \ |
|
[ ! -e "$DIR/rsa$NEXT_CSR" ] || \ |
|
[ ! -e "$DIR/ecc$NEXT_KEY" ] || \ |
|
[ ! -e "$DIR/ecc$NEXT_CSR" ] |
|
then |
|
generate_csr |
|
fi |
|
|
|
mode="${1:-}" |
|
|
|
[[ "$mode" == "quiet" ]] \ |
|
&& quiet=1 || quiet=0 |
|
|
|
if [ "$(basename "$(readlink -f "$DIR/rsa$NEXT_KEY")")" != "$(basename "$(readlink -f "$DIR/rsa$LATEST_KEY")")" ] || \ |
|
[ "$(basename "$(readlink -f "$DIR/rsa$NEXT_CSR")")" != "$(basename "$(readlink -f "$DIR/rsa$LATEST_CSR")")" ] || \ |
|
[ "$(basename "$(readlink -f "$DIR/ecc$NEXT_KEY")")" != "$(basename "$(readlink -f "$DIR/ecc$LATEST_KEY")")" ] || \ |
|
[ "$(basename "$(readlink -f "$DIR/ecc$NEXT_CSR")")" != "$(basename "$(readlink -f "$DIR/ecc$LATEST_CSR")")" ] |
|
then |
|
mode="force" |
|
fi |
|
|
|
if [ "$mode" == "force" ]; then echo "Notice: Renewal forced..." 1>&2 |
|
elif [ ! -e "$DIR/rsa$LATEST_CERT" ] || [ ! -e "$DIR/ecc$LATEST_CERT" ] || \ |
|
! test "$(find "$DIR/rsa$LATEST_CERT" "$DIR/ecc$LATEST_CERT" -mtime +"$RENEWAL")" |
|
then |
|
if [ "$quiet" -ne 1 ] |
|
then |
|
echo "Warning: Renewal not required yet!" 1>&2 |
|
echo " Use \"gencrt\" to force it." 1>&2 |
|
fi |
|
|
|
exit 0 |
|
fi |
|
|
|
# shellcheck disable=SC2086 |
|
certbot certonly $ARGS \ |
|
--non-interactive --quiet \ |
|
--csr "$DIR/rsa$NEXT_CSR" \ |
|
--cert-path "$DIR/rsa$CURRENT_CERT" \ |
|
--chain-path "$DIR/rsa$CURRENT_CHAIN" \ |
|
--fullchain-path "$DIR/rsa$CURRENT_FULLCHAIN" \ |
|
--webroot --webroot-path "$WEB" --domain "$SAN" |
|
|
|
# shellcheck disable=SC2086 |
|
certbot certonly $ARGS \ |
|
--non-interactive --quiet \ |
|
--csr "$DIR/ecc$NEXT_CSR" \ |
|
--cert-path "$DIR/ecc$CURRENT_CERT" \ |
|
--chain-path "$DIR/ecc$CURRENT_CHAIN" \ |
|
--fullchain-path "$DIR/ecc$CURRENT_FULLCHAIN" \ |
|
--webroot --webroot-path "$WEB" --domain "$SAN" |
|
|
|
ln -s -f "./rsa$CURRENT_CERT" "$DIR/rsa$LATEST_CERT" |
|
ln -s -f "./rsa$CURRENT_CHAIN" "$DIR/rsa$LATEST_CHAIN" |
|
ln -s -f "./rsa$CURRENT_FULLCHAIN" "$DIR/rsa$LATEST_FULLCHAIN" |
|
ln -s -f "./$(basename "$(readlink -f "$DIR/rsa$NEXT_KEY")")" "$DIR/rsa$LATEST_KEY" |
|
ln -s -f "./$(basename "$(readlink -f "$DIR/rsa$NEXT_CSR")")" "$DIR/rsa$LATEST_CSR" |
|
|
|
ln -s -f "./ecc$CURRENT_CERT" "$DIR/ecc$LATEST_CERT" |
|
ln -s -f "./ecc$CURRENT_CHAIN" "$DIR/ecc$LATEST_CHAIN" |
|
ln -s -f "./ecc$CURRENT_FULLCHAIN" "$DIR/ecc$LATEST_FULLCHAIN" |
|
ln -s -f "./$(basename "$(readlink -f "$DIR/ecc$NEXT_KEY")")" "$DIR/ecc$LATEST_KEY" |
|
ln -s -f "./$(basename "$(readlink -f "$DIR/ecc$NEXT_CSR")")" "$DIR/ecc$LATEST_CSR" |
|
|
|
if [ "$quiet" -ne 1 ] |
|
then |
|
echo "Notice: New certificate saved." 1>&2 |
|
echo "Please restart your daemons." 1>&2 |
|
fi |
|
} |
|
|
|
case "${1:-}" in |
|
|
|
"genkey"|"gencsr") |
|
generate_csr |
|
;; |
|
|
|
"gencrt"|"genpem") |
|
generate_crt "force" |
|
;; |
|
|
|
"cron") |
|
generate_crt "quiet" |
|
;; |
|
|
|
"help") |
|
echo "Usage: $0 [{genkey|gencsr|gencrt|genpem|cron|help}]" |
|
exit 0 |
|
;; |
|
|
|
*) |
|
generate_crt |
|
;; |
|
|
|
esac |