# dns hook for https://github.com/dehydrated-io/dehydrated # shellcheck shell=bash # some code taken from: # https://github.com/silkeh/pdns_api.sh # https://github.com/spfguru/dehydrated4googlecloud function porkbun-request() { local endpoint="$1" json="$2" url="https://porkbun.com/api/json/v3/$endpoint" body=$(echo "$json" | jq '.apikey = "'"$porkbun_api_key"'" | .secretapikey = "'"$porkbun_secret_key"'"') resp=$(curl -X POST -sSL "$url" -H content-type:application/json --data "$body") status=$(echo "$resp" | jq -r '.status') if [ "$status" != "SUCCESS" ]; then >&2 echo " ! Request to $url returned $status: $(echo "$resp" | jq -r '.message')" exit 1 fi echo "$resp" } function join() { local IFS="$1"; shift; echo "$*"; } function split-domain() { local domain="${1}" local all mapfile -t all < <(porkbun-request 'domain/listAll' '{}' | jq -r '.domains | map(.domain) | join(" ")') IFS='.' read -ra parts <<< "${domain}" for (( i=${#parts[@]}-1; i>=0; i-- )); do step="$(join . "${parts[@]:i}")" # shellcheck disable=SC2128 # nuh uh for check in $all; do if [ "$step" = "$check" ]; then echo -e "$step\n$(join . "${parts[@]:0:i}")" return fi done done exit 1 } function deploy_challenge() { local domain="${1}" token_value="${3}" echo " = Deploying challenge for $domain" mapfile -t split < <(split-domain "$domain") challenge="_acme-challenge.${split[1]}" porkbun-request "dns/create/${split[0]}" '{ "name": "'"$challenge"'", "type": "TXT", "content": "'"$token_value"'" }' > /dev/null echo " = Waiting for record to propogate" for nameserver in $(dig "${split[0]}" NS +short); do echo " = Checking NS $nameserver" verified=false while [ $verified = false ]; do result="$(dig +short "_acme-challenge.$domain" txt "@$nameserver")" while IFS= read -r line; do line="${line//'"'/''}" if [ "$line" = "$token_value" ]; then verified=true break fi done <<< "$result" [ $verified = false ] && sleep 1 done done echo " = Deployed" } function clean_challenge() { local domain="${1}" token_value="${3}" echo " = Cleaning up challenge for $domain" mapfile -t split < <(split-domain "$domain") mapfile -t ids < <(porkbun-request "dns/retrieve/${split[0]}" '{}' \ | jq -r '.records | map(select(.name == "_acme-challenge.'"$domain"'" and .type == "TXT" and .content == "'"$token_value"'")) | map(.id) | join(" ")') if [ "${#ids[@]}" != 0 ]; then # shellcheck disable=SC2128 # nuh uh for id in $ids; do porkbun-request "dns/delete/${split[0]}/$id" '{}' > /dev/null done fi } function config-get() { local name="$1" bash -c "source ~/.keys/sysconf.sh && echo \$$name" } HANDLER="$1"; shift if [[ "${HANDLER}" =~ ^(deploy_challenge|clean_challenge)$ ]]; then porkbun_api_key=$(config-get PORKBUN_API_KEY) porkbun_secret_key=$(config-get PORKBUN_SECRET_KEY) if [ -z "$porkbun_api_key$porkbun_secret_key" ]; then echo "missing porkbun secrets" exit 1 fi "$HANDLER" "$@" fi