Last active
June 16, 2022 04:11
-
-
Save rmarchei/98489c05f0898abe612eec916508f2bf to your computer and use it in GitHub Desktop.
route53 hook for dehydrated - python2 / python3 + boto2 version. Tested on Ubuntu 16.04
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# How to use: | |
# | |
# Ubuntu 16.04: apt install -y python-boto OR apt install -y python3-boto | |
# | |
# Specify the default profile on aws/boto profile files or use the optional AWS_PROFILE env var: | |
# AWS_PROFILE=example ./dehydrated -c -d example.com -t dns-01 -k /etc/dehydrated/hooks/route53.py | |
# | |
# Manually specify hosted zone: | |
# HOSTED_ZONE=example.com AWS_PROFILE=example ./dehydrated -c -d example.com -t dns-01 -k /etc/dehydrated/hooks/route53.py | |
# | |
# More info about dehaydrated and dns challenge: https://github.com/lukas2511/dehydrated/wiki/Examples-for-DNS-01-hooks | |
# Using AWS Profiles: http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-multiple-profiles | |
import os | |
import sys | |
from boto.route53 import * | |
from time import sleep | |
def route53_dns(domain, txt_challenge, action='upsert'): | |
conn = connection.Route53Connection() | |
action = action.upper() | |
if 'HOSTED_ZONE' in os.environ: | |
hosted_zone = os.environ['HOSTED_ZONE'] | |
if not domain.endswith(hosted_zone): | |
raise Exception("Incorrect hosted zone for domain {0}".format(domain)) | |
zone = conn.get_hosted_zone_by_name("{0}.".format(hosted_zone)) | |
zone_id = zone['GetHostedZoneResponse']['HostedZone']['Id'].replace('/hostedzone/', '') | |
else: | |
zones = conn.get_all_hosted_zones() | |
for zone in zones['ListHostedZonesResponse']['HostedZones']: | |
if "{0}.".format(domain).endswith(zone['Name']): | |
zone_id = zone['Id'].replace('/hostedzone/', '') | |
break | |
else: | |
raise Exception("Hosted zone not found for domain {0}".format(domain)) | |
name = u'_acme-challenge.{0}.'.format(domain) | |
record_set = conn.get_all_rrsets(zone_id, name=name, type='TXT') | |
challenges = [u'"{0}"'.format(txt_challenge)] | |
for r in record_set: | |
if r.name == name and r.type == 'TXT': | |
challenges += r.resource_records | |
change_set = record.ResourceRecordSets(conn, zone_id) | |
change = change_set.add_change("{0}".format(action), '_acme-challenge.{0}'.format(domain), type='TXT', ttl=60) | |
for c in set(challenges): | |
change.add_value(c) | |
try: | |
response = change_set.commit() | |
except Exception as e: | |
if action == "DELETE": | |
pass | |
else: | |
print(e.message, e.args) | |
if action in ('CREATE', 'UPSERT'): | |
# wait for DNS update | |
timeout = 300 | |
sleep_time = 5 | |
time_elapsed = 0 | |
st = status.Status(conn, response['ChangeResourceRecordSetsResponse']['ChangeInfo']) | |
while st.update() != 'INSYNC' and time_elapsed <= timeout: | |
print("Waiting for DNS change to complete... (Elapsed {0} seconds)".format(time_elapsed)) | |
sleep(sleep_time) | |
time_elapsed += sleep_time | |
if st.update() != 'INSYNC' and time_elapsed > timeout: | |
raise Exception("Timed out while waiting for DNS record to be ready. Waited {0} seconds".format(time_elapsed)) | |
print("DNS change completed") | |
if __name__ == "__main__": | |
hook = sys.argv[1] | |
if len(sys.argv) > 2: | |
domain = sys.argv[2] | |
txt_challenge = sys.argv[4] | |
else: | |
domain = None | |
txt_challenge = None | |
if hook == "deploy_challenge": | |
action = 'upsert' | |
elif hook == "clean_challenge": | |
action = 'delete' | |
else: | |
sys.exit(0) | |
print("hook: {0}".format(hook)) | |
print("domain: {0}".format(domain)) | |
print("txt_challenge: {0}".format(txt_challenge)) | |
route53_dns(domain, txt_challenge, action) |
@niall-byrne Thanks!!!
Is any of the versions above able to use wildcards? I'm still getting the error but the values provided do not match the current values
as mentioned above (https://gist.github.com/rmarchei/98489c05f0898abe612eec916508f2bf#gistcomment-2594451).
I've written a fork of this gist to:
- Implement wildcard support
- Allow
HOOK_CHAIN="yes"
for much faster batch confirmation (only need to wait for DNS propagation once, not once per domain)
https://gist.github.com/nh2/f744ac591e95f0c25b501db00cf7c71a
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The indentation in the above code seems to be off, this worked for me: