fix: target the correct public domain records in dns automation
This commit is contained in:
parent
e048079fa6
commit
3c05c7f7e8
2 changed files with 131 additions and 32 deletions
|
|
@ -4,7 +4,8 @@ set -euo pipefail
|
||||||
: "${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}"
|
: "${CLOUDFLARE_API_TOKEN:?set CLOUDFLARE_API_TOKEN}"
|
||||||
: "${CLOUDFLARE_ZONE_ID:?set CLOUDFLARE_ZONE_ID}"
|
: "${CLOUDFLARE_ZONE_ID:?set CLOUDFLARE_ZONE_ID}"
|
||||||
: "${BASE_DOMAIN:?set BASE_DOMAIN}"
|
: "${BASE_DOMAIN:?set BASE_DOMAIN}"
|
||||||
: "${SERVER_IP:?set SERVER_IP}"
|
: "${PUBLIC_DOMAIN:=$BASE_DOMAIN}"
|
||||||
|
: "${DNS_MODE:=upsert}"
|
||||||
|
|
||||||
api() {
|
api() {
|
||||||
curl -fsS -X "$1" "https://api.cloudflare.com/client/v4$2" \
|
curl -fsS -X "$1" "https://api.cloudflare.com/client/v4$2" \
|
||||||
|
|
@ -13,15 +14,21 @@ api() {
|
||||||
${3:+--data "$3"}
|
${3:+--data "$3"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lookup_record_id() {
|
||||||
|
local type="$1"
|
||||||
|
local name="$2"
|
||||||
|
curl -fsS "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records?type=$type&name=$name" \
|
||||||
|
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["result"][0]["id"] if d.get("result") else "")'
|
||||||
|
}
|
||||||
|
|
||||||
upsert_record() {
|
upsert_record() {
|
||||||
local type="$1"
|
local type="$1"
|
||||||
local name="$2"
|
local name="$2"
|
||||||
local content="$3"
|
local content="$3"
|
||||||
local proxied="${4:-false}"
|
local proxied="${4:-false}"
|
||||||
local existing_id
|
local existing_id
|
||||||
existing_id=$(curl -fsS "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID/dns_records?type=$type&name=$name" \
|
existing_id=$(lookup_record_id "$type" "$name")
|
||||||
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
|
|
||||||
-H 'Content-Type: application/json' | python3 -c 'import sys,json; d=json.load(sys.stdin); print(d["result"][0]["id"] if d.get("result") else "")')
|
|
||||||
|
|
||||||
local payload
|
local payload
|
||||||
payload=$(printf '{"type":"%s","name":"%s","content":"%s","ttl":120,"proxied":%s}' "$type" "$name" "$content" "$proxied")
|
payload=$(printf '{"type":"%s","name":"%s","content":"%s","ttl":120,"proxied":%s}' "$type" "$name" "$content" "$proxied")
|
||||||
|
|
@ -33,8 +40,42 @@ upsert_record() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
upsert_record A "$BASE_DOMAIN" "$SERVER_IP" false
|
delete_record() {
|
||||||
upsert_record A "git.$BASE_DOMAIN" "$SERVER_IP" false
|
local type="$1"
|
||||||
upsert_record A "registry.$BASE_DOMAIN" "$SERVER_IP" false
|
local name="$2"
|
||||||
|
local existing_id
|
||||||
|
existing_id=$(lookup_record_id "$type" "$name")
|
||||||
|
|
||||||
echo "cloudflare dns updated for $BASE_DOMAIN, git.$BASE_DOMAIN, registry.$BASE_DOMAIN"
|
if [[ -n "$existing_id" ]]; then
|
||||||
|
api DELETE "/zones/$CLOUDFLARE_ZONE_ID/dns_records/$existing_id" >/dev/null
|
||||||
|
echo "deleted $type $name"
|
||||||
|
else
|
||||||
|
echo "skipped missing $type $name"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
records=(
|
||||||
|
"$PUBLIC_DOMAIN"
|
||||||
|
"git.$PUBLIC_DOMAIN"
|
||||||
|
"registry.$PUBLIC_DOMAIN"
|
||||||
|
)
|
||||||
|
|
||||||
|
case "$DNS_MODE" in
|
||||||
|
upsert)
|
||||||
|
: "${SERVER_IP:?set SERVER_IP}"
|
||||||
|
upsert_record A "${records[0]}" "$SERVER_IP" false
|
||||||
|
upsert_record A "${records[1]}" "$SERVER_IP" false
|
||||||
|
upsert_record A "${records[2]}" "$SERVER_IP" false
|
||||||
|
echo "cloudflare dns updated for ${records[*]}"
|
||||||
|
;;
|
||||||
|
delete)
|
||||||
|
delete_record A "${records[0]}"
|
||||||
|
delete_record A "${records[1]}"
|
||||||
|
delete_record A "${records[2]}"
|
||||||
|
echo "cloudflare dns cleanup finished for ${records[*]}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unsupported DNS_MODE: $DNS_MODE" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,32 @@ require python3
|
||||||
: "${PORKBUN_API_KEY:?set PORKBUN_API_KEY}"
|
: "${PORKBUN_API_KEY:?set PORKBUN_API_KEY}"
|
||||||
: "${PORKBUN_SECRET_API_KEY:?set PORKBUN_SECRET_API_KEY}"
|
: "${PORKBUN_SECRET_API_KEY:?set PORKBUN_SECRET_API_KEY}"
|
||||||
: "${BASE_DOMAIN:?set BASE_DOMAIN}"
|
: "${BASE_DOMAIN:?set BASE_DOMAIN}"
|
||||||
: "${SERVER_IP:?set SERVER_IP}"
|
: "${PUBLIC_DOMAIN:=$BASE_DOMAIN}"
|
||||||
|
: "${DNS_MODE:=upsert}"
|
||||||
|
|
||||||
api_base="https://api.porkbun.com/api/json/v3"
|
api_base="https://api.porkbun.com/api/json/v3"
|
||||||
|
|
||||||
|
if [[ "$PUBLIC_DOMAIN" == "$BASE_DOMAIN" ]]; then
|
||||||
root_name=""
|
root_name=""
|
||||||
|
elif [[ "$PUBLIC_DOMAIN" == *".$BASE_DOMAIN" ]]; then
|
||||||
|
root_name="${PUBLIC_DOMAIN%.${BASE_DOMAIN}}"
|
||||||
|
else
|
||||||
|
echo "PUBLIC_DOMAIN must equal BASE_DOMAIN or be a subdomain of BASE_DOMAIN" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -n "$root_name" ]]; then
|
||||||
|
git_name="git.$root_name"
|
||||||
|
registry_name="registry.$root_name"
|
||||||
|
else
|
||||||
git_name="git"
|
git_name="git"
|
||||||
registry_name="registry"
|
registry_name="registry"
|
||||||
|
fi
|
||||||
|
|
||||||
payload() {
|
payload() {
|
||||||
local content="$1"
|
local name="$1"
|
||||||
printf '{"apikey":"%s","secretapikey":"%s","content":"%s","ttl":"600"}' \
|
local content="$2"
|
||||||
"$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY" "$content"
|
printf '{"apikey":"%s","secretapikey":"%s","name":"%s","type":"A","content":"%s","ttl":"600"}' \
|
||||||
|
"$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY" "$name" "$content"
|
||||||
}
|
}
|
||||||
|
|
||||||
list_records() {
|
list_records() {
|
||||||
|
|
@ -31,13 +45,9 @@ list_records() {
|
||||||
--data "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_API_KEY\"}"
|
--data "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_API_KEY\"}"
|
||||||
}
|
}
|
||||||
|
|
||||||
upsert_a_record() {
|
lookup_record_id() {
|
||||||
local name="$1"
|
local fqdn="$1"
|
||||||
local fqdn="$BASE_DOMAIN"
|
python3 - "$fqdn" "$(list_records)" <<'PY'
|
||||||
[[ -n "$name" ]] && fqdn="$name.$BASE_DOMAIN"
|
|
||||||
|
|
||||||
local record_id
|
|
||||||
record_id=$(python3 - "$fqdn" "$(list_records)" <<'PY'
|
|
||||||
import json,sys
|
import json,sys
|
||||||
fqdn=sys.argv[1]
|
fqdn=sys.argv[1]
|
||||||
data=json.loads(sys.argv[2])
|
data=json.loads(sys.argv[2])
|
||||||
|
|
@ -46,17 +56,31 @@ for rec in data.get('records', []):
|
||||||
print(rec.get('id',''))
|
print(rec.get('id',''))
|
||||||
break
|
break
|
||||||
PY
|
PY
|
||||||
)
|
}
|
||||||
|
|
||||||
|
upsert_a_record() {
|
||||||
|
local name="$1"
|
||||||
|
local fqdn="$BASE_DOMAIN"
|
||||||
|
[[ -n "$name" ]] && fqdn="$name.$BASE_DOMAIN"
|
||||||
|
|
||||||
|
local record_id
|
||||||
|
record_id=$(lookup_record_id "$fqdn")
|
||||||
|
|
||||||
if [[ -n "$record_id" ]]; then
|
|
||||||
curl -fsS "$api_base/dns/edit/$BASE_DOMAIN/$record_id" \
|
|
||||||
-H 'Content-Type: application/json' \
|
|
||||||
--data "$(payload "$SERVER_IP")" >/dev/null
|
|
||||||
echo "updated A $fqdn -> $SERVER_IP"
|
|
||||||
else
|
|
||||||
local body
|
local body
|
||||||
body=$(printf '{"apikey":"%s","secretapikey":"%s","name":"%s","type":"A","content":"%s","ttl":"600"}' \
|
body=$(printf '{"apikey":"%s","secretapikey":"%s","name":"%s","type":"A","content":"%s","ttl":"600"}' \
|
||||||
"$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY" "$name" "$SERVER_IP")
|
"$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY" "$name" "$SERVER_IP")
|
||||||
|
|
||||||
|
if [[ -n "$record_id" ]]; then
|
||||||
|
local delete_body
|
||||||
|
delete_body=$(printf '{"apikey":"%s","secretapikey":"%s"}' "$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY")
|
||||||
|
curl -fsS "$api_base/dns/delete/$BASE_DOMAIN/$record_id" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data "$delete_body" >/dev/null
|
||||||
|
curl -fsS "$api_base/dns/create/$BASE_DOMAIN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data "$body" >/dev/null
|
||||||
|
echo "updated A $fqdn -> $SERVER_IP"
|
||||||
|
else
|
||||||
curl -fsS "$api_base/dns/create/$BASE_DOMAIN" \
|
curl -fsS "$api_base/dns/create/$BASE_DOMAIN" \
|
||||||
-H 'Content-Type: application/json' \
|
-H 'Content-Type: application/json' \
|
||||||
--data "$body" >/dev/null
|
--data "$body" >/dev/null
|
||||||
|
|
@ -64,8 +88,42 @@ PY
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete_a_record() {
|
||||||
|
local name="$1"
|
||||||
|
local fqdn="$BASE_DOMAIN"
|
||||||
|
[[ -n "$name" ]] && fqdn="$name.$BASE_DOMAIN"
|
||||||
|
|
||||||
|
local record_id
|
||||||
|
record_id=$(lookup_record_id "$fqdn")
|
||||||
|
|
||||||
|
if [[ -n "$record_id" ]]; then
|
||||||
|
local body
|
||||||
|
body=$(printf '{"apikey":"%s","secretapikey":"%s"}' "$PORKBUN_API_KEY" "$PORKBUN_SECRET_API_KEY")
|
||||||
|
curl -fsS "$api_base/dns/delete/$BASE_DOMAIN/$record_id" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data "$body" >/dev/null
|
||||||
|
echo "deleted A $fqdn"
|
||||||
|
else
|
||||||
|
echo "skipped missing A $fqdn"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "$DNS_MODE" in
|
||||||
|
upsert)
|
||||||
|
: "${SERVER_IP:?set SERVER_IP}"
|
||||||
upsert_a_record "$root_name"
|
upsert_a_record "$root_name"
|
||||||
upsert_a_record "$git_name"
|
upsert_a_record "$git_name"
|
||||||
upsert_a_record "$registry_name"
|
upsert_a_record "$registry_name"
|
||||||
|
echo "porkbun dns updated for $PUBLIC_DOMAIN, git.$PUBLIC_DOMAIN, registry.$PUBLIC_DOMAIN"
|
||||||
echo "porkbun dns updated for $BASE_DOMAIN, git.$BASE_DOMAIN, registry.$BASE_DOMAIN"
|
;;
|
||||||
|
delete)
|
||||||
|
delete_a_record "$root_name"
|
||||||
|
delete_a_record "$git_name"
|
||||||
|
delete_a_record "$registry_name"
|
||||||
|
echo "porkbun dns cleanup finished for $PUBLIC_DOMAIN, git.$PUBLIC_DOMAIN, registry.$PUBLIC_DOMAIN"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unsupported DNS_MODE: $DNS_MODE" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue