Class: Acmesmith::OrderingService

Inherits:
Object
  • Object
show all
Defined in:
lib/acmesmith/ordering_service.rb

Defined Under Namespace

Classes: NotCompleted

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(acme:, common_name:, identifiers:, private_key:, challenge_responder_rules:, chain_preferences:, profile_rules: [], not_before: nil, not_after: nil) ⇒ OrderingService

Returns a new instance of OrderingService.

Parameters:

  • ACME client

  • Common Name for a ordering certificate

  • Array of domain names for a ordering certificate. common_name has to be explicitly included in this argument.

  • Private key

  • responders

  • chain_preferences

  • (defaults to: nil)
  • (defaults to: nil)


17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/acmesmith/ordering_service.rb', line 17

def initialize(acme:, common_name:, identifiers:, private_key:, challenge_responder_rules:, chain_preferences:, profile_rules: [], not_before: nil, not_after: nil)
  @acme = acme
  @common_name = common_name
  @identifiers = identifiers
  @private_key = private_key
  @challenge_responder_rules = challenge_responder_rules
  @chain_preferences = chain_preferences
  @profile_rules = profile_rules
  @not_before = not_before
  @not_after = not_after

  @order_url = nil # https://github.com/unixcharles/acme-client/pull/263
end

Instance Attribute Details

#acmeObject (readonly)

Returns the value of attribute acme.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def acme
  @acme
end

#chain_preferencesObject (readonly)

Returns the value of attribute chain_preferences.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def chain_preferences
  @chain_preferences
end

#challenge_responder_rulesObject (readonly)

Returns the value of attribute challenge_responder_rules.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def challenge_responder_rules
  @challenge_responder_rules
end

#common_nameObject (readonly)

Returns the value of attribute common_name.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def common_name
  @common_name
end

#identifiersObject (readonly)

Returns the value of attribute identifiers.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def identifiers
  @identifiers
end

#not_afterObject (readonly)

Returns the value of attribute not_after.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def not_after
  @not_after
end

#not_beforeObject (readonly)

Returns the value of attribute not_before.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def not_before
  @not_before
end

#private_keyObject (readonly)

Returns the value of attribute private_key.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def private_key
  @private_key
end

#profile_rulesObject (readonly)

Returns the value of attribute profile_rules.



31
32
33
# File 'lib/acmesmith/ordering_service.rb', line 31

def profile_rules
  @profile_rules
end

Instance Method Details

#certificateObject



106
107
108
# File 'lib/acmesmith/ordering_service.rb', line 106

def certificate
  @certificate or raise NotCompleted, "not completed yet"
end

#csrAcme::Client::CertificateRequest

Returns:



125
126
127
# File 'lib/acmesmith/ordering_service.rb', line 125

def csr
  @csr ||= Acme::Client::CertificateRequest.new(subject: { common_name: common_name }, names: sans, private_key: private_key)
end

#ensure_authorizationObject



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/acmesmith/ordering_service.rb', line 64

def ensure_authorization
  return if order.authorizations.empty? || order.status == 'ready'
  puts "=> Looking for required domain authorizations"
  puts
  order.authorizations.map(&:domain).each do |domain|
    puts " * #{domain}"
  end
  puts

  AuthorizationService.new(challenge_responder_rules, order.authorizations).perform!
end

#finalize_orderObject



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/acmesmith/ordering_service.rb', line 76

def finalize_order
  puts
  puts "=> Finalizing the order"
  puts
  puts csr.csr.to_pem
  puts

  print " * Requesting..."
  @order_url = order.url if defined?(Acme::Client::Error::OrderNotReloadable)
  order.finalize(csr: csr)
  puts" [ ok ]"
end

#orderObject

Returns Acme::Client::Resources::Order.

Returns:

  • Acme::Client::Resources::Order



111
112
113
# File 'lib/acmesmith/ordering_service.rb', line 111

def order
  @order or raise "BUG: order not yet generated"
end

#pem_chainObject

Returns String.

Returns:

  • String



101
102
103
104
# File 'lib/acmesmith/ordering_service.rb', line 101

def pem_chain
  url = order.certificate_url or raise NotCompleted, "not completed yet"
  CertificateRetrievingService.new(acme, common_name, url, chain_preferences: chain_preferences).pem_chain
end

#perform!Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/acmesmith/ordering_service.rb', line 33

def perform!
  puts "=> Ordering a certificate for the following identifiers:"
  puts
  puts " * CN:  #{common_name}"
  sans.each do |san|
    puts " * SAN: #{san}"
  end

  resolved_profile = profile
  if resolved_profile
    puts
    puts " * Profile: #{resolved_profile}"
  end

  puts
  puts "=> Placing an order"
  @order = acme.new_order(identifiers: identifiers, not_before: not_before, not_after: not_after, profile: resolved_profile)
  puts " * URL: #{order.url}"

  ensure_authorization()

  finalize_order()
  wait_order_for_complete()

  @certificate = Certificate.by_issuance(pem_chain, csr, name: common_name)

  puts
  puts "=> Certificate issued"
  nil
end

#profileObject



120
121
122
# File 'lib/acmesmith/ordering_service.rb', line 120

def profile
  profile_rules.find { |rule| rule.filter.match?(common_name) }&.name
end

#sansArray<String>

Returns:



116
117
118
# File 'lib/acmesmith/ordering_service.rb', line 116

def sans
  identifiers[1..-1]
end

#wait_order_for_completeObject



89
90
91
92
93
94
95
96
97
98
# File 'lib/acmesmith/ordering_service.rb', line 89

def wait_order_for_complete
  # Workaround for https://github.com/unixcharles/acme-client/pull/263

  while %w(ready processing).include?(order.status)
    order.instance_variable_set(:@url, @order_url) if @order_url
    order.reload()
    puts " * Waiting for complete: status=#{order.status}"
    sleep 2
  end
end