Skip to content

Instantly share code, notes, and snippets.

@matschundbrei
Last active September 4, 2016 00:43
Show Gist options
  • Save matschundbrei/a6ab4dd8bf2b665dd028334b433a7d19 to your computer and use it in GitHub Desktop.
Save matschundbrei/a6ab4dd8bf2b665dd028334b433a7d19 to your computer and use it in GitHub Desktop.
A bash script (relying on jq & awscli) to update/add single records in Route53
#!/bin/bash
# author: Matschundbrei <[email protected]>
# usage
USAGE="usage: `basename $0` name.domain.tld type value [ttl]"
# default ttl:
DEFTTL=3600
# AWS profile (in .aws/credentials) to use
AWSPROFILE="owndns"
if [[ $# -lt 3 ]]; then
echo $USAGE
exit 0
fi
which jq > /dev/null
if [[ $? -ne 0 ]]; then
echo "in order to run this script you will need to install jq (https://stedolan.github.io/jq/)"
exit 1
fi
which aws > /dev/null
if [[ $? -ne 0 ]]; then
echo "in order to run this script you will need to install the aws cli tools (http://docs.aws.amazon.com/cli/latest/userguide/installing.html)"
echo "you will also need to set up a profile to access Route53 in AWS in your ~/.aws/credentials"
exit 1
fi
NAME=$1
TYPE=${2^^}
VALUE=$3
if [ -z ${4+x} ]; then
TTL=$DEFTTL
else
TTL=$4
fi
# check if name is valid domain name
# straight from http://stackoverflow.com/questions/15268987/bash-based-regex-domain-name-validation
echo $NAME | grep -P '(?=^.{5,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)' > /dev/null
if [[ $? -ne 0 ]]; then
echo "sorry, but $NAME does not look like a valid dns name!"
echo $USAGE
exit 1
fi
# check for valid type
echo $TYPE | grep -P '^(TXT|A|AAAA|MX|SRV|CNAME)$' > /dev/null
if [[ $? -ne 0 ]]; then
echo "allowed record types are: A, AAAA, TXT, MX, CNAME and SRV; you gave: $TYPE"
echo $USAGE
exit 1
fi
# check if TTL is a number
echo $TTL | grep -P '^[0-9]+$' > /dev/null
if [[ $? -ne 0 ]]; then
echo "The TTL you gave me does not seem to be an integer number: $TTL"
echo $USAGE
exit 1
fi
# split value if longer than 255 chars
# see https://kb.isc.org/article/AA-00356/0/Can-I-have-a-TXT-or-SPF-record-longer-than-255-characters.html
VALLEN=$(echo $VALUE | wc -c)
if [[ $VALLEN -gt 255 ]] && [ "$TYPE" == "TXT" ]; then
RESTVAL=$VALUE
NEWVAL=""
while [ $(echo $RESTVAL | wc -c) -gt 255 ]; do
if [ -z "$NEWVAL" ]; then
NEWVAL="\"${RESTVAL:0:254}\""
RESTVAL="${RESTVAL:254}"
else
NEWVAL="$NEWVAL \"${RESTVAL:0:254}\""
RESTVAL="${RESTVAL:254}"
fi
done
NEWVAL="$NEWVAL \"${RESTVAL}\""
VALUE=$NEWVAL
elif [[ $VALLEN -gt 255 ]]; then
echo "sorry, but we don't allow for values with over 255 characters for record-type $TYPE (TXT works, though)"
echo $USAGE
exit 1
elif [ "$TYPE" == "TXT" ] || [ "$TYPE" == "SRV" ]; then
VALUE="\"${VALUE}\""
fi
COMMENT="Updated by ${HOSTNAME} via script"
JSON=$(jq -n -M -c --arg com "${COMMENT}" --arg ttl ${TTL} --arg name "${NAME}" --arg typ "${TYPE}" --arg value "${VALUE}" \
'.Comment = $com | .Changes[0].Action = "UPSERT" | .Changes[0].ResourceRecordSet.Name = $name | .Changes[0].ResourceRecordSet.Type = $typ | .Changes[0].ResourceRecordSet.TTL = $ttl | .Changes[0].ResourceRecordSet.ResourceRecords[0].Value = $value | .Changes[0].ResourceRecordSet.ResourceRecords[0].Value |= tostring | .Changes[0].ResourceRecordSet.TTL |= tonumber')
DOMAIN=$(echo -n ${NAME} | jq -R -r 'split(".") | reverse | [ .[1,0] | tostring ] | join(".")')
ZONEID=$(aws --profile ${AWSPROFILE} route53 list-hosted-zones | jq -r --arg dom "${DOMAIN}" '.HostedZones[] | if .Name | contains($dom) then .Id else empty end')
if [ -z $ZONEID ] ; then
echo "We're sorry, but your domain ${DOMAIN} was not found in the hosted zones of AWS Route53"
exit 1
else
echo "updating remote record for ${DOMAIN}"
RESULT=$(aws --profile ${AWSPROFILE} route53 change-resource-record-sets --hosted-zone-id "${ZONEID}" --change-batch "${JSON}")
echo "Here's the result: ${RESULT}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment