#!/usr/bin/env bash single=0 # merge the certs into a single cert force=0 # if to skip similariaty checks or not quiet=0 # should i shut up?!?!? :< cert='cert.pem' # where the public cert should go key='cert.key' # where the private cert should go domain='localhost' # the domain to copy certs from email="freya@freyacat.org" status=0 usage() { printf "usage: recert [-hsfq] [-d DOMAIN] [-c CERT] [-k KEY]\n\n" printf "\t-h\t\tshow the help message\n" printf "\t-s\t\tcombine the certs into a single cert\n" printf "\t-f\t\tskip cert equal checks (force)\n" printf "\t-q\t\tquiet output\n" printf "\t-d DOMAIN\tthe domain name to recert\n" printf "\t-c CERT\t\tthe destination path for the cert\n" printf "\t-k KEY\t\tthe destination path for the key (no -s)\n" } hash() { if [ -f "$1" ]; then sha3sum "$1" | awk '{ print $1 }'; fi } letscert() { args=(--non-interactive --agree-tos --no-eff-email --email "$email") certbot delete \ $args \ --cert-name "$domain" certbot certonly \ $args \ --preferred-chain "ISRG Root X1" \ --key-type rsa \ --webroot \ --webroot-path "/var/www/html" \ --domains "$1" status=1 } recert_log() { if [ $quiet = 0 ]; then printf "$*" 1>&2 fi } chk_command() { if ! command -v "$1" > /dev/null; then >&2 echo "error: command '$1' could not be found" exit 1 fi } while getopts ":hsfqd:c:k:" arg > /dev/null; do case $arg in h) usage exit 0 ;; s) single=1 ;; f) force=1 ;; q) quiet=1 ;; d) domain=${OPTARG} ;; c) cert=${OPTARG} ;; k) key=${OPTARG} ;; ?) echo "unknown option" exit 1 ;; esac done chk_command "getopts" chk_command "certbot" chk_command "openssl" if [ ! "$cert" = "cert.pem" ] && [ "$key" = "cert.key" ]; then name=${cert%.*} key="$name.key" fi # Step 1: make sure letsencrypt certs exist (create if not) lets_root="/etc/letsencrypt/live" lets_cert="$lets_root/$domain/fullchain.pem" lets_key="$lets_root/$domain/privkey.pem" if [ ! -f "$lets_cert" ] && [ ! -f "$lets_key" ]; then letscert "$domain" fi # Step 2: make sure certs wont expire soon (create if will) if openssl x509 -checkend 604800 -noout -in "$lets_cert" > /dev/null; then # certificate is good, only update if forced if [ $force = 1 ]; then rm "$lets_root"/* rmdir "$lets_root" recert_log "renewing... " letscert "$domain" fi else recert_log "renewing... " letscert "$domain" fi # Step 3: store lets encrypt cert into tmp file tmp=$(mktemp) if [ $single = 1 ]; then { cat "$lets_cert"; echo; cat "$lets_key"; } >> "$tmp" fi # Setup 4: get hashes current_hash="" if [ -f "$cert" ]; then current_hash=$(md5sum "$lets_cert" | cut -f 1 -d " ") else current_hash="FORCE" fi new_hash="" if [ $single = 1 ]; then new_hash=$(md5sum "$tmp" | cut -f 1 -d " ") else new_hash=$(md5sum "$lets_cert" | cut -f 1 -d " ") fi # Step 5: copy if hases out of date if [ "$current_hash" != "$new_hash" ]; then recert_log "copied certs\n" if [ $single = 1 ]; then cp "$tmp" "$cert" else cp "$lets_cert" "$cert" cp "$lets_key" "$key" fi status=1 else recert_log "up to date\n" fi # Cleanup rm "$tmp" exit "$status"