acme-cli 0.6.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/acme-cli.gemspec +3 -3
- data/lib/letsencrypt/cli/acme_wrapper.rb +28 -15
- data/lib/letsencrypt/cli/app.rb +4 -4
- data/lib/letsencrypt/cli/support/certificate.rb +29 -0
- data/lib/letsencrypt/cli/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c426da565e907b19f9a87cd785aef871d1e9c43bc7ce91380376a459198abb49
|
4
|
+
data.tar.gz: fdecdc6b9a931dc8526fd52b53e7b7c5c2882af978ad6d44f5035877a0e38a4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cf06389946f95ed0b16cfa74101ffee3012be8b0b20618e497bdeeac58998ff28295ab8b00cbefbe47d5fdd63e262f31b78ef495bc0befacfb8f3be408f13487
|
7
|
+
data.tar.gz: a9276b7d8b2aeed105601c626b5e1b5f7db00009f3a483a9f6e176d485f0053d41988b952666d0433e2875c03b05f6aa8d58112aee26221e7d225db240501827
|
data/acme-cli.gemspec
CHANGED
@@ -10,16 +10,16 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["stwienert@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{slim ACME (e. g. letsencrypt) client for quickly authorizing (multiple) domains and issuing certificates}
|
13
|
-
spec.homepage = "https://github.com/zealot28/acme-cli"
|
13
|
+
spec.homepage = "https://github.com/zealot28/ruby-acme-cli"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = '>= 2.
|
15
|
+
spec.required_ruby_version = '>= 2.1.0'
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
18
|
spec.bindir = "exe"
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_runtime_dependency 'acme-client', '>= 0.
|
22
|
+
spec.add_runtime_dependency 'acme-client', '>= 2.0.0'
|
23
23
|
spec.add_runtime_dependency 'thor'
|
24
24
|
spec.add_runtime_dependency 'colorize'
|
25
25
|
|
@@ -2,6 +2,7 @@ require 'json'
|
|
2
2
|
require 'acme-client'
|
3
3
|
require 'logger'
|
4
4
|
require 'colorize'
|
5
|
+
require_relative 'support/certificate'
|
5
6
|
|
6
7
|
class AcmeWrapper
|
7
8
|
def initialize(options)
|
@@ -22,28 +23,34 @@ class AcmeWrapper
|
|
22
23
|
end
|
23
24
|
|
24
25
|
def client
|
25
|
-
@client ||= Acme::Client.new(private_key: account_key,
|
26
|
+
@client ||= Acme::Client.new(private_key: account_key, directory: directory)
|
26
27
|
end
|
27
28
|
|
28
|
-
def
|
29
|
+
def create_order(domains)
|
30
|
+
log "Creating order for domains #{domains.to_s.blue}"
|
31
|
+
return client.new_order(identifiers: domains)
|
32
|
+
end
|
33
|
+
|
34
|
+
def authorize(authorization)
|
35
|
+
domain = authorization.domain
|
29
36
|
FileUtils.mkdir_p(@options[:webroot_path])
|
30
37
|
log "Authorizing #{domain.blue}.."
|
31
|
-
|
32
|
-
|
33
|
-
challenge = authorization.http01
|
38
|
+
challenge = authorization.http
|
34
39
|
|
35
40
|
challenge_file = File.join(@options[:webroot_path], challenge.filename.split('/').last)
|
36
41
|
log "Writing challenge to #{challenge_file}", :debug
|
37
42
|
File.write(challenge_file, challenge.file_content)
|
38
43
|
|
39
|
-
challenge.
|
44
|
+
challenge.request_validation
|
40
45
|
|
41
|
-
|
46
|
+
10.times do
|
42
47
|
log "Checking verification...", :debug
|
43
48
|
sleep 1
|
44
|
-
|
49
|
+
challenge.reload
|
50
|
+
break if challenge.status != 'pending'
|
45
51
|
end
|
46
|
-
|
52
|
+
|
53
|
+
if challenge.status == 'valid'
|
47
54
|
log "Authorization successful for #{domain.green}"
|
48
55
|
File.unlink(challenge_file)
|
49
56
|
true
|
@@ -84,7 +91,13 @@ class AcmeWrapper
|
|
84
91
|
csr.version = 2
|
85
92
|
csr.public_key = certificate_private_key.public_key
|
86
93
|
csr.sign(certificate_private_key, OpenSSL::Digest::SHA256.new)
|
87
|
-
|
94
|
+
order = create_order(domains)
|
95
|
+
order.finalize(csr: csr)
|
96
|
+
while order.status == 'processing'
|
97
|
+
sleep(1)
|
98
|
+
order.reload
|
99
|
+
end
|
100
|
+
certificate = Certificate.new(order.certificate)
|
88
101
|
File.write(@options[:fullchain_path], certificate.fullchain_to_pem)
|
89
102
|
File.write(@options[:chain_path], certificate.chain_to_pem)
|
90
103
|
File.write(@options[:certificate_path], certificate.to_pem)
|
@@ -114,7 +127,7 @@ class AcmeWrapper
|
|
114
127
|
return false
|
115
128
|
end
|
116
129
|
cert = OpenSSL::X509::Certificate.new(File.read(path))
|
117
|
-
if client.
|
130
|
+
if client.revoke(certificate: cert)
|
118
131
|
log "Certificate '#{path}' was revoked", :info
|
119
132
|
end
|
120
133
|
true
|
@@ -147,14 +160,14 @@ class AcmeWrapper
|
|
147
160
|
exit 2
|
148
161
|
end
|
149
162
|
|
150
|
-
false
|
163
|
+
false
|
151
164
|
end
|
152
165
|
|
153
|
-
def
|
166
|
+
def directory
|
154
167
|
if @options[:test]
|
155
|
-
"https://acme-staging.api.letsencrypt.org"
|
168
|
+
"https://acme-staging-v02.api.letsencrypt.org/directory"
|
156
169
|
else
|
157
|
-
"https://acme-
|
170
|
+
"https://acme-v02.api.letsencrypt.org/directory"
|
158
171
|
end
|
159
172
|
end
|
160
173
|
|
data/lib/letsencrypt/cli/app.rb
CHANGED
@@ -20,8 +20,7 @@ module Letsencrypt
|
|
20
20
|
wrapper.log "not an email", :fatal
|
21
21
|
exit 1
|
22
22
|
end
|
23
|
-
registration = wrapper.client.
|
24
|
-
registration.agree_terms
|
23
|
+
registration = wrapper.client.new_account(contact: "mailto:" + email, terms_of_service_agreed: true)
|
25
24
|
wrapper.log "Account created, Terms accepted"
|
26
25
|
end
|
27
26
|
|
@@ -38,8 +37,9 @@ module Letsencrypt
|
|
38
37
|
method_option :webroot_path, desc: "Path to mapped .well-known/acme-challenge folder (no subdirs will be created)", aliases: '-w', required: true
|
39
38
|
def authorize(*domains)
|
40
39
|
rc = 0
|
41
|
-
|
42
|
-
|
40
|
+
order = wrapper.create_order(domains)
|
41
|
+
order.authorizations.each do |authorization|
|
42
|
+
if !wrapper.authorize(authorization)
|
43
43
|
rc = 1
|
44
44
|
end
|
45
45
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Certificate
|
2
|
+
extend Forwardable
|
3
|
+
|
4
|
+
attr_reader :x509, :x509_chain
|
5
|
+
|
6
|
+
def_delegators :x509, :to_pem, :to_der
|
7
|
+
|
8
|
+
def initialize(fullchain_certificate)
|
9
|
+
fullchain_array = fullchain_certificate.strip.split("\n\n")
|
10
|
+
@x509 = OpenSSL::X509::Certificate.new(fullchain_array.first)
|
11
|
+
@x509_chain = fullchain_array[1..-1].map { |cert| OpenSSL::X509::Certificate.new(cert) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def chain_to_pem
|
15
|
+
x509_chain.map(&:to_pem).join("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def x509_fullchain
|
19
|
+
[x509, *x509_chain]
|
20
|
+
end
|
21
|
+
|
22
|
+
def fullchain_to_pem
|
23
|
+
x509_fullchain.map(&:to_pem).join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
def common_name
|
27
|
+
x509.subject.to_a.find { |name, _, _| name == 'CN' }[1]
|
28
|
+
end
|
29
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acme-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Wienert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acme-client
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 2.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 2.0.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,8 +203,9 @@ files:
|
|
203
203
|
- lib/letsencrypt/cli.rb
|
204
204
|
- lib/letsencrypt/cli/acme_wrapper.rb
|
205
205
|
- lib/letsencrypt/cli/app.rb
|
206
|
+
- lib/letsencrypt/cli/support/certificate.rb
|
206
207
|
- lib/letsencrypt/cli/version.rb
|
207
|
-
homepage: https://github.com/zealot28/acme-cli
|
208
|
+
homepage: https://github.com/zealot28/ruby-acme-cli
|
208
209
|
licenses:
|
209
210
|
- MIT
|
210
211
|
metadata: {}
|
@@ -216,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
216
217
|
requirements:
|
217
218
|
- - ">="
|
218
219
|
- !ruby/object:Gem::Version
|
219
|
-
version: 2.
|
220
|
+
version: 2.1.0
|
220
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
221
222
|
requirements:
|
222
223
|
- - ">="
|
@@ -224,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
225
|
version: '0'
|
225
226
|
requirements: []
|
226
227
|
rubyforge_project:
|
227
|
-
rubygems_version: 2.6
|
228
|
+
rubygems_version: 2.7.6
|
228
229
|
signing_key:
|
229
230
|
specification_version: 4
|
230
231
|
summary: slim ACME (e. g. letsencrypt) client for quickly authorizing (multiple) domains
|