#!/usr/bin/env bash VERSION="1.0" PROG="$(basename "$0")" QUIET=n # shellcheck disable=SC2034 while getopts 'dhp:t:z:i:qv' opt; do case $opt in d) DEBUG="Y" ;; p) AWS_CLI_PROFILE="$OPTARG" ;; q) QUIET= ;; v) echo "dns_route53 version $VERSION"; exit 0 ;; z) ROUTE53_HOSTED_ZONE_NAME="$OPTARG" ;; i) ROUTE53_HOSTED_ZONE_ID="$OPTARG" ;; *) cat <&2 AWS_CLI_PROFILE=default fi op="$1" if ! [[ "$op" =~ ^(add|del)$ ]]; then echo "Operation must be \"add\" or \"del\"" >&2 exit 3 fi name="$2" if [ -z "$name" ]; then echo "'name' parameter is required, see -h" >&2 exit 3 fi data="$3" if [ -z "$data" ]; then echo "'data' parameter is required, see -h" >&2 exit 3 fi if [ "$op" = 'del' ]; then ttl=120 elif [ -z "$5" ]; then ttl="120" elif ! [[ "$5" =~ ^[0-9]+$ ]]; then echo "TTL $5 is not numeric" >&2 exit 3 elif [ "$5" -lt 120 ]; then [ -n "$VERB" ] && \ echo "$5 is too small. Using TTL of 120 instead" >&2 ttl="120" else ttl="$5" fi # end processing parameters [ -n "$DEBUG" ] && \ echo "$PROG: $op $name \"$data\" $ttl" >&2 # Determine what actual hosted zone to use. HOSTED_ZONE_NAME=$ROUTE53_HOSTED_ZONE_NAME HOSTED_ZONE_ID=$ROUTE53_HOSTED_ZONE_ID RR_NAME="_acme-challenge.${name}" RR_VALUE="${data}" # Function to parse through the segments in the supplied name # to determine the zone and its id function determine_hosted_zone_name_and_id() { TMP_NAME=$name TMP_RR_NAME= while [[ "$TMP_NAME" =~ ^([^.]+)\.([^.]+.*) ]]; do if [ -n "${TMP_RR_NAME}" ]; then TMP_RR_NAME="${TMP_RR_NAME}."; fi TMP_RR_NAME="${TMP_RR_NAME}${BASH_REMATCH[1]}" testdomain="${BASH_REMATCH[2]}" [ -n "$DEBUG" ] && echo "Testing hosted zone ${testdomain}" TMP_NAME=$testdomain if [[ ! "$TMP_NAME" =~ [^.]+\.[^.]+ ]]; then [ -n "$DEBUG" ] && echo "No segments left" exit 1 fi TMP_ZONE_ID=$(aws --profile="${AWS_CLI_PROFILE}" route53 list-hosted-zones --query "HostedZones[?Name=='${testdomain}'].Id | [0]" | sed -e 's/^"//' -e 's/"$//') if [ "${TMP_ZONE_ID}" != "null" ]; then [ -n "$DEBUG" ] && echo "Found hosted zone ${testdomain}" HOSTED_ZONE_NAME=${testdomain} HOSTED_ZONE_ID=$TMP_ZONE_ID break fi done } # If zone ID is specified, then use it to determine the hosted zone name if [ -n "${HOSTED_ZONE_ID}" ]; then HOSTED_ZONE_NAME=$(aws --profile="${AWS_CLI_PROFILE}" route53 list-hosted-zones --query "HostedZones[?Id=='${ZONE_ID}'].Name | [0]" | sed -e 's/^"//' -e 's/"$//') # If zone name is specified, then use it to get the zone id elif [ -n "${HOSTED_ZONE_NAME}" ]; then HOSTED_ZONE_ID=$(aws --profile="${AWS_CLI_PROFILE}" route53 list-hosted-zones --query "HostedZones[?Name=='${HOSTED_ZONE_NAME}'].Id | [0]" | sed -e 's/^"//' -e 's/"$//') else determine_hosted_zone_name_and_id fi if [ -z "${HOSTED_ZONE_ID}" ]; then echo "Hosted zone id not specified or determined" >&2 exit 3 fi if [ "$op" = "add" ]; then ACTION="UPSERT" elif [ "$op" = "del" ]; then ACTION="DELETE" else echo "Unsupported Operation: $op" >&2 fi CHANGE_BATCH=' { "Comment": "GetSSL LetsEncrypt DNS Challenge", "Changes": [{ "Action" : "'"$ACTION"'", "ResourceRecordSet" : { "Name" : "'"$RR_NAME"'", "Type" : "TXT", "TTL" : '${ttl}', "ResourceRecords" : [{ "Value" : "\"'$RR_VALUE'\"" }] } }] } ' [ -n "$DEBUG" ] && echo "${CHANGE_BATCH}" >&2 aws \ --profile="${AWS_CLI_PROFILE}" \ route53 \ change-resource-record-sets \ --hosted-zone-id="${HOSTED_ZONE_ID}" \ --change-batch "${CHANGE_BATCH}" exit $?