Class: Bullion::ChallengeClients::DNS

Inherits:
Bullion::ChallengeClient show all
Defined in:
lib/bullion/challenge_clients/dns.rb

Overview

ACME DNS01 Challenge Client

Direct Known Subclasses

RSpec::ChallengeClients::DNS

Constant Summary

Constants inherited from Bullion::ChallengeClient

Bullion::ChallengeClient::ChallengeClientMetric

Instance Attribute Summary

Attributes inherited from Bullion::ChallengeClient

#challenge

Instance Method Summary collapse

Methods inherited from Bullion::ChallengeClient

#attempt, #identifier, #initialize

Constructor Details

This class inherits a constructor from Bullion::ChallengeClient

Instance Method Details

#digest_value(string) ⇒ Object



19
20
21
22
23
24
# File 'lib/bullion/challenge_clients/dns.rb', line 19

def digest_value(string)
  digester = OpenSSL::Digest.new("SHA256")
  digest   = digester.digest(string)
  # clean up the digest output so it can match the provided challenge value
  Base64.urlsafe_encode64(digest).sub(/[\s=]*\z/, "")
end

#dns_nameObject



26
27
28
# File 'lib/bullion/challenge_clients/dns.rb', line 26

def dns_name
  "_acme-challenge.#{identifier}"
end

#dns_valueObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/bullion/challenge_clients/dns.rb', line 30

def dns_value
  # Randomly select a nameserver to pull the TXT record
  nameserver = NAMESERVERS.sample

  LOGGER.debug "Looking up #{dns_name}"
  records = records_for(dns_name, nameserver)
  raise "Failed to find records for #{dns_name}" unless records

  record = records.map(&:strings).flatten.first
  LOGGER.debug "Resolved #{dns_name} to value #{record}"
  record
rescue StandardError => e
  msg = ["Resolution error '#{e.message}' for #{dns_name}"]
  msg << "via #{nameserver}" if nameserver
  LOGGER.info msg.join(" ")
  false
end

#performObject



12
13
14
15
16
17
# File 'lib/bullion/challenge_clients/dns.rb', line 12

def perform
  value = dns_value
  expected_value = digest_value("#{challenge.token}.#{challenge.thumbprint}")

  value == expected_value
end

#records_for(name, nameserver = nil) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/bullion/challenge_clients/dns.rb', line 48

def records_for(name, nameserver = nil)
  if nameserver
    Resolv::DNS.open(nameserver:) do |dns|
      dns.getresources(name, Resolv::DNS::Resource::IN::TXT)
    end
  else
    Resolv::DNS.open do |dns|
      dns.getresources(name, Resolv::DNS::Resource::IN::TXT)
    end
  end
end

#typeObject



8
9
10
# File 'lib/bullion/challenge_clients/dns.rb', line 8

def type
  "DNS01"
end