Skip to content

Instantly share code, notes, and snippets.

@mtbdeano
Created June 29, 2015 21:10
Show Gist options
  • Save mtbdeano/fbd7672c04e7b4657e37 to your computer and use it in GitHub Desktop.
Save mtbdeano/fbd7672c04e7b4657e37 to your computer and use it in GitHub Desktop.
Simple python script to keep Amazon Route 53 public/private split horizon DNS domains in sync
import boto.route53
import boto.ec2
import pprint as pp
def match_domain(domain, region="us-east-1"):
''' iterate through the public EIPs and make sure that if there is a `domain.com` entry for that EIP, it's private IP is also mapped in the private `domain.com`
'''
r53 = boto.route53.connect_to_region(region)
ec2 = boto.ec2.connect_to_region(region)
public_zone = None
private_zone = None
# need to make sure the domain ends with a dot
if domain[-1:] is not u'.':
domain += u'.'
for zone in r53.get_zones():
if zone.name == domain:
if zone.config[u'PrivateZone'] == u'true':
private_zone = zone
else:
public_zone = zone
if public_zone is None or private_zone is None:
print(u'Unable to find matching {} entries'.format(domain))
eips = filter(lambda eip: eip.domain == u'vpc', ec2.get_all_addresses())
# route53 objects
public_addresses = filter(lambda r: r.type == u'A', r53.get_all_rrsets(public_zone.id))
private_addresses = filter(lambda r: r.type == u'A', r53.get_all_rrsets(private_zone.id))
# convenience set
set_of_private_addresses = set(map(lambda x: x.resource_records[0], private_addresses))
# maps
public_to_private = {eip.public_ip: eip.private_ip_address for eip in eips}
public_to_name = {r.resource_records[0]: r.name for r in public_addresses}
# cross domain map
name_to_private = {name: public_to_private[public_ip] for (public_ip, name) in
filter(lambda (ip, name): ip in public_to_private, public_to_name.iteritems())}
print "name_to_private"
pp.pprint(name_to_private)
# just find the ones that don't exist
upsert_to_private = dict(filter(lambda (name, ip): ip not in set_of_private_addresses, name_to_private.iteritems()))
print "upsert_to_private"
pp.pprint(upsert_to_private)
@mtbdeano
Copy link
Author

This requires boto, but not much else. Basic logic is:

  1. find matched domain pair (public and private)
  2. get list of elastic IPs
  3. get all A records from both domains
  4. build maps across domains
  5. match the maps
    with name_to_private being the complete list of public DNS names that require private DNS entries and upsert_to_private as the list of names that don't already exist in Route 53 on the private side. Actually updating your domain record is left as an exercise for the reader.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment