Skip to content

Instantly share code, notes, and snippets.

@smiller171
Forked from mariocesar/dyndns_route53.py
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smiller171/9976620 to your computer and use it in GitHub Desktop.
Save smiller171/9976620 to your computer and use it in GitHub Desktop.

route53_auto-update

Automatically update a route53 entry at init.

To make these scripts work for you you need to make a few edits:

  • First, Add your Hosted_Zone ID in dyndns_route53.py
  • Then enter the domain name that you want kept up-to-date

I highly suggest storing dyndns_route53.py in S3 or somewhere where your instance can easily download it.

  • Edit user-data to point at the location of dyndns_route53.py

  • The contents of this file go in the user-data field when spinning up an instance or setting up an auto-scaling rule.

If you are going to be using the IAM role I provided you need to edit it to point at the correct hosted-zone

I will likely expand this role in a future update to grant permissions to the python script in S3. Right now I have that script set as public.

Credit for dyndns_route53.py goes to @mariocesar His original gist can be found here: https://gist.github.com/mariocesar/4142563

"""
Requirements:
$ sudo pip install boto dnspython
Edit ~/.boto to use your AWS credentials or use included IAM role
"""
import time
import sys
import urllib2
import dns.resolver
from boto.route53.connection import Route53Connection
from boto.route53.exception import DNSServerError
from boto.route53.record import ResourceRecordSets
import logging
logger = logging.getLogger(__name__)
handler = logging.FileHandler('dyndns_route53.log')
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.INFO)
# Settings, Change me!
HOSTED_ZONE = 'Enter Your Hosted Zone ID Here'
DOMAIN_NAME = 'domain.name.you.want.updated.com'
get_change_id = lambda response: response['ChangeInfo']['Id'].split('/')[-1]
get_change_status = lambda response: response['ChangeInfo']['Status']
def resolve_name_ip(name):
resolver = dns.resolver.Resolver()
resolver.nameservers = [
'8.8.8.8',
'8.8.4.4'
]
answer = resolver.query(name)
"""
>>> answer.response.answer[0].to_text()
home.mydomain.com. 60 IN A 192.168.0.2'
>>> answer.response.answer[0].items
[<DNS IN A rdata: 192.168.0.2>]
>>> answer.response.answer[0].items[0].address
'192.168.0.2'
"""
return answer.response.answer[0].items[0].address
def main():
# Get your public IP from the hypervisor
# If you wish to use this on a non-AWS server, use http://ip.42.pl/raw instead
current_ip = urllib2.urlopen('http://169.254.169.254/latest/meta-data/public-ipv4').read()
# Avoid to hit the Route53 API if is not necessary.
# so compare first to a DNS server if the IP changed
resolved_ip = resolve_name_ip(DOMAIN_NAME)
if resolved_ip == current_ip:
logger.debug('DNS response (%s) and public IP (%s) are the same, nothing to do' % (resolved_ip, current_ip))
return
conn = Route53Connection()
try:
zone = conn.get_hosted_zone(HOSTED_ZONE)
except DNSServerError:
logger.error('%s Zone Not Found' % HOSTED_ZONE)
sys.exit(1)
response = conn.get_all_rrsets(HOSTED_ZONE, 'A', DOMAIN_NAME, maxitems=1)[0]
if current_ip not in response.resource_records:
logger.info('Found new IP: %s' % current_ip)
# Delete the old record, and create a new one.
# This code is from route53.py script, the change record command
changes = ResourceRecordSets(conn, HOSTED_ZONE, '')
change1 = changes.add_change("DELETE", DOMAIN_NAME, 'A', response.ttl)
for old_value in response.resource_records:
change1.add_value(old_value)
change2 = changes.add_change("CREATE", DOMAIN_NAME, 'A', response.ttl)
change2.add_value(current_ip)
try:
commit = changes.commit()
logger.debug('%s' % commit)
except:
logger.error("Changes can't be made: %s" % commit)
sys.exit(1)
else:
change = conn.get_change(get_change_id(commit['ChangeResourceRecordSetsResponse']))
logger.debug('%s' % change)
while get_change_status(change['GetChangeResponse']) == 'PENDING':
time.sleep(2)
change = conn.get_change(get_change_id(change['GetChangeResponse']))
logger.debug('%s' % change)
if get_change_status(change['GetChangeResponse']) == 'INSYNC':
logger.info('Change %s A de %s -> %s' % (DOMAIN_NAME, response.resource_records[0], current_ip))
else:
logger.warning('Unknow status for the change: %s' % change)
logger.debug('%s' % change)
if __name__ == '__main__':
main()
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1396631065000",
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:GetChange",
"route53:GetHostedZone",
"route53:ListHostedZones",
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/Z215MEZ908EMNX"
]
}
]
}
#!/bin/bash
mkdir /tmp/dyndns
cd /tmp/dyndns
# edit the following to the path where your python script resides
wget https://s3.amazonaws.com/<s3-bucket>/dyndns_route53.py
python dyndns_route53.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment