#!/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 <<EOF
|
|
Usage
|
|
$PROG [-dt -q] add name data [ttl]
|
|
$PROG [-dt -h -p "aws-profile-name" -q] del name data
|
|
|
|
Add or delete TXT records from Route53 Hosted Zone
|
|
|
|
You must have the AWS CLI installed and a profile configured for this script to work.
|
|
The IAM user that the profile uses requires the following action permissions in AWS:
|
|
- route53:ListHostedZones - Not necessary if zone ID is available to this script
|
|
- route53:ChangeResourceRecordSets
|
|
|
|
With getssl, this script is called from the dns_add_route53 and
|
|
dns_del_route53 wrapper scripts.
|
|
|
|
Arguments:
|
|
add - add the specified record to the domain
|
|
|
|
del - remove the specified record from the domain
|
|
|
|
name is the fully qualified record name to create the challenge for e.g. www.example.org. Note that trailing '.' is necessary. Also note that _acme-challenge. will automatically be prepended by this script
|
|
|
|
data is the record data, e.g. "myverificationtoken"
|
|
|
|
ttl is optional and will default to 120 if not specified
|
|
|
|
If it is necessary to turn on debugging externally, define
|
|
ROUTE53_DEBUG="y" (any non-null string will do).
|
|
For minimal trace output (to override -q), define ROUTE53_TRACE="y".
|
|
|
|
Options
|
|
-d Provide debugging output - all requests and responses
|
|
-h This help.
|
|
-i: The hosted zone ID
|
|
-p: The AWS CLI profile to use. Will use default if not specified
|
|
-q: Quiet - omit normal success messages
|
|
-z: The hosted zone name. Will be used to determine the zone ID if ID was not provided
|
|
|
|
All output, except for this help text, is to stderr.
|
|
|
|
Environment variables
|
|
ROUTE53_SCRIPT location of this script
|
|
ROUTE53_HOSTED_ZONE_NAME The name of the hosted zone name. If not specified, then the name will be determined from the record name provided to this script
|
|
ROUTE53_HOSTED_ZONE_ID The id of the hosted zone to be used instead of trying to automatically determine the ID
|
|
AWS_CLI_PROFILE the aws cli profile to use if not using default
|
|
|
|
BUGS
|
|
Report any issues to https://github.com/xyide/getssl/issues
|
|
EOF
|
|
exit 0
|
|
;;
|
|
esac
|
|
done
|
|
shift $((OPTIND-1))
|
|
|
|
if [ -z "$AWS_CLI_PROFILE" ]; then
|
|
echo "AWS_CLI_PROFILE not defined. Using default" >&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 $?
|