summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-07-30 11:50:23 -0400
committerFreya Murphy <freya@freyacat.org>2025-07-30 11:50:23 -0400
commit896323f6210a4d033885d1c4f0e445ce7f8bb4a2 (patch)
tree67b8fbc7e6f3b422fd2e99ee94ef8d4c982ba078
parentupdate fconv (diff)
downloadscripts-896323f6210a4d033885d1c4f0e445ce7f8bb4a2.tar.gz
scripts-896323f6210a4d033885d1c4f0e445ce7f8bb4a2.tar.bz2
scripts-896323f6210a4d033885d1c4f0e445ce7f8bb4a2.zip
update cfdns
-rwxr-xr-xcfdns287
1 files changed, 113 insertions, 174 deletions
diff --git a/cfdns b/cfdns
index 2476ad0..12679e1 100755
--- a/cfdns
+++ b/cfdns
@@ -1,233 +1,172 @@
-#!/usr/bin/env bash
+#!/bin/bash
-quiet=0 # should i shut up?!?!? :<
+API_TOKEN="${API_TOKEN:-ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcd}"
+ZONE="${ZONE:-example.com}"
+DOMAIN="${DOMAIN:-example.com}"
-token="" # the api token
-domain="" # the domain to update
-
-record="A" # the record type
-ttl="60" # the new time to live
-content="" # the new record content
-
-usage() {
- printf "usage: cfdns [-hq] [-d DOMAIN] [-t TOKEN] [-r RECORD] [-l TTL] [-cC CONTENT]\n\n"
- printf "\t-h\t\tshow the help message\n"
- printf "\t-q\t\tquiet output\n"
- printf "\t-d DOMAIN\tthe domain name to update\n"
- printf "\t-t TOKEN\tthe api token\n"
- printf "\t-r RECORD\tthe new record type\n"
- printf "\t-l TTL\t\tthe new time to live\n"
- printf "\t-c CONTENT\tthe new contents of the record\n"
- printf "\t-C RAW CONTENT\tthe new conents of the record (as raw json)\n"
+EVENT() {
+ printf "\x1b[95m>>> \x1b[0m\x1b[98m$1\n"
}
-chk_command() {
- if ! command -v "$1" > /dev/null; then
- >&2 echo "error: command '$1' could not be found"
- exit 1
- fi
-}
-
-chk_command "getopts"
-chk_command "curl"
-chk_command "jq"
-
-while getopts "hqd:t:r:l:c:C:" arg > /dev/null; do
- case $arg in
- h)
- usage
- exit 0
- ;;
- q)
- quiet=1
- ;;
- d)
- domain="${OPTARG}"
- ;;
- t)
- token="${OPTARG}"
- ;;
- r)
- record="${OPTARG}"
- ;;
- l)
- ttl="${OPTARG}"
- ;;
- c)
- content="\"content\": \"${OPTARG}\""
- ;;
- C)
- content="${OPTARG}"
- ;;
- ?)
- exit 1
- ;;
- esac
-done
-
-if [ ! "$cert" = "cert.pem" ] && [ "$key" = "cert.key" ]; then
- name=${cert%.*}
- key="$name.key"
-fi
-
-log() {
- if [ $quiet = 0 ]; then
- printf "$*\n" 1>&2
- fi
+LOG() {
+ printf "\x1b[98m$1\n"
}
-step() {
- if [ $quiet = 0 ]; then
- printf "\033[32m>>> \033[0m$*\n" 1>&2
- fi
+ERROR() {
+ >&2 printf "\x1b[91mError: \x1b[0m\x1b[98m$1\n"
}
-error() {
- printf "\033[31merror: \033[0m$*\n" > /dev/stderr
-}
-
-die() {
- kill $$
-}
-
-handle_error() {
- errs="$1"
- count="$(echo $errs | jq -r ". | length")"
- for i in $(seq 0 $(($count - 1))); do
- err="$(echo $errs | jq -r ".[$i]")"
- error "$(echo $err | jq -r '.message')"
- chain="$(echo $err | jq -r '.error_chain')"
- if ! [ "$chain" = "null" ]; then
- count="$(echo $chain | jq -r ". | length")"
- for j in $(seq 0 $(($count - 1))); do
- error "$(echo $chain | jq -r ".[$j].message")"
- done
- fi
- done
-}
-
-_curl() {
+CURL() {
RESPONSE=$(curl --silent --request $1 \
--url "https://api.cloudflare.com/client/v4$2" \
--header "Content-Type: application/json" \
- --header "Authorization: Bearer $token" \
+ --header "Authorization: Bearer $API_TOKEN" \
--data "$3")
SUCCESS=$(echo $RESPONSE | jq -r ".success")
if [ "$SUCCESS" != "true" ]; then
- errs="$(echo $RESPONSE | jq -r .errors)"
- handle_error "$errs"
- die
+ ERROR "$(echo $RESPONSE | jq -r ".errors[0].message")"
+ kill $$
fi
echo $RESPONSE | jq ".result"
}
-patch() {
- _curl "PATCH" "$1" "$2"
+PATCH() {
+ CURL "PATCH" "$1" "$2"
}
-post() {
- _curl "POST" "$1" "$2"
+POST() {
+ CURL "POST" "$1" "$2"
}
-get() {
- _curl "GET" "$1" ""
+GET() {
+ CURL "GET" "$1" ""
}
-# Step 1: get the zone the domain is in
-zone=$(echo "$domain" | awk -F'.' '{print $(NF-1)"."$(NF);}' 2>/dev/null)
-
-if [ "$zone" = "" ]; then
- error "invalid domain: '$domain'"
- die
-fi
-
-step "fetching zones..."
-zones=$(get "/zones")
-zone_id="null"
+EVENT "Getting zones"
+ZONES=$(GET "/zones")
+ZONE_ID="null"
i=0
while true; do
- json="$(echo "$zones" | jq ".[$i]")"
- if [ "$json" == "null" ]; then
- break
- fi
+ ZONE_JSON=$(echo $ZONES | jq ".[$i]")
+
+ if [ "$ZONE_JSON" == "null" ]; then
+ break
+ fi
- name="$(echo "$json" | jq -r ".name")"
- id="$(echo "$json" | jq -r ".id")"
+ NAME=$(echo $ZONE_JSON | jq -r ".name")
+ ID=$(echo $ZONE_JSON | jq -r ".id")
- log "found zone: $name ($id)"
+ LOG "Found zone $NAME ($ID)"
+
+ if [ "$NAME" == "$ZONE" ]; then
+ ZONE_ID=$ID
+ break
+ fi
- if [ "$name" == "$zone" ]; then
- zone_id="$id"
- break
- fi
+ ((i=i+1))
- ((i=i+1))
done
-if [ "$zone_id" == "null" ]; then
- error "could not find zone: $zone"
- die
-fi
+if [ "$ZONE_ID" == "null" ]; then
+ ERROR "Could not find zone $DOMAIN"
+ exit 1
+fi
+
+EVENT "Getting records"
-# Step 2: get the current record id if it exists
-step "fetching records..."
+RECORDS=$(GET "/zones/$ZONE_ID/dns_records")
-records="$(get "/zones/$zone_id/dns_records")"
-current="null"
+IPv4Current="null"
+IPv6Current="null"
+IPv4Id="null"
+IPv6Id="null"
i=0
while true; do
+
+ RECORD=$(echo $RECORDS | jq ".[$i]")
- _record="$(echo "$records" | jq ".[$i]")"
+ if [ "$RECORD" == "null" ]; then
+ break
+ fi
- if [ "$_record" == "null" ]; then
- break
- fi
+ NAME=$(echo $RECORD | jq -r '.name')
+ TYPE=$(echo $RECORD | jq -r '.type')
+ CONTENT=$(echo $RECORD | jq -r '.content')
+ ID=$(echo $RECORD | jq -r '.id')
- name="$(echo "$_record" | jq -r ".name")"
- type="$(echo "$_record" | jq -r ".type")"
- _content="$(echo "$_record" | jq -r ".name")"
- id="$(echo "$_record" | jq -r ".id")"
+ LOG "Found record $NAME $TYPE \"$CONTENT\" ($ID)"
- log "found record: $name $type \"$_content\" ($id)"
+ if [ "$NAME" == "$DOMAIN" ] && [ "$TYPE" == "A" ]; then
+ IPv4Current="$CONTENT"
+ IPv4Id="$ID"
+ fi
- if [ "$name" == "$domain" ] && [ "$record" = "$type" ]; then
- current="$id"
- break
- fi
+ if [ "$NAME" == "$DOMAIN" ] && [ "$TYPE" == "AAAA" ]; then
+ IPv6Current="$CONTENT"
+ IPv6Id="$ID"
+ fi
+
+ ((i=i+1))
- ((i=i+1))
done
-# Step 3: update record
-step "updating record"
+EVENT "Getting current IPs"
+
+IPv4New=$(curl ip.me -4sL --silent)
+LOG "Using IPv4 $IPv4New"
+
+IPv6New=$(curl ip.me -6sL --silent)
+LOG "Using IPv6 $IPv6New"
-update() {
- patch "/zones/$zone_id/dns_records/$1" "$2"
+UPDATE() {
+ PATCH "/zones/$ZONE_ID/dns_records/$1" "$2" > /dev/null
}
-create() {
- post "/zones/$zone_id/dns_records" "$1"
+CREATE() {
+ POST "/zones/$ZONE_ID/dns_records" "$1" > /dev/null
}
-json="{
- \"name\": \"$domain\",
- \"proxied\": false,
- \"type\": \"$record\",
- $content
+IPv4JSON="{
+ \"content\": \"$IPv4New\",
+ \"name\": \"$DOMAIN\",
+ \"proxied\": false,
+ \"type\": \"A\"
+}"
+
+IPv6JSON="{
+ \"content\": \"$IPv6New\",
+ \"name\": \"$DOMAIN\",
+ \"proxied\": false,
+ \"type\": \"AAAA\"
}"
-log $(echo "$json" | jq -C)
+EVENT "Updating records"
-if [ "$current" == "null" ]; then
- log "no record found... creating new one"
- create "$json"
+if [ "$IPv4Id" == "null" ]; then
+ LOG "No IPv4 record found... creating new one"
+ CREATE "$IPv4JSON"
+elif [ "$IPv4Current" != "$IPv4New" ]; then
+ LOG "IPv4 record found... updating"
+ UPDATE "$IPv4Id" "$IPv4JSON"
else
- log "record found... updating"
- update "$current" "$json"
+ LOG "IPv4 is up to date... skipping"
fi
-step "successfully updated record"
+if [ -z "$IPv6New" ]; then
+ LOG "System does not support IPv6... skipping"
+elif [ "$IPv6Id" == "null" ]; then
+ LOG "No IPv6 record found... creating new one"
+ CREATE "$IPv6JSON"
+elif [ "$IPv6Current" != "$IPv6New" ]; then
+ LOG "IPv6 record found... updating"
+ UPDATE "$IPv6Id" "$IPv6JSON"
+else
+ LOG "IPv6 is up to date... skipping"
+fi
+
+EVENT "Successfully updated records"
+