acmesmith 0.6.1 → 0.7.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/acmesmith/client.rb +235 -0
- data/lib/acmesmith/command.rb +20 -181
- data/lib/acmesmith/config.rb +4 -0
- data/lib/acmesmith/version.rb +1 -1
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4a9da6141839cd8a3b4850091f05ab7e024a252
|
4
|
+
data.tar.gz: 64807174e4ee28afd2a4be93d7ae8cbcdcf8cde1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1be84d5808225cf30cd6dc324a4a7924f1dacfdb310cc5872e7bdfa74d12ef93e7de5c234ba9ad4fe0679ce03ded44e832a66065544cb9dd808360fb7da4e5a3
|
7
|
+
data.tar.gz: 549065d60f3774ab1ef4be20da4b90d4f02f0e7b13af912b62128c65026ae5c1fb76880754251a3b69a929fe2d3a1581c8d09f5a8184829c57c33e317d875d4c
|
@@ -0,0 +1,235 @@
|
|
1
|
+
require 'acmesmith/account_key'
|
2
|
+
require 'acmesmith/certificate'
|
3
|
+
|
4
|
+
require 'acme-client'
|
5
|
+
|
6
|
+
module Acmesmith
|
7
|
+
class Client
|
8
|
+
def initialize(config: nil)
|
9
|
+
@config ||= config
|
10
|
+
end
|
11
|
+
|
12
|
+
def register(contact)
|
13
|
+
key = AccountKey.generate
|
14
|
+
acme = Acme::Client.new(private_key: key.private_key, endpoint: config['endpoint'])
|
15
|
+
registration = acme.register(contact: contact)
|
16
|
+
registration.agree_terms
|
17
|
+
|
18
|
+
storage.put_account_key(key, account_key_passphrase)
|
19
|
+
|
20
|
+
key
|
21
|
+
end
|
22
|
+
|
23
|
+
def authorize(*domains)
|
24
|
+
targets = domains.map do |domain|
|
25
|
+
authz = acme.authorize(domain: domain)
|
26
|
+
challenges = [authz.http01, authz.dns01, authz.tls_sni01].compact
|
27
|
+
challenge = nil
|
28
|
+
responder = config.challenge_responders.find do |x|
|
29
|
+
challenge = challenges.find { |_| x.support?(_.class::CHALLENGE_TYPE) }
|
30
|
+
end
|
31
|
+
{domain: domain, authz: authz, responder: responder, challenge: challenge}
|
32
|
+
end
|
33
|
+
|
34
|
+
begin
|
35
|
+
targets.each do |target|
|
36
|
+
target[:responder].respond(target[:domain], target[:challenge])
|
37
|
+
end
|
38
|
+
|
39
|
+
targets.each do |target|
|
40
|
+
puts "=> Requesting verifications..."
|
41
|
+
target[:challenge].request_verification
|
42
|
+
end
|
43
|
+
loop do
|
44
|
+
all_valid = true
|
45
|
+
targets.each do |target|
|
46
|
+
next if target[:valid]
|
47
|
+
|
48
|
+
status = target[:challenge].verify_status
|
49
|
+
puts " * [#{target[:domain]}] verify_status: #{status}"
|
50
|
+
|
51
|
+
if status == 'valid'
|
52
|
+
target[:valid] = true
|
53
|
+
next
|
54
|
+
end
|
55
|
+
|
56
|
+
all_valid = false
|
57
|
+
if status == "invalid"
|
58
|
+
err = target[:challenge].error
|
59
|
+
puts " ! [#{target[:domain]}] #{err["type"]}: #{err["detail"]}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
break if all_valid
|
63
|
+
sleep 3
|
64
|
+
end
|
65
|
+
puts "=> Done"
|
66
|
+
ensure
|
67
|
+
targets.each do |target|
|
68
|
+
target[:responder].cleanup(target[:domain], target[:challenge])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def request(common_name, *sans)
|
74
|
+
csr = Acme::Client::CertificateRequest.new(common_name: common_name, names: sans)
|
75
|
+
retried = false
|
76
|
+
acme_cert = begin
|
77
|
+
acme.new_certificate(csr)
|
78
|
+
rescue Acme::Client::Error::Unauthorized => e
|
79
|
+
raise unless config.auto_authorize_on_request
|
80
|
+
raise if retried
|
81
|
+
|
82
|
+
puts "=> Authorizing unauthorized domain names"
|
83
|
+
# https://github.com/letsencrypt/boulder/blob/b9369a481415b3fe31e010b34e2ff570b89e42aa/ra/ra.go#L604
|
84
|
+
m = e.message.match(/authorizations for these names not found or expired: ((?:[a-zA-Z0-9_.\-]+(?:,\s+|$))+)/)
|
85
|
+
if m && m[1]
|
86
|
+
domains = m[1].split(/,\s+/)
|
87
|
+
else
|
88
|
+
warn " ! Error message on certificate request was #{e.message.inspect} and acmesmith couldn't determine which domain names are unauthorized (maybe a bug)"
|
89
|
+
warn " ! Attempting to authorize all domains in this certificate reuqest for now."
|
90
|
+
domains = [common_name, *sans]
|
91
|
+
end
|
92
|
+
puts " * #{domains.join(', ')}"
|
93
|
+
authorize(*domains)
|
94
|
+
retried = true
|
95
|
+
retry
|
96
|
+
end
|
97
|
+
|
98
|
+
cert = Certificate.from_acme_client_certificate(acme_cert)
|
99
|
+
storage.put_certificate(cert, certificate_key_passphrase)
|
100
|
+
|
101
|
+
execute_post_issue_hooks(common_name)
|
102
|
+
|
103
|
+
cert
|
104
|
+
end
|
105
|
+
|
106
|
+
def execute_post_issue_hooks(common_name)
|
107
|
+
post_issues_hooks_for_common_name = config.post_issueing_hooks(common_name)
|
108
|
+
if post_issues_hooks_for_common_name
|
109
|
+
post_issues_hooks_for_common_name.each do |hook|
|
110
|
+
hook.execute
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def certificate_versions(common_name)
|
116
|
+
storage.list_certificate_versions(common_name).sort
|
117
|
+
end
|
118
|
+
|
119
|
+
def certificates_list
|
120
|
+
storage.list_certificates.sort
|
121
|
+
end
|
122
|
+
|
123
|
+
def current(common_name)
|
124
|
+
storage.get_current_certificate_version(common_name)
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_certificate(common_name, version: 'current', type: 'text')
|
128
|
+
cert = storage.get_certificate(common_name, version: version)
|
129
|
+
|
130
|
+
certs = []
|
131
|
+
case type
|
132
|
+
when 'text'
|
133
|
+
certs << cert.certificate.to_text
|
134
|
+
certs << cert.certificate.to_pem
|
135
|
+
when 'certificate'
|
136
|
+
certs << cert.certificate.to_pem
|
137
|
+
when 'chain'
|
138
|
+
certs << cert.chain
|
139
|
+
when 'fullchain'
|
140
|
+
certs << cert.fullchain
|
141
|
+
end
|
142
|
+
|
143
|
+
certs
|
144
|
+
end
|
145
|
+
|
146
|
+
def save_certificate(common_name, version: 'current', mode: '0600', output:)
|
147
|
+
cert = storage.get_certificate(common_name, version: version)
|
148
|
+
File.open(output, 'w', mode.to_i(8)) do |f|
|
149
|
+
f.puts(cert.fullchain)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def get_private_key(common_name, version: 'current')
|
154
|
+
cert = storage.get_certificate(common_name, version: version)
|
155
|
+
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
156
|
+
|
157
|
+
cert.private_key.to_pem
|
158
|
+
end
|
159
|
+
|
160
|
+
def save_private_key(common_name, version: 'current', mode: '0600', output:)
|
161
|
+
cert = storage.get_certificate(common_name, version: version)
|
162
|
+
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
163
|
+
File.open(output, 'w', mode.to_i(8)) do |f|
|
164
|
+
f.puts(cert.private_key)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def save_pkcs12(common_name, version: 'current', mode: '0600', output:, passphrase:)
|
169
|
+
cert = storage.get_certificate(common_name, version: version)
|
170
|
+
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
171
|
+
|
172
|
+
p12 = OpenSSL::PKCS12.create(passphrase, cert.common_name, cert.private_key, cert.certificate)
|
173
|
+
File.open(output, 'w', mode.to_i(8)) do |f|
|
174
|
+
f.puts p12.to_der
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def autorenew(days)
|
179
|
+
storage.list_certificates.each do |cn|
|
180
|
+
puts "=> #{cn}"
|
181
|
+
cert = storage.get_certificate(cn)
|
182
|
+
not_after = cert.certificate.not_after.utc
|
183
|
+
|
184
|
+
puts " Not valid after: #{not_after}"
|
185
|
+
next unless (cert.certificate.not_after.utc - Time.now.utc) < (days.to_i * 86400)
|
186
|
+
puts " * Renewing: CN=#{cert.common_name}, SANs=#{cert.sans.join(',')}"
|
187
|
+
request(cert.common_name, *cert.sans)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_san(common_name, *add_sans)
|
192
|
+
puts "=> reissuing CN=#{common_name} with new SANs #{add_sans.join(?,)}"
|
193
|
+
cert = storage.get_certificate(common_name)
|
194
|
+
sans = cert.sans + add_sans
|
195
|
+
puts " * SANs will be: #{sans.join(?,)}"
|
196
|
+
request(cert.common_name, *sans)
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
def config
|
202
|
+
@config
|
203
|
+
end
|
204
|
+
|
205
|
+
def storage
|
206
|
+
config.storage
|
207
|
+
end
|
208
|
+
|
209
|
+
def account_key
|
210
|
+
@account_key ||= storage.get_account_key.tap do |x|
|
211
|
+
x.key_passphrase = account_key_passphrase if account_key_passphrase
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def acme
|
216
|
+
@acme ||= Acme::Client.new(private_key: account_key.private_key, endpoint: config['endpoint'])
|
217
|
+
end
|
218
|
+
|
219
|
+
def certificate_key_passphrase
|
220
|
+
if config['passphrase_from_env']
|
221
|
+
ENV['ACMESMITH_CERTIFICATE_KEY_PASSPHRASE'] || config['certificate_key_passphrase']
|
222
|
+
else
|
223
|
+
config['certificate_key_passphrase']
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def account_key_passphrase
|
228
|
+
if config['passphrase_from_env']
|
229
|
+
ENV['ACMESMITH_ACCOUNT_KEY_PASSPHRASE'] || config['account_key_passphrase']
|
230
|
+
else
|
231
|
+
config['account_key_passphrase']
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
data/lib/acmesmith/command.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
require 'thor'
|
2
2
|
|
3
3
|
require 'acmesmith/config'
|
4
|
-
require 'acmesmith/
|
5
|
-
require 'acmesmith/certificate'
|
6
|
-
|
7
|
-
require 'acme-client'
|
4
|
+
require 'acmesmith/client'
|
8
5
|
|
9
6
|
module Acmesmith
|
10
7
|
class Command < Thor
|
@@ -13,138 +10,48 @@ module Acmesmith
|
|
13
10
|
|
14
11
|
desc "register CONTACT", "Create account key (contact e.g. mailto:xxx@example.org)"
|
15
12
|
def register(contact)
|
16
|
-
key =
|
17
|
-
acme = Acme::Client.new(private_key: key.private_key, endpoint: config['endpoint'])
|
18
|
-
registration = acme.register(contact: contact)
|
19
|
-
registration.agree_terms
|
20
|
-
|
21
|
-
storage.put_account_key(key, account_key_passphrase)
|
13
|
+
key = client.register(contact)
|
22
14
|
puts "Generated:\n#{key.private_key.public_key.to_pem}"
|
23
15
|
end
|
24
16
|
|
25
17
|
desc "authorize DOMAIN [DOMAIN ...]", "Get authz for DOMAIN."
|
26
18
|
def authorize(*domains)
|
27
|
-
|
28
|
-
authz = acme.authorize(domain: domain)
|
29
|
-
challenges = [authz.http01, authz.dns01, authz.tls_sni01].compact
|
30
|
-
challenge = nil
|
31
|
-
responder = config.challenge_responders.find do |x|
|
32
|
-
challenge = challenges.find { |_| x.support?(_.class::CHALLENGE_TYPE) }
|
33
|
-
end
|
34
|
-
{domain: domain, authz: authz, responder: responder, challenge: challenge}
|
35
|
-
end
|
36
|
-
|
37
|
-
begin
|
38
|
-
targets.each do |target|
|
39
|
-
target[:responder].respond(target[:domain], target[:challenge])
|
40
|
-
end
|
41
|
-
|
42
|
-
targets.each do |target|
|
43
|
-
puts "=> Requesting verifications..."
|
44
|
-
target[:challenge].request_verification
|
45
|
-
end
|
46
|
-
loop do
|
47
|
-
all_valid = true
|
48
|
-
targets.each do |target|
|
49
|
-
next if target[:valid]
|
50
|
-
|
51
|
-
status = target[:challenge].verify_status
|
52
|
-
puts " * [#{target[:domain]}] verify_status: #{status}"
|
53
|
-
|
54
|
-
if status == 'valid'
|
55
|
-
target[:valid] = true
|
56
|
-
next
|
57
|
-
end
|
58
|
-
|
59
|
-
all_valid = false
|
60
|
-
if status == "invalid"
|
61
|
-
err = target[:challenge].error
|
62
|
-
puts " ! [#{target[:domain]}] #{err["type"]}: #{err["detail"]}"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
break if all_valid
|
66
|
-
sleep 3
|
67
|
-
end
|
68
|
-
puts "=> Done"
|
69
|
-
ensure
|
70
|
-
targets.each do |target|
|
71
|
-
target[:responder].cleanup(target[:domain], target[:challenge])
|
72
|
-
end
|
73
|
-
end
|
19
|
+
client.authorize(*domains)
|
74
20
|
end
|
75
21
|
|
76
22
|
desc "request COMMON_NAME [SAN]", "request certificate for CN +COMMON_NAME+ with SANs +SAN+"
|
77
23
|
def request(common_name, *sans)
|
78
|
-
|
79
|
-
retried = false
|
80
|
-
acme_cert = begin
|
81
|
-
acme.new_certificate(csr)
|
82
|
-
rescue Acme::Client::Error::Unauthorized => e
|
83
|
-
raise unless config.auto_authorize_on_request
|
84
|
-
raise if retried
|
85
|
-
|
86
|
-
puts "=> Authorizing unauthorized domain names"
|
87
|
-
# https://github.com/letsencrypt/boulder/blob/b9369a481415b3fe31e010b34e2ff570b89e42aa/ra/ra.go#L604
|
88
|
-
m = e.message.match(/authorizations for these names not found or expired: ((?:[a-zA-Z0-9_.\-]+(?:,\s+|$))+)/)
|
89
|
-
if m && m[1]
|
90
|
-
domains = m[1].split(/,\s+/)
|
91
|
-
else
|
92
|
-
warn " ! Error message on certificate request was #{e.message.inspect} and acmesmith couldn't determine which domain names are unauthorized (maybe a bug)"
|
93
|
-
warn " ! Attempting to authorize all domains in this certificate reuqest for now."
|
94
|
-
domains = [common_name, *sans]
|
95
|
-
end
|
96
|
-
puts " * #{domains.join(', ')}"
|
97
|
-
authorize(*domains)
|
98
|
-
retried = true
|
99
|
-
retry
|
100
|
-
end
|
101
|
-
|
102
|
-
cert = Certificate.from_acme_client_certificate(acme_cert)
|
103
|
-
storage.put_certificate(cert, certificate_key_passphrase)
|
104
|
-
|
24
|
+
cert = client.request(common_name, *sans)
|
105
25
|
puts cert.certificate.to_text
|
106
26
|
puts cert.certificate.to_pem
|
107
|
-
|
108
|
-
execute_post_issue_hooks(common_name)
|
109
27
|
end
|
110
28
|
|
111
29
|
desc "post-issue-hooks COMMON_NAME", "Run all post-issueing hooks for common name. (for testing purpose)"
|
112
30
|
def post_issue_hooks(common_name)
|
113
|
-
|
31
|
+
client.post_issue_hooks(common_name)
|
114
32
|
end
|
115
33
|
map 'post-issue-hooks' => :post_issue_hooks
|
116
34
|
|
117
35
|
desc "list [COMMON_NAME]", "list certificates or its versions"
|
118
36
|
def list(common_name = nil)
|
119
37
|
if common_name
|
120
|
-
puts
|
38
|
+
puts client.certificate_versions(common_name)
|
121
39
|
else
|
122
|
-
puts
|
40
|
+
puts client.certificates_list
|
123
41
|
end
|
124
42
|
end
|
125
43
|
|
126
44
|
desc "current COMMON_NAME", "show current version for certificate"
|
127
45
|
def current(common_name)
|
128
|
-
puts
|
46
|
+
puts client.current(common_name)
|
129
47
|
end
|
130
48
|
|
131
49
|
desc "show-certificate COMMON_NAME", "show certificate"
|
132
50
|
method_option :version, type: :string, default: 'current'
|
133
51
|
method_option :type, type: :string, enum: %w(text certificate chain fullchain), default: 'text'
|
134
52
|
def show_certificate(common_name)
|
135
|
-
|
136
|
-
|
137
|
-
case options[:type]
|
138
|
-
when 'text'
|
139
|
-
puts cert.certificate.to_text
|
140
|
-
puts cert.certificate.to_pem
|
141
|
-
when 'certificate'
|
142
|
-
puts cert.certificate.to_pem
|
143
|
-
when 'chain'
|
144
|
-
puts cert.chain
|
145
|
-
when 'fullchain'
|
146
|
-
puts cert.fullchain
|
147
|
-
end
|
53
|
+
certs = client.get_certificate(common_name, version: options[:version], type: options[:type])
|
54
|
+
puts certs
|
148
55
|
end
|
149
56
|
map 'show-certiticate' => :show_certificate
|
150
57
|
|
@@ -153,19 +60,13 @@ module Acmesmith
|
|
153
60
|
method_option :output, type: :string, required: true, banner: 'PATH', desc: 'Path to output file'
|
154
61
|
method_option :mode, type: :string, default: '0600', desc: 'Mode (permission) of the output file on create'
|
155
62
|
def save_certificate(common_name)
|
156
|
-
|
157
|
-
File.open(options[:output], 'w', options[:mode].to_i(8)) do |f|
|
158
|
-
f.puts(cert.fullchain)
|
159
|
-
end
|
63
|
+
client.save_certificate(common_name, version: options[:version], mode: options[:mode], output: options[:output])
|
160
64
|
end
|
161
65
|
|
162
66
|
desc "show-private-key COMMON_NAME", "show private key"
|
163
67
|
method_option :version, type: :string, default: 'current'
|
164
68
|
def show_private_key(common_name)
|
165
|
-
|
166
|
-
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
167
|
-
|
168
|
-
puts cert.private_key.to_pem
|
69
|
+
puts client.get_private_key(common_name, version: options[:version])
|
169
70
|
end
|
170
71
|
map 'show-private-key' => :show_private_key
|
171
72
|
|
@@ -174,11 +75,7 @@ module Acmesmith
|
|
174
75
|
method_option :output, type: :string, required: true, banner: 'PATH', desc: 'Path to output file'
|
175
76
|
method_option :mode, type: :string, default: '0600', desc: 'Mode (permission) of the output file on create'
|
176
77
|
def save_private_key(common_name)
|
177
|
-
|
178
|
-
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
179
|
-
File.open(options[:output], 'w', options[:mode].to_i(8)) do |f|
|
180
|
-
f.puts(cert.private_key)
|
181
|
-
end
|
78
|
+
client.save_private_key(common_name, version: options[:version], mode: options[:mode], output: options[:output])
|
182
79
|
end
|
183
80
|
|
184
81
|
desc 'save-pkcs12 COMMON_NAME', 'Save ceriticate and private key to .p12 file'
|
@@ -186,9 +83,6 @@ module Acmesmith
|
|
186
83
|
method_option :output, type: :string, required: true, banner: 'PATH', desc: 'Path to output file'
|
187
84
|
method_option :mode, type: :string, default: '0600', desc: 'Mode (permission) of the output file on create'
|
188
85
|
def save_pkcs12(common_name)
|
189
|
-
cert = storage.get_certificate(common_name, version: options[:version])
|
190
|
-
cert.key_passphrase = certificate_key_passphrase if certificate_key_passphrase
|
191
|
-
|
192
86
|
print 'Passphrase: '
|
193
87
|
passphrase = $stdin.noecho { $stdin.gets }.chomp
|
194
88
|
print "\nPassphrase (confirm): "
|
@@ -196,81 +90,26 @@ module Acmesmith
|
|
196
90
|
puts
|
197
91
|
|
198
92
|
raise ArgumentError, "Passphrase doesn't match" if passphrase != passphrase2
|
199
|
-
|
200
|
-
p12 = OpenSSL::PKCS12.create(passphrase, cert.common_name, cert.private_key, cert.certificate)
|
201
|
-
File.open(options[:output], 'w', options[:mode].to_i(8)) do |f|
|
202
|
-
f.puts p12.to_der
|
203
|
-
end
|
93
|
+
client.save_pkcs12(common_name, version: options[:version], mode: options[:mode], output: options[:output], passphrase: passphrase)
|
204
94
|
end
|
205
95
|
|
206
96
|
desc "autorenew", "request renewal of certificates which expires soon"
|
207
97
|
method_option :days, type: :numeric, aliases: %w(-d), default: 7, desc: 'specify threshold in days to select certificates to renew'
|
208
98
|
def autorenew
|
209
|
-
|
210
|
-
puts "=> #{cn}"
|
211
|
-
cert = storage.get_certificate(cn)
|
212
|
-
not_after = cert.certificate.not_after.utc
|
213
|
-
|
214
|
-
puts " Not valid after: #{not_after}"
|
215
|
-
next unless (cert.certificate.not_after.utc - Time.now.utc) < (options[:days].to_i * 86400)
|
216
|
-
puts " * Renewing: CN=#{cert.common_name}, SANs=#{cert.sans.join(',')}"
|
217
|
-
request(cert.common_name, *cert.sans)
|
218
|
-
end
|
99
|
+
client.autorenew(options[:days])
|
219
100
|
end
|
220
101
|
|
221
102
|
desc "add-san COMMON_NAME [ADDITIONAL_SANS]", "request renewal of existing certificate with additional SANs"
|
222
103
|
def add_san(common_name, *add_sans)
|
223
|
-
|
224
|
-
cert = storage.get_certificate(common_name)
|
225
|
-
sans = cert.sans + add_sans
|
226
|
-
puts " * SANs will be: #{sans.join(?,)}"
|
227
|
-
request(cert.common_name, *sans)
|
104
|
+
client.add_san(common_name, *add_sans)
|
228
105
|
end
|
229
106
|
|
230
107
|
private
|
231
108
|
|
232
|
-
def
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
def storage
|
237
|
-
config.storage
|
109
|
+
def client
|
110
|
+
config = Config.load_yaml(options[:config])
|
111
|
+
config.merge!("passphrase_from_env" => options[:passphrase_from_env]) unless options[:passphrase_from_env].nil?
|
112
|
+
@client = Client.new(config: config)
|
238
113
|
end
|
239
|
-
|
240
|
-
def account_key
|
241
|
-
@account_key ||= storage.get_account_key.tap do |x|
|
242
|
-
x.key_passphrase = account_key_passphrase if account_key_passphrase
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
def acme
|
247
|
-
@acme ||= Acme::Client.new(private_key: account_key.private_key, endpoint: config['endpoint'])
|
248
|
-
end
|
249
|
-
|
250
|
-
def certificate_key_passphrase
|
251
|
-
if options[:passphrase_from_env] || config['passphrase_from_env']
|
252
|
-
ENV['ACMESMITH_CERTIFICATE_KEY_PASSPHRASE'] || config['certificate_key_passphrase']
|
253
|
-
else
|
254
|
-
config['certificate_key_passphrase']
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def account_key_passphrase
|
259
|
-
if options[:passphrase_from_env] || config['passphrase_from_env']
|
260
|
-
ENV['ACMESMITH_ACCOUNT_KEY_PASSPHRASE'] || config['account_key_passphrase']
|
261
|
-
else
|
262
|
-
config['account_key_passphrase']
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
def execute_post_issue_hooks(common_name)
|
267
|
-
post_issues_hooks_for_common_name = config.post_issueing_hooks(common_name)
|
268
|
-
if post_issues_hooks_for_common_name
|
269
|
-
post_issues_hooks_for_common_name.each do |hook|
|
270
|
-
hook.execute
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
114
|
end
|
276
115
|
end
|
data/lib/acmesmith/config.rb
CHANGED
data/lib/acmesmith/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acmesmith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- sorah (Shota Fukumori)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-07-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acme-client
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- lib/acmesmith/challenge_responders.rb
|
125
125
|
- lib/acmesmith/challenge_responders/base.rb
|
126
126
|
- lib/acmesmith/challenge_responders/route53.rb
|
127
|
+
- lib/acmesmith/client.rb
|
127
128
|
- lib/acmesmith/command.rb
|
128
129
|
- lib/acmesmith/config.rb
|
129
130
|
- lib/acmesmith/post_issueing_hooks.rb
|
@@ -152,12 +153,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
152
153
|
version: '0'
|
153
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
155
|
requirements:
|
155
|
-
- - "
|
156
|
+
- - ">"
|
156
157
|
- !ruby/object:Gem::Version
|
157
|
-
version:
|
158
|
+
version: 1.3.1
|
158
159
|
requirements: []
|
159
160
|
rubyforge_project:
|
160
|
-
rubygems_version: 2.6.
|
161
|
+
rubygems_version: 2.6.11
|
161
162
|
signing_key:
|
162
163
|
specification_version: 4
|
163
164
|
summary: ACME client (Let's encrypt client) to manage certificate in multi server
|