-
-
Save joshgarnett/02920846fea35f738d3370fd991bb0e0 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby | |
require 'aws-sdk' | |
# | |
# This script requires you to have the following environment variables set: | |
# AWS_REGION="us-west-2" | |
# AWS_ACCESS_KEY_ID="<YOUR_KEY>" | |
# AWS_SECRET_ACCESS_KEY="<YOUR_SECRET_KEY>" | |
# | |
# Based on https://gist.github.com/asimihsan/d8d8f0f10bdc85fc6f8a | |
# | |
def find_hosted_zone(route53, domain) | |
route53 = Aws::Route53::Client.new | |
hosted_zones = route53.list_hosted_zones_by_name.hosted_zones | |
index = hosted_zones.index { |zone| domain.end_with?(zone.name.chop) } | |
if index.nil? | |
puts 'Unable to find matching zone.' | |
exit 1 | |
end | |
hosted_zones[index] | |
end | |
def wait_for_change(route53, change_id) | |
status = '' | |
until status == 'INSYNC' | |
resp = route53.get_change(id: change_id) | |
status = resp.change_info.status | |
if status != 'INSYNC' | |
puts 'Waiting for dns change to complete' | |
sleep 5 | |
end | |
end | |
end | |
def setup_dns(domain, txt_challenge) | |
route53 = Aws::Route53::Client.new | |
hosted_zone = find_hosted_zone(route53, domain) | |
changes = [] | |
changes << { | |
action: 'UPSERT', | |
resource_record_set: { | |
name: "_acme-challenge.#{domain}.", | |
type: 'TXT', | |
ttl: 60, | |
resource_records: [ | |
value: "\"#{txt_challenge}\"" | |
] | |
} | |
} | |
resp = route53.change_resource_record_sets( | |
hosted_zone_id: hosted_zone.id, | |
change_batch: { | |
changes: changes | |
} | |
) | |
wait_for_change(route53, resp.change_info.id) | |
end | |
def delete_dns(domain, txt_challenge) | |
route53 = Aws::Route53::Client.new | |
hosted_zone = find_hosted_zone(route53, domain) | |
changes = [] | |
changes << { | |
action: 'DELETE', | |
resource_record_set: { | |
name: "_acme-challenge.#{domain}.", | |
type: 'TXT', | |
ttl: 60, | |
resource_records: [ | |
value: "\"#{txt_challenge}\"" | |
] | |
} | |
} | |
resp = route53.change_resource_record_sets( | |
hosted_zone_id: hosted_zone.id, | |
change_batch: { | |
changes: changes | |
} | |
) | |
wait_for_change(route53, resp.change_info.id) | |
end | |
if __FILE__ == $PROGRAM_NAME | |
hook_stage = ARGV[0] | |
domain = ARGV[1] | |
txt_challenge = ARGV[3] | |
puts "stage: #{hook_stage} domain: #{domain} txt_challenge: #{txt_challenge}" | |
if hook_stage == 'deploy_challenge' | |
setup_dns(domain, txt_challenge) | |
elsif hook_stage == 'clean_challenge' | |
delete_dns(domain, txt_challenge) | |
end | |
end |
I found that this script has problems when you have sub domain zones in AWS. Eg.
- example.com
- sub.example.com
index = hosted_zones.index { |zone| domain.end_with?(zone.name.chop) }
This will cause the script to create the challenge TXT record in the example.com zone but a DNS query will try to find it in the subdomain zone. To work around this I changed the comparison to the other way around. Instead of checking if the domain ends with the zone name I check if the zone name ends with the domain latter part:
index = hosted_zones.index { |zone| zone.name.chop.end_with?(domain.split(".",2)[1]) }
Something to consider!
@reinhard-brandstaedter what I did to fix the same issue:
index = hosted_zones.rindex { |zone| domain.end_with?(zone.name.chop) }
It will then use the "earliest match"
@cbergmann have a look at my fork: https://gist.github.com/oveaurs/68c32500c0f5a2a4507f051adf439673