class Acmesmith::ChallengeResponders::Ns1
Public Class Methods
new(config)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 16 def initialize(config) @config = config @ttl = @config.has_key?(:ttl) ? @config[:ttl] : 3600 @timeout = 2 begin token = @config.fetch(:token) rescue warn "ERROR :: Please verify that you add your NS1 account 'Token' config file." exit 1 end @ns1 = NSOne::Client.new(token) end
Public Instance Methods
cleanup(domain, challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 42 def cleanup(domain, challenge) @zone = find_zone(domain) unless @zone warn "ERROR :: Domain '#{domain}' is not configured in NS1." exit 1 end @fqdn = canonicalize(domain, challenge) delete_rr(challenge) wait_for_sync_by_api(challenge, false) end
respond(domain, challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 29 def respond(domain, challenge) @zone = find_zone(domain) unless @zone warn "ERROR :: Domain '#{domain}' is not configured in NS1." exit 1 end @fqdn = canonicalize(domain, challenge) create_rr(challenge) wait_for_sync_by_api(challenge) wait_for_sync_by_dns(challenge) end
support?(type)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 12 def support?(type) type == 'dns-01' end
Private Instance Methods
canonicalize(domain, challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 159 def canonicalize(domain, challenge) "#{challenge.record_name}.#{domain}.".gsub(/\.{2,}/, '.') end
create_rr(challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 70 def create_rr(challenge) begin data = { "zone" => @zone, "domain" => @fqdn, "type" => challenge.record_type, "answers" => [{"answer" => [challenge.record_content]}], "ttl" => @ttl, } res = @ns1.create_record(@zone, @fqdn, challenge.record_type, data) raise "ERROR :: Failed to create record: #{@fqdn} zone: #{@zone}. msg: #{res["message"]}" if res.has_key?("message") res rescue => e warn "ERROR :: error on create -> #{e}" exit 3 end end
delete_rr(challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 92 def delete_rr(challenge) begin res = @ns1.delete_record(@zone, @fqdn, challenge.record_type) raise "ERROR :: Failed to delete record: #{@fqdn} zone: #{@zone}." if res.has_key?("message") res rescue => e warn "ERROR :: error on delete -> #{e}" exit 3 end end
find_zone(domain)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 167 def find_zone(domain) get_zones.select {|z| domain[z] }.first end
get_rr(challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 56 def get_rr(challenge) begin type = challenge.record_type res = @ns1.record(@zone, @fqdn, type) return res.has_key?("message") && res["message"] == "record not found" ? false : res rescue => e warn "ERROR :: Failed to get record: #{@fqdn}. error: #{e}" exit 3 end end
get_zones()
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 163 def get_zones() @zones ||= @ns1.zones.map {|z| z["zone"]} end
wait_for_sync_by_api(challenge, for_create = true)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 105 def wait_for_sync_by_api(challenge, for_create = true) puts " * API Check :: Checking if record found using NS1 API --> record: #{@fqdn} expected value: #{challenge.record_content}" record = get_rr(challenge) if for_create while !record puts " * Record creation still in process. waiting 3 seconds." sleep 3 record = get_rr(challenge) end puts " * Confirm new record creation using API!" return true else while record puts " * Record deletion still in process. waiting 3 seconds" sleep 3 record = get_rr(challenge) end puts " * Confirm record deletion using API!" return true end # if for_create end
wait_for_sync_by_dns(challenge)
click to toggle source
# File lib/acmesmith/challenge_responders/ns1.rb, line 133 def wait_for_sync_by_dns(challenge) value = challenge.record_content puts " * DNS CHeck :: Checking if record found using DNS query --> record: #{@fqdn} expected value: #{challenge.record_content}" resolv = Resolv::DNS.new() nameservers = resolv.getresources(@zone, Resolv::DNS::Resource::IN::NS).map {|ns| Resolv.getaddresses(ns.name.to_s).first} Resolv::DNS.open(:nameserver => nameservers) do | dns | dns.timeouts = @timeout loop do resolv_value = dns.getresources(@fqdn, Resolv::DNS::Resource::IN::TXT).map(&:data).first if resolv_value == value puts " * Success - Value found and it is as expected. value: #{resolv_value}" sleep 1 break else puts " * Waiting - Value still does not match the expected result. current value: #{resolv_value}" sleep 3 end end # loop end # Resolv::DNS end