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')
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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()
예제 #5
0
 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)
예제 #6
0
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/", ""))
예제 #7
0
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)
예제 #9
0
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
예제 #10
0
 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()
예제 #11
0
    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
예제 #13
0
    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)
예제 #14
0
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,
                             ))
예제 #15
0
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()
예제 #16
0
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
예제 #17
0
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))
예제 #18
0
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
예제 #19
0
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
예제 #20
0
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)
예제 #21
0
    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
예제 #22
0
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)
예제 #23
0
 def test_get_zones(self):
     route53 = Route53Connection()
     route53.get_zones()
예제 #24
0
 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)
예제 #25
0
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>
예제 #26
0
 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)
예제 #27
0
 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')
예제 #28
0
    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)
예제 #29
0
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)
예제 #30
0
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>