Last active
September 4, 2016 00:43
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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