Created
March 11, 2021 10:44
-
-
Save movd/03febb3ab6435db46452fb55f3a44d65 to your computer and use it in GitHub Desktop.
Run as a cronjob to restore the `cloud.` DNS record that dynv6.com currently keeps on deleting because of a bug in the system.
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
#!/usr/bin/env bash | |
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" | |
me="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")" | |
DYNV6_APIBASE="https://dynv6.com/api/v2/zones" | |
DYNV6_TOKEN=${DYNV6_TOKEN} | |
DYNV6_CNAME_RECORD=${DYNV6_CNAME_RECORD} | |
dynv6_zone_name="" | |
check_dependencies() { | |
# look for required binaries (taken straight from dehydrated) | |
for binary in curl jq dig ts; do | |
bin_path="$(command -v "${binary}" 2>/dev/null)" || _exiterr "This script requires ${binary}." | |
[[ -x "${bin_path}" ]] || _exiterr "${binary} found in PATH but it's not executable" | |
done | |
} | |
_echo() { | |
echo "${me}: ${1}" |ts | |
} | |
_exiterr() { | |
echo "ERROR: ${1}" >&2 | |
exit 1 | |
} | |
check_config() { | |
if [ -z "${DYNV6_TOKEN}" ] || [ -z "${DYNV6_ZONEID}" ]; then | |
# if env variables not set source .env file as config | |
# load .env https://stackoverflow.com/a/30969768 and check | |
set -o allexport | |
# shellcheck disable=SC1090 | |
source "${DIR}/${ENV}.env" 2>/dev/null || _exiterr "${DIR}/${ENV}.env is not available!" && | |
set +o allexport | |
[[ -n "${DYNV6_TOKEN}" ]] || _exiterr "Environment variable DYNV6_TOKEN is empty!" | |
[[ -n "${DYNV6_ZONEID}" ]] || _exiterr "Environment variable DYNV6_ZONEID is empty!" | |
[[ -n "${DYNV6_CNAME_RECORD}" ]] || _exiterr "Environment variable DYNV6_CNAME_RECORD is empty!" | |
fi | |
} | |
check_dynv6_connection() { | |
# test connection to dynv6 api | |
check_connection_status_code=$(curl -s -o /dev/null -I -w "%{http_code}" -X GET -H "Authorization: Bearer ${DYNV6_TOKEN}" ${DYNV6_APIBASE}/"${DYNV6_ZONEID}"/records) | |
if ! [[ $check_connection_status_code = "200" ]]; then | |
[[ "$check_connection_status_code" == "401" ]] && _exiterr "HTTP code 401: Unauthorized" | |
[[ "$check_connection_status_code" == "403" ]] && _exiterr "HTTP code 403: Forbidden. Check your DYNV6_TOKEN" | |
[[ "$check_connection_status_code" == "404" ]] && _exiterr "HTTP code 404: Zone not found. Check your DYNV6_ZONEID" | |
_exiterr "Could not connect to dynv6 API. returned HTTP code: ${check_connection_status_code}" | |
fi | |
} | |
get_zone_name() { | |
# get zone name from zone id | |
all_zones=$(curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer ${DYNV6_TOKEN}" ${DYNV6_APIBASE} ) | |
dynv6_zone_name=$(echo "${all_zones}" | jq -r --arg arg "$DYNV6_ZONEID" ' | |
map( | |
select( | |
( | |
.id == ( $arg | tonumber ) | |
) | |
) | |
) | .[].name' # Just extract the zone name | |
) | |
} | |
create_new_cname_record() { | |
json_payload='{"name":"'"$DYNV6_CNAME_RECORD"'","data":"'$dynv6_zone_name.'","type":"CNAME"}' | |
_echo "Sending the following payload..." | |
_echo "${json_payload}" | |
res=$(curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Bearer ${DYNV6_TOKEN}" -d "$json_payload" ${DYNV6_APIBASE}/"${DYNV6_ZONEID}"/records) | |
record_id=$(echo "${res}"| jq -r '.id') | |
re='^[0-9]+$' | |
if ! [[ $record_id =~ $re ]]; then | |
_exiterr "Something is really wrong. I did not receive a numeric ID from the dynv6.com API" | |
else | |
_echo "Created CNAME record with id: ${record_id}. The API responded with:" | |
_echo "${res}" | |
_echo "Waiting for DNS propagation..." | |
i=1 | |
# cloud.example.com must answer with example.com | |
while ! dig CNAME +trace +noall +answer "${DYNV6_CNAME_RECORD}.${dynv6_zone_name}" | grep -q "${dynv6_zone_name}."; do | |
# abort propagation check after 30 seconds | |
sleep 1 | |
((i++)) | |
if ((i > 29)); then | |
break | |
fi | |
done | |
fi | |
} | |
run_main() { | |
all_records=$(curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer ${DYNV6_TOKEN}" ${DYNV6_APIBASE}/"${DYNV6_ZONEID}"/records) | |
found_record_id=$(echo "${all_records}" | jq -r --arg arg "$DYNV6_CNAME_RECORD" 'map(select((.name == $arg ))) | .[].id') | |
# If found_record_id is not NaN it does not exist | |
re='^[0-9]+$' | |
if ! [[ $found_record_id =~ $re ]]; then | |
_echo "No record for '${DYNV6_CNAME_RECORD}.${dynv6_zone_name}' found! I will create a new one..." | |
create_new_cname_record || exit 1 | |
#else | |
#_echo "Record '${DYNV6_CNAME_RECORD}.${dynv6_zone_name}' already exists. I will do nothing." | |
fi | |
} | |
check_dependencies || exit 1 | |
check_config || exit 1 | |
check_dynv6_connection || exit 1 | |
get_zone_name || exit 1 | |
run_main || exit 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Run this script like so:
The following environment variables are required:
DYNV6_TOKEN
DYNV6_ZONEID
DYNV6_CNAME_RECORD
= The subdomain that gets wrongfully deletedEnvironment variables can be set in a
.env
file in the same folder as the script or passed via the shell.Get
DYNV6_TOKEN
Key:View your default token or create a new one: "🔍 Details"
Get
DYNV6_ZONEID
ID:https://dynv6.com/zones/123456
is123456
Example crontab entry:
Limitations:
example.com
must be set up as a single-zone.