82 lines
2.6 KiB
Bash
82 lines
2.6 KiB
Bash
#!/usr/bin/env bash
|
|
# DNS records, over whichever provider the target names.
|
|
#
|
|
# Usage:
|
|
# ./dns.sh list
|
|
# ./dns.sh add <subdomain> # <sub>.<domain> -> <domain>
|
|
# ./dns.sh add-wildcard <sub>
|
|
# ./dns.sh remove <subdomain>
|
|
#
|
|
# Read-only verbs announce and wait; mutating ones refuse.
|
|
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
source ./lib/config.sh
|
|
source ./lib/estate.sh
|
|
load_config
|
|
|
|
announce() {
|
|
echo "would run:"
|
|
printf ' %s\n' "$*"
|
|
}
|
|
|
|
list() {
|
|
case "$DNS_PROVIDER" in
|
|
route53)
|
|
announce "aws route53 list-resource-record-sets --hosted-zone-id $AWS_HOSTED_ZONE_ID" \
|
|
"--query 'ResourceRecordSets[].[Name,Type,TTL,ResourceRecords[0].Value]' --output table"
|
|
;;
|
|
google)
|
|
announce "gcloud dns record-sets list --zone=${ESTATE}-zone --project=${GCP_PROJECT:-<unset>}"
|
|
;;
|
|
*) echo "unknown DNS_PROVIDER: $DNS_PROVIDER" >&2; exit 1 ;;
|
|
esac
|
|
echo
|
|
echo "read-only, but NOT run: each batch is announced and"
|
|
echo "waited on. Approve it and it runs."
|
|
}
|
|
|
|
mutate() {
|
|
local verb="$1" sub="${2:-}"
|
|
[ -z "$sub" ] && { echo "usage: $0 $verb <subdomain>" >&2; exit 1; }
|
|
local name
|
|
case "$verb" in
|
|
add) name="${sub}.${DOMAIN}" ;;
|
|
add-wildcard) name="*.${sub}.${DOMAIN}" ;;
|
|
remove) name="${sub}.${DOMAIN}" ;;
|
|
esac
|
|
echo "$verb: $name -> $DOMAIN (provider: $DNS_PROVIDER)"
|
|
echo
|
|
|
|
# The wildcard-depth rule again, applied BEFORE the record is created rather
|
|
# than discovered in a browser afterwards.
|
|
if [ "$verb" = "add" ]; then
|
|
local issued; issued=$(estate_get "certs.issued" | python3 -c 'import json,sys
|
|
try: print("\n".join(json.load(sys.stdin)))
|
|
except Exception: pass')
|
|
local covered=""
|
|
while IFS= read -r san; do
|
|
[ -z "$san" ] && continue
|
|
san_covers "$name" "$san" && { covered=1; break; }
|
|
done <<< "$issued"
|
|
[ -z "$covered" ] && {
|
|
echo "WARNING: '$name' is covered by no issued SAN." >&2
|
|
echo " A wildcard matches ONE label. The record would" >&2
|
|
echo " resolve and then fail TLS. Reissue the cert first." >&2
|
|
echo >&2
|
|
}
|
|
fi
|
|
|
|
echo "REFUSING: this changes live DNS." >&2
|
|
echo " Nothing is created, modified or deleted on any account without" >&2
|
|
echo " explicit approval for that specific action." >&2
|
|
exit 1
|
|
}
|
|
|
|
case "${1:-list}" in
|
|
list) list ;;
|
|
add|add-wildcard|remove) mutate "$@" ;;
|
|
*) echo "usage: $0 [list|add <sub>|add-wildcard <sub>|remove <sub>]" >&2; exit 1 ;;
|
|
esac
|