def setUp(self): super(TestRoute53AliasResourceRecordSets, self).setUp() self.conn = Route53Connection() self.base_domain = 'boto-test-%s.com' % str(int(time.time())) self.zone = self.conn.create_zone(self.base_domain) # a standard record to use as the target for our alias self.zone.add_a('target.%s' % self.base_domain, '102.11.23.1')
def main(): args = options() route53_ips = get_route53(args) ec2_ips = get_ec2(args) report_ips = {} conn = Route53Connection() changes = ResourceRecordSets(conn, args.zoneid) print 'Following records will be deleted.' for name, ip in route53_ips.items(): match = 0 for ec2_id in ec2_ips: if ip in ec2_ips[ec2_id].values(): match = 1 if match == 0: report_ips[name] = ip for name, ip in sorted(report_ips.items()): if re.match('[\d\.]+', ip): print "A;%s;%s" % (ip, name) change = changes.add_change("DELETE", str(name), "A", 300) change.add_value(ip) else: print "CNAME;%s;%s" % (ip, name) changes.commit() print 'Deleted records: ' pprint.pprint(changes)
def check_if_zone_exists(domain, **kwargs): # For Route53 domain should end with dot domain = _make_qualified(domain) conn = Route53Connection(kwargs['id'], kwargs['secret']) zone = conn.get_zone(domain) return bool(zone)
def set_cname(cname, name): hostname, domain = cname.split('.', 1) conn = Route53Connection() zone = conn.get_hosted_zone_by_name(domain) if zone is None: raise ValueError('Invalid CNAME: {0}'.format(cname)) if not cname.endswith('.'): cname += '.' records = conn.get_all_rrsets(hosted_zone_id=zone.Id.split('/')[-1]) # Remove old CNAMEs if they exist old_cnames = [r for r in records if r.name == cname and r.type == 'CNAME'] for old in old_cnames: change = records.add_change(action='DELETE', name=old.name, type=old.type) change.__dict__.update(old.__dict__) # Add current CNAME change = records.add_change(action='CREATE', name=cname, type='CNAME', ttl=60) change.add_value(name) records.commit()
def setUpClass(self): route53 = Route53Connection() self.base_domain = 'boto-test-%s.com' % str(int(time.time())) zone = route53.get_zone(self.base_domain) if zone is not None: zone.delete() self.zone = route53.create_zone(self.base_domain)
def update_route53(): route53 = Route53Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) rr = route53.get_all_rrsets(ZONEID) oldips = [] for r in rr: #print r.name if r.name == DDNSNAME: oldips += r.resource_records deletechanges = "" newip = wtf_myip() if oldips == [newip]: #No need to update!!! syslog("Record in route53 matches current ip") else: for ip in oldips: deletechanges += """ <Change> <Action>DELETE</Action> <ResourceRecordSet> <Name>%s</Name> <Type>A</Type> <TTL>60</TTL> <ResourceRecords> <ResourceRecord> <Value>%s</Value> </ResourceRecord> </ResourceRecords> </ResourceRecordSet> </Change> """ % (DDNSNAME, ip) #print deletechanges xml = """<?xml version="1.0" encoding="UTF-8"?> <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2011-05-05/"> <ChangeBatch> <Comment>Add record</Comment> <Changes> %s <Change> <Action>CREATE</Action> <ResourceRecordSet> <Name>%s</Name> <Type>A</Type> <TTL>60</TTL> <ResourceRecords> <ResourceRecord> <Value>%s</Value> </ResourceRecord> </ResourceRecords> </ResourceRecordSet> </Change> </Changes> </ChangeBatch> </ChangeResourceRecordSetsRequest>""" % (deletechanges, DDNSNAME, newip) #print xml c = route53.change_rrsets(ZONEID, xml) syslog( c["ChangeResourceRecordSetsResponse"]["ChangeInfo"]["Id"].replace( "/change/", ""))
def get_route53_connection(args): params = {} if args.aws_access_key_id: params["aws_access_key_id"] = args.aws_access_key_id if args.aws_secret_access_key: params["aws_secret_access_key"] = args.aws_secret_access_key return Route53Connection(**params)
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)
def get_connection(): global CONNECTION if CONNECTION is None: keys = ['aws_access_key_id', 'aws_secret_access_key'] ckwargs = {} for key in keys: ckwargs[key] = OPTS[key] if None in ckwargs.values(): ckwargs.clear() CONNECTION = Route53Connection(**ckwargs) return CONNECTION
def setUpClass(self): time_str = str(int(time.time())) self.route53 = Route53Connection() self.base_domain = 'boto-private-zone-test-%s.com' % time_str self.vpc = VPCConnection() self.test_vpc = self.vpc.create_vpc(cidr_block='10.11.0.0/16') # tag the vpc to make it easily identifiable if things go spang self.test_vpc.add_tag("Name", self.base_domain) self.zone = self.route53.get_zone(self.base_domain) if self.zone is not None: self.zone.delete()
def __init__(self, accessKey, secretKey, domain): self.domain = domain self.accessKey = accessKey self.secretKey = secretKey self.connection = Route53Connection( aws_access_key_id=accessKey, aws_secret_access_key=secretKey, ) self._cache = {}
def getAWSRoute53data(awsHOSTEDZoneID): dnsREMOTEDict = {} try: route53 = Route53Connection() sets = route53.get_all_rrsets(awsHOSTEDZoneID) except (socket.error, DNSServerError) as e: notify("Unable to get resource record data from Route53", e) sys.exit(1) for rset in sets: d = dnsREMOTEDict.setdefault(str(rset.type), {}) for rcd in rset.resource_records: e = d.setdefault(str(rset.name), []) d[str(rset.name)].append(str(rcd)) return dnsREMOTEDict
def route53_connection(self): """(:class:`boto.route53.connection.Route53Connection`) The Route 53 connection. """ ec2 = self.ec2_connection return Route53Connection( aws_access_key_id=ec2.provider.access_key, aws_secret_access_key=ec2.provider.secret_key, port=ec2.port, proxy=ec2.proxy, proxy_port=ec2.proxy_port, debug=ec2.debug, security_token=ec2.provider.security_token, validate_certs=ec2.https_validate_certificates)
def create_or_update_type_CNAME_record(domain, target, **kwargs): """ Create or update CNAME record for domain :param str domain: domain to add :param list target: CNAME target to point the domain to :param dict kwargs: additional params such as id and secret for access to AWS ROUTE 53 :return: """ domain = _make_qualified(domain) main_domain = domain.split('.', 1)[-1] conn = Route53Connection(kwargs['id'], kwargs['secret']) zone = conn.get_zone(main_domain) if zone is None: raise ValueError('Zone for domain {} not found. ' 'Need to configure the zone'.format(domain)) record = zone.get_cname(domain) if record is None: zone.add_cname(domain, target) current_app.logger.debug( 'Create new record CNAME in zone "{zone}" with ' '"{domain}" and target "{target}"'.format( zone=zone.name, domain=domain, target=target, )) return if target == record.resource_records: current_app.logger.debug('CNAME record for "{domain}" with ' 'to "{target}" in zone "{zone}" ' 'already exists'.format(zone=zone.name, target=target, domain=domain)) return zone.update_cname(domain, target) current_app.logger.debug('Updated CNAME record in zone "{zone}" with ' 'domain "{domain}" and target "{target}"'.format( zone=zone.name, domain=domain, target=target, ))
def setHostCname(domain, hostname, hostIp): hostFqn = hostname + '.' + domain + '.' print domain, hostname, hostFqn conn = Route53Connection() zone = conn.get_hosted_zone_by_name(domain) if zone is None: raise ValueError('Invalid CNAME: {0}'.format(domain)) records = conn.get_all_rrsets(hosted_zone_id=zone.Id.split('/')[-1]) # Add current CNAME change = records.add_change(action='UPSERT', name=hostFqn, type='A', ttl=60) change.add_value(hostIp) records.commit()
def get_route53(args): route53_ips = {} conn = Route53Connection() try: conn.get_hosted_zone(args.zoneid) except DNSServerError: print "%s zone not found" % args.zoneid sys.exit(1) print "Retrieving Route53 records..." records = conn.get_all_rrsets(args.zoneid) for record in records: if record.type == 'A': route53_ips[record.name] = record.resource_records[0] elif (record.type == 'CNAME' and (record.resource_records[0].endswith('.compute.amazonaws.com') or record.resource_records[0].endswith('.internal'))): route53_ips[record.name] = record.resource_records[0] return route53_ips
def create_or_update_type_A_record(domain, new_ips, **kwargs): """ Create or update A record for domain :param str domain: domain to add :param list new_ips: IP addresses of load balancer :param dict kwargs: additional params such as id and secret for access to AWS ROUTE 53 :return: """ domain = _make_qualified(domain) main_domain = domain.split('.', 1)[-1] conn = Route53Connection(kwargs['id'], kwargs['secret']) zone = conn.get_zone(main_domain) if zone is None: raise ValueError('Zone for domain {} not found. ' 'Need to configure the zone'.format(domain)) record = zone.get_a(domain) if record is None: zone.add_a(domain, new_ips) current_app.logger.debug('Create new record in zone "{zone}" with ' '"{domain}" and ip "{ips}"'.format( zone=zone.name, domain=domain, ips=new_ips)) else: if set(new_ips) != set(record.resource_records): zone.update_a(domain, new_ips) current_app.logger.debug('Replace record in zone "{zone}" with ' 'domain "{domain}" and ip "{ips}"'.format( zone=zone.name, domain=domain, ips=new_ips)) else: current_app.logger.debug('Domain "{domain}" with ' 'ip "{ips}" in zone "{zone}" ' 'already exists'.format(zone=zone.name, domain=domain, ips=new_ips))
def r53_connect(region=None, *args, **kwargs): """Helper to connect to Amazon Web Services Route53, using identify provided by environment, as also optional region in arguments. .. note:: The region parameter is allowed, but do nothing, still here for future API compatibility and orthogonality between templates. """ if not os_environ.get("AWS_ACCESS_KEY_ID", None): raise Route53TemplateError( "Environment variable AWS_ACCESS_KEY_ID is not set.") if not os_environ.get("AWS_SECRET_ACCESS_KEY", None): raise Route53TemplateError( "Environment variable AWS_SECRET_ACCESS_KEY is not set.") connection = Route53Connection(os_environ.get("AWS_ACCESS_KEY_ID"), os_environ.get("AWS_SECRET_ACCESS_KEY"), *args, **kwargs) return connection
def get_route53(args): route53_ips = {} conn = Route53Connection() try: conn.get_hosted_zone(args.zoneid) except DNSServerError: print "%s zone not found" % args.zoneid sys.exit(1) #zonename = conn.get_hosted_zone(args.zoneid) #domain = zonename['GetHostedZoneResponse']['HostedZone']['Name'] print "Retrieving Route53 records..." records = conn.get_all_rrsets(args.zoneid) for record in records: if record.type == 'A': route53_ips[record.name] = record.resource_records[0] return route53_ips
def lambda_handler(event, context): conn = Route53Connection() zones = conn.get_all_hosted_zones() for zone in zones['ListHostedZonesResponse']['HostedZones']: zone_id = zone['Id'].replace('/hostedzone/', '') args = CommandArgs(zone_id, 'eu-central-1') option = options() print "Working with %s" % zone_id route53_ips = get_route53(args) ec2_ips = get_ec2(args) report_ips = {} changes = ResourceRecordSets(conn, args.zoneid) print 'Following records will be deleted: ' for name, ip in route53_ips.items(): match = 0 for ec2_id in ec2_ips: if ip in ec2_ips[ec2_id].values(): match = 1 if match == 0: report_ips[name] = ip print report_ips.items() if len(report_ips) != 0: for name, ip in sorted(report_ips.items()): if re.match('[\d\.]+', ip): print "A;%s;%s" % (ip, name) change = changes.add_change("DELETE", str(name), "A", 60) change.add_value(ip) else: print "CNAME;%s;%s" % (ip, name) if not option.dry: print 'Deleting records...' changes.commit() pprint.pprint(changes)
def run(self, cmd, hosted_zone_name=None, name=None, alias_dns_name=None, payload=None, config=None): try: if payload: name_prefix = payload['labels']['name_prefix'] alias_dns_name = payload['labels']['alias_dns_name'] hosted_zone_name = payload['labels']['hosted_zone_name'] name = name_prefix + '.' + hosted_zone_name except: self.logger.exception( 'Cannot validate kubernetes payload request for route53 alias!' ) raise try: conn = Route53Connection() zone = conn.get_hosted_zone_by_name(hosted_zone_name) hosted_zone_id = zone.Id.split("/")[2] changes = ResourceRecordSets(conn, hosted_zone_id) change = changes.add_change(cmd, name, "A", alias_hosted_zone_id=hosted_zone_id, alias_dns_name=alias_dns_name, alias_evaluate_target_health=False) result = changes.commit() except Exception as err: sys.stderr.write('ERROR: %s\n' % str(err)) raise
def delete_type_CNAME_record(domain, **kwargs): """ Delete CNAME record for domain :param domain: domain to delete :param dict kwargs: additional params such as id and secret for access to AWS ROUTE 53 :return: None """ domain = _make_qualified(domain) main_domain = domain.split('.', 1)[-1] conn = Route53Connection(kwargs['id'], kwargs['secret']) zone = conn.get_zone(main_domain) if zone is None: return record = zone.get_cname(domain) if record is None: return zone.delete_cname(domain, all=False)
def test_get_zones(self): route53 = Route53Connection() route53.get_zones()
def setUp(self): super(Route53TestCase, self).setUp() self.conn = Route53Connection() self.base_domain = 'boto-test-%s.com' % str(int(time.time())) self.zone = self.conn.create_zone(self.base_domain)
from boto.route53.connection import Route53Connection # your amazon keys key = "" access = "" if __name__ == '__main__': zones = {} route53 = Route53Connection(key, access) # create a new zone response = route53.create_hosted_zone('example.com') # list existing hosted zones results = route53.get_all_hosted_zones() for zone in results['ListHostedZonesResponse']['HostedZones']: print "========================================" print zone['Name'] print "\t%s" % zone['Id'] zone_id = zone['Id'].replace('/hostedzone/', '') zones[zone['Name']] = zone_id sets = route53.get_all_rrsets(zone_id) for rset in sets: print "\t%s: %s %s @ %s" % (rset.name, rset.type, rset.resource_records, rset.ttl) # add an A record xml = """<?xml version="1.0" encoding="UTF-8"?> <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2010-10-01/"> <ChangeBatch> <Comment>Add record</Comment>
def test_route_53_expiration(self): c = Route53Connection() self.assert_is_expired(c, ROUTE_53_EXPIRED, status=403) self.assert_is_not_expired(c, GENERIC_BAD_REQUEST, status=403)
def setUpClass(self): route53 = Route53Connection() zone = route53.get_zone('example.com') if zone is not None: zone.delete() self.zone = route53.create_zone('example.com')
def __init__(self, addr, domain, route53, replicas, debug): self.ipconverter = '.ipaddr.'+domain+'.' try: if domain.find('.') > 0: self.mydomain = dns.name.Name((domain+'.').split('.')) else: self.mydomain = domain self.mysrvdomain = dns.name.Name((SRVNAME+domain+'.').split('.')) except dns.name.EmptyLabel as e: print "A DNS name is required. Use -n option." raise e # Replicas of the Replica self.replicas = replicas self.debug = debug self.route53 = route53 if self.route53: try: from boto.route53.connection import Route53Connection from boto.route53.exception import DNSServerError except Exception as e: print "To use Amazon Route 53, install boto: http://github.com/boto/boto/" raise e # Check if AWS CONFIG data is present ROUTE53CONFIGFILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'route53.cfg') # Touching the CONFIG file with open(ROUTE53CONFIGFILE, 'a'): os.utime(ROUTE53CONFIGFILE, None) import ConfigParser config = ConfigParser.RawConfigParser() config.read(ROUTE53CONFIGFILE) try: AWS_ACCESS_KEY_ID = config.get('ENVIRONMENT', 'AWS_ACCESS_KEY_ID') AWS_SECRET_ACCESS_KEY = config.get('ENVIRONMENT', 'AWS_SECRET_ACCESS_KEY') except Exception as e: print "To use Route53 set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as follows:" print "$ concoord route53id [AWS_ACCESS_KEY_ID]" print "$ concoord route53key [AWS_SECRET_ACCESS_KEY]" sys.exit(1) # initialize Route 53 connection self.route53_name = domain+'.' self.route53_conn = Route53Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) # get the zone_id for the domainname, the domainname # should be added to the zones beforehand self.route53_zone_id = self.get_zone_id(self.route53_conn, self.route53_name) self.updateroute53() else: # STANDALONE NAMESERVER self.addr = addr if addr else findOwnIP() self.udpport = 53 self.udpsocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) try: self.udpsocket.bind((self.addr,self.udpport)) print "Connected to " + self.addr + ":" + str(self.udpport) except socket.error as e: print "Can't bind to UDP port 53: %s" % str(e) raise e # When the nameserver starts the revision number is 00 for that day self.revision = strftime("%Y%m%d", gmtime())+str(0).zfill(2)
from boto.route53.connection import Route53Connection initialcommit = False repo_dir = "./zones" if not os.path.exists(repo_dir): repo = git.Repo.init(repo_dir) shutil.copyfile("git-commit-notifier.post-commit.hook", os.path.join(repo_dir, ".git/hooks/post-commit")) os.chmod(os.path.join(repo_dir, ".git/hooks/post-commit"), 755) initialcommit = True else: repo = git.Repo(repo_dir) os.chdir(repo_dir) c = Route53Connection() for zone in c.get_zones(): zonefilename = zone.name + "xml" with open(zonefilename, 'w') as route53zonefile: for record in zone.get_records(): route53zonefile.write(record.to_xml() + "\n\n") route53zonefile.closed repo.index.add([zonefilename]) if not initialcommit: if repo.index.diff('HEAD'): commitmessage = "added or modified:" for diffmember in repo.index.diff('HEAD'): commitmessage += " {}".format(diffmember.b_path) repo.index.commit(commitmessage)
import os import socket import boto from boto.route53.connection import Route53Connection import re import sys master_ip = socket.gethostbyname(socket.gethostname()) if __name__ == '__main__': domain = sys.argv[1] R53_KEY = sys.argv[2] R53_SECRET = sys.argv[3] r53 = Route53Connection(R53_KEY, R53_SECRET) all_zones = r53.get_all_hosted_zones() dev_next = [ i for i in all_zones.HostedZones if i.Name == '%s' % domain] dn_id = dev_next[0].Id.replace('/hostedzone/','') all_rsets = r53.get_all_rrsets(dn_id) xml_add = """<?xml version="1.0" encoding="UTF-8"?> <ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/2012-02-29/"> <ChangeBatch> <Comment>API call from newly spawned salt-master to register new internal IP to domain for minions</Comment> <Changes> <Change> <Action>CREATE</Action>