class Acmesmith::AuthorizationService
Constants
- AuthorizationProcess
@!attribute [r] domain
@return [String] domain name
@!attribute [r] authorization
@return [Acme::Client::Resources::Authorization] authz object
@!attribute [r] challenge_responder
@return [Acmesmith::ChallengeResponders::Base] responder
@!attribute [r] challenge
@return [Acme::Client::Resources::Challenges::Base] challenge
Attributes
challenge_responder_rules[R]
Public Class Methods
new(challenge_responder_rules, authorizations)
click to toggle source
@param challenge_responder_rules
[Array<Acmemith::Config::ChallengeReponderRule>] @param authorizations [Array<Acme::Client::Resources::Authorization>]
# File lib/acmesmith/authorization_service.rb, line 34 def initialize(challenge_responder_rules, authorizations) @challenge_responder_rules = challenge_responder_rules @authorizations = authorizations end
Public Instance Methods
cleanup()
click to toggle source
# File lib/acmesmith/authorization_service.rb, line 142 def cleanup processes_by_responder.each do |responder, ps| puts "=> Cleaning the responses the challenges for the following identifier:" puts puts " * Responder: #{responder.class}" puts " * Identifiers:" ps.each do |process| puts " - #{process.domain} (#{process.challenge.challenge_type})" end puts responder.cleanup_all(*ps.map{ |t| [t.domain, t.challenge] }) end end
perform!()
click to toggle source
# File lib/acmesmith/authorization_service.rb, line 41 def perform! return if authorizations.empty? respond() request_validation() wait_for_validation() cleanup() puts "=> Authorized!" end
processes()
click to toggle source
@return [Array<AuthorizationProcess>]
# File lib/acmesmith/authorization_service.rb, line 158 def processes @processes ||= authorizations.map do |authz| challenge = nil responder_rule = challenge_responder_rules.select do |rule| rule.filter.applicable?(authz.domain) end.find do |rule| challenge = authz.challenges.find do |c| # OMG, acme-client might return a Hash instead of Acme::Client::Resources::Challenge::* object... challenge_type = case when c.is_a?(Hash) c[:challenge_type] when c.is_a?(Acme::Client::Resources::Challenges::Unsupported) next when c.respond_to?(:challenge_type) c.challenge_type end rule.challenge_responder.support?(challenge_type) end end unless responder_rule raise NoApplicableChallengeResponder, "Cannot find a challenge responder for domain #{authz.domain.inspect}" end AuthorizationProcess.new( domain: authz.domain, authorization: authz, challenge_responder: responder_rule.challenge_responder, challenge: challenge, ) end end
processes_by_responder()
click to toggle source
@return [Array<(Acmesmith::ChallengeResponders::Base
, Array<AuthorizationProcess>)>]
# File lib/acmesmith/authorization_service.rb, line 192 def processes_by_responder @processes_by_responder ||= processes.group_by(&:responder_id).map { |_, ps| [ps[0].challenge_responder, ps] } end
request_validation()
click to toggle source
# File lib/acmesmith/authorization_service.rb, line 68 def request_validation puts "=> Requesting validations..." puts processes.each do |process| challenge = process.challenge print " * #{process.domain} (#{challenge.challenge_type}) ..." retried = false begin challenge.request_validation() puts " [ ok ]" rescue Acme::Client::Error::Malformed # Rescue in case of requesting validation for a challenge which has already determined valid (asynchronously while we're receiving it). # LE Boulder doesn't take this as an error, but pebble do. # https://github.com/letsencrypt/boulder/blob/ebba443cad233111ee2b769ef09b32a13c3ba57e/wfe2/wfe.go#L1235 # https://github.com/letsencrypt/pebble/blob/b60b0b677c280ccbf63de55a26775591935c448b/wfe/wfe.go#L2166 challenge.reload if process.valid? puts " [ ok ] (turned valid in background)" next end if retried raise else retried = true retry end end end puts end
respond()
click to toggle source
# File lib/acmesmith/authorization_service.rb, line 52 def respond processes_by_responder.each do |responder, ps| puts "=> Responsing to the challenges for the following identifier:" puts puts " * Responder: #{responder.class}" puts " * Identifiers:" ps.each do |process| puts " - #{process.domain} (#{process.challenge.challenge_type})" end puts responder.respond_all(*ps.map{ |t| [t.domain, t.challenge] }) end end
wait_for_validation()
click to toggle source
# File lib/acmesmith/authorization_service.rb, line 101 def wait_for_validation puts "=> Waiting for the validation..." puts loop do processes.each do |process| next if process.valid? process.challenge.reload status = process.challenge.status puts " * [#{process.domain}] status: #{status}" case when process.valid? next when process.invalid? err = process[:challenge].error puts " ! [#{process[:domain]}] error: #{err.inspect}" end end break if processes.all?(&:completed?) sleep 3 end puts invalid_processes = processes.select(&:invalid?) unless invalid_processes.empty? $stderr.puts "" $stderr.puts "!! Some identitiers failed to challenge" $stderr.puts "" invalid_processes.each do |process| $stderr.puts " - #{process.domain}: #{process.challenge.error.inspect}" end $stderr.puts "" raise AuthorizationFailed, "Some identifiers failed to challenge: #{invalid_processes.map(&:domain).inspect}" end end