berth init
This commit is contained in:
81
berth/ctrl/dns.sh
Normal file
81
berth/ctrl/dns.sh
Normal file
@@ -0,0 +1,81 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user