Skip to content

Instantly share code, notes, and snippets.

@adamrothman
Last active March 4, 2016 22:44
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 adamrothman/91fcd5dc2e0c009b9c05 to your computer and use it in GitHub Desktop.
Save adamrothman/91fcd5dc2e0c009b9c05 to your computer and use it in GitHub Desktop.
Update a Route 53 record with your current external IP address
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
import re
import sys
from argparse import ArgumentParser
from datetime import datetime
from subprocess import CalledProcessError
from subprocess import check_output
from botocore.session import get_session
IP_PATTERN = r'^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
RECORD_TYPE = 'A'
def log(msg):
print('{}\t{}'.format(datetime.now().isoformat(), msg))
def get_external_ip():
try:
ip = check_output(['dig', '+short', 'myip.opendns.com', '@resolver1.opendns.com'])
if re.match(IP_PATTERN, ip):
return ip.strip()
else:
log('IP "{}" does not match pattern'.format(ip))
except CalledProcessError as e:
log(e.output)
return None
def get_registered_ip(client, hosted_zone_id, record_name):
res = client.list_resource_record_sets(
HostedZoneId=hosted_zone_id,
StartRecordName=record_name,
StartRecordType=RECORD_TYPE,
MaxItems='1',
)
resource_record_sets = res['ResourceRecordSets']
if resource_record_sets:
record_set = resource_record_sets[0]
if record_set['Name'] == record_name and record_set['Type'] == RECORD_TYPE:
resource_records = record_set['ResourceRecords']
if resource_records:
return resource_records[0]['Value']
return None
def register_ip(client, hosted_zone_id, record_name, ip, ttl):
res = client.change_resource_record_sets(
HostedZoneId=hosted_zone_id,
ChangeBatch={
'Comment': datetime.now().isoformat(),
'Changes': [
{
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': record_name,
'ResourceRecords': [{'Value': ip}],
'TTL': ttl,
'Type': RECORD_TYPE,
},
},
],
},
)
return res['ResponseMetadata']['HTTPStatusCode'] == 200
if __name__ == '__main__':
parser = ArgumentParser(description='Update Route 53 A record')
parser.add_argument('hosted_zone_id', type=str)
parser.add_argument('record_name', type=str)
parser.add_argument('-t', '--ttl', default=3600, type=int)
args = parser.parse_args()
external_ip = get_external_ip()
if external_ip is None:
log('Unable to determine external IP address')
sys.exit(1)
route53 = get_session().create_client('route53')
registered_ip = get_registered_ip(route53, args.hosted_zone_id, args.record_name)
if registered_ip != external_ip:
if register_ip(route53, args.hosted_zone_id, args.record_name, external_ip, args.ttl):
log('Updated {} with address {}'.format(args.record_name, external_ip))
else:
log('Failed to update {}'.format(args.record_name))
sys.exit(1)
else:
log('IP address unchanged for {}'.format(args.record_name))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment