예제 #1
0
 def _change_txt_record(self, action, zone_id, domain, value):
     client = self._find_client_for_domain(domain)
     response = client.change_resource_record_sets(
         HostedZoneId=zone_id,
         ChangeBatch={
             "Changes": [{
                 "Action": action,
                 "ResourceRecordSet": {
                     "Name":
                     domain,
                     "Type":
                     "TXT",
                     "TTL":
                     DNS_TTL,
                     "ResourceRecords": [
                         # For some reason TXT records need to be
                         # manually quoted.
                         {
                             "Value": '"{}"'.format(value)
                         }
                     ],
                 }
             }]
         })
     return response["ChangeInfo"]["Id"]
예제 #2
0
 def _change_txt_record(self, action, zone_id, domain, value):
     client = self._find_client_for_domain(domain)
     response = client.change_resource_record_sets(
         HostedZoneId=zone_id,
         ChangeBatch={
             "Changes": [
                 {
                     "Action": action,
                     "ResourceRecordSet": {
                         "Name": domain,
                         "Type": "TXT",
                         "TTL": DNS_TTL,
                         "ResourceRecords": [
                             # For some reason TXT records need to be
                             # manually quoted.
                             {"Value": '"{}"'.format(value)}
                         ],
                     }
                 }
             ]
         }
     )
     return response["ChangeInfo"]["Id"]
예제 #3
0
    def update_txt_record_route53(self, domain, challenge, key, access_key_id,
                                  secret_access_key):
        session = boto3.Session(aws_access_key_id=access_key_id,
                                aws_secret_access_key=secret_access_key)
        client = session.client('route53')

        # Finding zone id for the given domain
        paginator = client.get_paginator('list_hosted_zones')
        target_labels = domain.rstrip('.').split('.')
        zones = []
        try:
            for page in paginator.paginate():
                for zone in page['HostedZones']:
                    if zone['Config']['PrivateZone']:
                        continue

                    candidate_labels = zone['Name'].rstrip('.').split('.')
                    if candidate_labels == target_labels[-len(candidate_labels
                                                              ):]:
                        zones.append((zone['Name'], zone['Id']))
            if not zones:
                raise CallError(
                    f'Unable to find a Route53 hosted zone for {domain}')
        except boto_exceptions.ClientError as e:
            raise CallError(
                f'Failed to get Hosted zones with provided credentials :{e}')

        # Order the zones that are suffixes for our desired to domain by
        # length, this puts them in an order like:
        # ["foo.bar.baz.com", "bar.baz.com", "baz.com", "com"]
        # And then we choose the first one, which will be the most specific.
        zones.sort(key=lambda z: len(z[0]), reverse=True)
        zone_id = zones[0][1]

        try:
            resp = client.change_resource_record_sets(
                HostedZoneId=zone_id,
                ChangeBatch={
                    'Changes': [{
                        'Action': 'UPSERT',
                        'ResourceRecordSet': {
                            'Name':
                            challenge.validation_domain_name(domain),
                            'ResourceRecords': [{
                                'Value':
                                f'"{challenge.validation(key)}"'
                            }],
                            'TTL':
                            3600,
                            'Type':
                            'TXT'
                        }
                    }],
                    'Comment':
                    f'{"Free" if self.middleware.call_sync("system.is_freenas") else "True"}'
                    'NAS-dns-route53 certificate validation'
                })
        except boto_BaseClientException as e:
            raise CallError(f'Failed to update record sets : {e}')
        """
        Wait for a change to be propagated to all Route53 DNS servers.
        https://docs.aws.amazon.com/Route53/latest/APIReference/API_GetChange.html
        """
        for unused_n in range(0, 120):
            r = client.get_change(Id=resp['ChangeInfo']['Id'])
            if r['ChangeInfo']['Status'] == 'INSYNC':
                return resp['ChangeInfo']['Id']
            time.sleep(5)

        raise CallError(
            f'Timed out waiting for Route53 change. Current status: {resp["ChangeInfo"]["Status"]}'
        )
예제 #4
0
    def update_txt_record_route53(self, domain, challenge, key, access_key_id, secret_access_key):
        session = boto3.Session(
            aws_access_key_id=access_key_id,
            aws_secret_access_key=secret_access_key
        )
        client = session.client('route53')

        # Finding zone id for the given domain
        paginator = client.get_paginator('list_hosted_zones')
        target_labels = domain.rstrip('.').split('.')
        zones = []
        try:
            for page in paginator.paginate():
                for zone in page['HostedZones']:
                    if zone['Config']['PrivateZone']:
                        continue

                    candidate_labels = zone['Name'].rstrip('.').split('.')
                    if candidate_labels == target_labels[-len(candidate_labels):]:
                        zones.append((zone['Name'], zone['Id']))
            if not zones:
                raise CallError(
                    f'Unable to find a Route53 hosted zone for {domain}'
                )
        except boto_exceptions.ClientError as e:
            raise CallError(
                f'Failed to get Hosted zones with provided credentials :{e}'
            )

        # Order the zones that are suffixes for our desired to domain by
        # length, this puts them in an order like:
        # ["foo.bar.baz.com", "bar.baz.com", "baz.com", "com"]
        # And then we choose the first one, which will be the most specific.
        zones.sort(key=lambda z: len(z[0]), reverse=True)
        zone_id = zones[0][1]

        try:
            resp = client.change_resource_record_sets(
                HostedZoneId=zone_id,
                ChangeBatch={
                    'Changes': [
                        {
                            'Action': 'UPSERT',
                            'ResourceRecordSet': {
                                'Name': challenge.validation_domain_name(domain),
                                'ResourceRecords': [{'Value': f'"{challenge.validation(key)}"'}],
                                'TTL': 3600,
                                'Type': 'TXT'
                            }
                        }
                    ],
                    'Comment': f'{"Free" if self.middleware.call_sync("system.is_freenas") else "True"}'
                               'NAS-dns-route53 certificate validation'
                }
            )
        except boto_BaseClientException as e:
            raise CallError(
                f'Failed to update record sets : {e}'
            )

        """
        Wait for a change to be propagated to all Route53 DNS servers.
        https://docs.aws.amazon.com/Route53/latest/APIReference/API_GetChange.html
        """
        for unused_n in range(0, 120):
            r = client.get_change(Id=resp['ChangeInfo']['Id'])
            if r['ChangeInfo']['Status'] == 'INSYNC':
                return resp['ChangeInfo']['Id']
            time.sleep(5)

        raise CallError(
            f'Timed out waiting for Route53 change. Current status: {resp["ChangeInfo"]["Status"]}'
        )