예제 #1
0
    def wait_for_change(self, change_id, host):
        _, change_id = change_id
        client = self._find_client_for_domain(host)

        while True:
            response = client.get_change(Id=change_id)
            if response["ChangeInfo"]["Status"] == "INSYNC":
                return
            time.sleep(5)
예제 #2
0
    def wait_for_change(self, change_id, host):
        _, change_id = change_id
        client = self._find_client_for_domain(host)

        while True:
            response = client.get_change(Id=change_id)
            if response["ChangeInfo"]["Status"] == "INSYNC":
                return
            time.sleep(5)
예제 #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"]}'
        )