From b0803b02a59e2a695597ef25f980a9de570c17a3 Mon Sep 17 00:00:00 2001 From: Brian Hechinger Date: Thu, 2 Nov 2017 10:19:41 -0400 Subject: [PATCH] Adding the Route53 dns script and some docs. --- dns_scripts/DNS_ROUTE53.md | 10 +++++ dns_scripts/dns_route53.py | 87 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 dns_scripts/DNS_ROUTE53.md create mode 100755 dns_scripts/dns_route53.py diff --git a/dns_scripts/DNS_ROUTE53.md b/dns_scripts/DNS_ROUTE53.md new file mode 100644 index 0000000..30ee075 --- /dev/null +++ b/dns_scripts/DNS_ROUTE53.md @@ -0,0 +1,10 @@ +# Do DNS-01 verification using Route53 + +I was not about to implement this in BASH, sorry guys. I'd like you to have it, however. + +It's pretty simple to use. + +1. pip install boto3 dnspython +2. ln -s dns_route53.py dns_add_route53 +3. ln -s dns_route53.py dns_del_route53 +4. Use it just like the other scripts diff --git a/dns_scripts/dns_route53.py b/dns_scripts/dns_route53.py new file mode 100755 index 0000000..8805269 --- /dev/null +++ b/dns_scripts/dns_route53.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +import boto3, sys, time +from os.path import basename +import dns.resolver + +client = boto3.client('route53') + +name = sys.argv[0] +fqdn = sys.argv[1] +challenge = sys.argv[2] + +bname = basename(name) +if bname == 'dns_add_route53': + action = 'UPSERT' +elif bname == 'dns_del_route53': + action = 'DELETE' +else: + print("No such action: {a}".format(a=bname)) + sys.exit(1) + +try: + response = client.list_hosted_zones() +except Exception as e: + print("Oops: {e!r}".format(e=e)) + sys.exit(1) + +zone_id = "" +zone_list = dict() +for zone in response['HostedZones']: + if not zone['Config']['PrivateZone']: + zone_list[zone['Name']] = zone['Id'] + +for key in sorted(zone_list.iterkeys(), key=len, reverse=True): + if key in "{z}.".format(z=fqdn): + zone_id = zone_list[key] + +if zone_id == "": + print("We didn't find the zone") + sys.exit(1) + +challenge_fqdn = "_acme-challenge.{f}".format(f=fqdn) +try: + response = client.change_resource_record_sets( + HostedZoneId=zone_id, + ChangeBatch={ + 'Comment': 'getssl/Letsencrypt verification', + 'Changes': [ + { + 'Action': action, + 'ResourceRecordSet': { + 'Name': challenge_fqdn, + 'Type': 'TXT', + 'TTL': 300, + 'ResourceRecords': [{'Value': "\"{c}\"".format(c=challenge)}] + } + }, + ] + } + ) +except Exception as e: + print("Oops: {e!r}".format(e=e)) + sys.exit(1) + +waiting = 0 +if action == 'UPSERT': + # Wait until we see the record before returning. The ACME server's timeout is too short. + # But only if we're adding the record. Don't care how long it takes to delete. + while (True): + try: + my_resolver = dns.resolver.Resolver(configure=False) + my_resolver.nameservers = ['8.8.8.8', '8.8.4.4'] + results = my_resolver.query(challenge_fqdn, 'TXT') + data = str(results.response.answer[0][0]).strip('\"') + if data == challenge: + print("found {f} entry".format(f=challenge_fqdn)) + else: + print("found {f} entry but it has bad data: {d}".format(f=challenge_fqdn, + d=data)) + break + + except dns.resolver.NXDOMAIN: + waiting += 10 + print("Didn't find {f} entry yet, sleeping... ({w}s)".format(f=challenge_fqdn, + w=waiting)) + time.sleep(10) + pass \ No newline at end of file