Last active
October 6, 2023 09:34
-
-
Save guss77/01f095623a1d2fd00869784554d3e1a5 to your computer and use it in GitHub Desktop.
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
#!/bin/bash -e | |
verbosity=info | |
tokfile="/tmp/tok-$$" | |
domlist_pfx="/tmp/doms-$$-" | |
doctl_tokens=( | |
# Place all your DO personal access tokens here in this array as simple text, preferably one per line | |
) | |
function log() { | |
local level="$1" dolog= | |
shift | |
local message="$*" | |
case "$verbosity" in | |
debug) dolog=1;; | |
info) [ "$level" == "debug" ] || dolog=1;; | |
warn) [ "$level" == "debug" -o "$level" == "info" ] || dolog=1;; | |
error) [ "$level" == "error" ] && dolog=1;; | |
esac | |
[ -n "$dolog" ] && logger -st "$(basename $0)" "$message" | |
} | |
for level in debug info warn error; do | |
eval "function $level() { log $level \"\$*\"; }" | |
done | |
function doctl() { | |
[ -f $tokfile ] || return 1 | |
/app/auth/doctl -t $(cat $tokfile) "$@" | |
} | |
function cache_domain_auth() { | |
for token in ${doctl_tokens[@]}; do | |
echo $token > $tokfile | |
doctl compute domain list --no-header | cut -d' ' -f1 > ${domlist_pfx}${token} | |
done | |
} | |
function auth_domain() { | |
local zoneid="$1" host_name="$2" token="$3" | |
doctl compute domain records create "${zoneid}" \ | |
--record-name "${host_name%.$zoneid}" --record-type TXT --record-data "${token}" \ | |
--record-ttl 30 >&2 | |
} | |
function clear_token() { | |
local zoneid="$1" host_name="$2" token="$3" | |
doctl compute domain records list "${zoneid}" | grep TXT | fgrep "${host_name%.$zoneid} " | while read rid nop; do | |
doctl compute domain records delete "${zoneid}" "$rid" -f | |
done | |
} | |
function get_ns() { | |
local domain="$1" | |
dig ns "$domain" | awk '$1!~/^;/&&$4=="NS"{print$5}' | head -n1 | |
} | |
function get_tokens() { | |
local domain="$1" host_name="$2" | |
dig @$(get_ns "$domain") txt "$host_name" | awk '$1!~/^;/&&$4=="TXT"{print substr($0, index($0,$5))}' | |
} | |
function wait_for_record() { | |
local domain="$1" host_name="$2" token="$3" | |
start=$(date +%s) | |
count=0 | |
while ! (get_tokens "$domain" "$host_name" | grep -q '"'"$token"'"'); do | |
debug "Still waiting for $host_name from $domain $(( $(date +%s) - $start ))" | |
sleep 2 | |
count=$(( $count + 1 )) | |
if [ "$count" -gt 30 ]; then | |
error "Timedout verifying token '$3' on $host_name from $domain" | |
exit 2 | |
fi | |
done | |
sleep 15 # wait for DNS propagation time. Ideally we won't need to do that, or at least only as the last challenge | |
# but certbot doesn't send promised $CERTBOT_REMAINING_CHALLENGES nor supports --manual-propagation-seconds option | |
} | |
function find_zone() { | |
local lookup="$1" | |
for token in ${doctl_tokens[@]}; do | |
for zone in $(cat ${domlist_pfx}${token}); do | |
debug "Chceking $lookup against DigitalOcean zone $zone" | |
[ "${lookup%$zone}" == "$lookup" ] && continue # certbot domain is not in this zone | |
echo $token > $tokfile | |
echo $zone | |
return | |
done | |
done | |
error "Failed to find valid zone for $lookup!" | |
return 1 | |
} | |
function cleanup() { | |
for token in ${doctl_tokens[@]}; do rm -f ${domlist_pfx}${token}; done | |
rm -f $tokfile | |
} | |
cache_domain_auth | |
find_zone "$CERTBOT_DOMAIN" | while read zoneid; do | |
if [[ -v CERTBOT_AUTH_OUTPUT ]]; then # cleanup | |
info "Cleaning up ACME challenge for $CERTBOT_DOMAIN in $zoneid" >&2 | |
clear_token "$zoneid" "_acme-challenge.$CERTBOT_DOMAIN" "$CERTBOT_VALIDATION" | |
else # auth | |
info "Generating ACME challenge for $CERTBOT_DOMAIN in $zoneid" | |
auth_domain "$zoneid" "_acme-challenge.$CERTBOT_DOMAIN" "$CERTBOT_VALIDATION" | |
wait_for_record "$zoneid" "_acme-challenge.$CERTBOT_DOMAIN" "$CERTBOT_VALIDATION" | |
fi | |
done | |
info "Done with $CERTBOT_DOMAIN" | |
cleanup |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment