acme-client 2.0.6 → 2.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/acme/client.rb +18 -2
- data/lib/acme/client/chain_identifier.rb +27 -0
- data/lib/acme/client/error.rb +1 -0
- data/lib/acme/client/faraday_middleware.rb +1 -9
- data/lib/acme/client/resources/account.rb +1 -1
- data/lib/acme/client/resources/authorization.rb +1 -1
- data/lib/acme/client/resources/challenges/base.rb +1 -1
- data/lib/acme/client/resources/order.rb +3 -3
- data/lib/acme/client/util.rb +11 -0
- data/lib/acme/client/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 718dac85c8139621711a030272097498d04414ca52c9d84544b8bac32179e8a1
|
4
|
+
data.tar.gz: 9e929450733261f291a62b96f5056ed89e8c235cae010805ddccfc3efb17188c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6e77c41a67b3f2fe9d6e373d58e928bfc0ee2523ac7b0ce2beb93167179a0950045cbb0ec4f5d8616527108814001acd0da7909a8bb0df8dac9b6ddde8bfbba
|
7
|
+
data.tar.gz: 9eba181b543cfe437e2043970b2e74cd691944457d43d3c3ea052cf10d3134e59b51aa8ee3522c36f27b25c212797e44e0e29b86f96b13361e98ca07d054ccac
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -184,7 +184,7 @@ csr = Acme::Client::CertificateRequest.new(private_key: a_different_private_key,
|
|
184
184
|
order.finalize(csr: csr)
|
185
185
|
while order.status == 'processing'
|
186
186
|
sleep(1)
|
187
|
-
|
187
|
+
order.reload
|
188
188
|
end
|
189
189
|
order.certificate # => PEM-formatted certificate
|
190
190
|
```
|
data/lib/acme/client.rb
CHANGED
@@ -20,6 +20,7 @@ require 'acme/client/faraday_middleware'
|
|
20
20
|
require 'acme/client/jwk'
|
21
21
|
require 'acme/client/error'
|
22
22
|
require 'acme/client/util'
|
23
|
+
require 'acme/client/chain_identifier'
|
23
24
|
|
24
25
|
class Acme::Client
|
25
26
|
DEFAULT_DIRECTORY = 'http://127.0.0.1:4000/directory'.freeze
|
@@ -127,9 +128,24 @@ class Acme::Client
|
|
127
128
|
Acme::Client::Resources::Order.new(self, **arguments)
|
128
129
|
end
|
129
130
|
|
130
|
-
def certificate(url:)
|
131
|
+
def certificate(url:, force_chain: nil)
|
131
132
|
response = download(url, format: :pem)
|
132
|
-
response.body
|
133
|
+
pem = response.body
|
134
|
+
|
135
|
+
return pem if force_chain.nil?
|
136
|
+
|
137
|
+
return pem if ChainIdentifier.new(pem).match_name?(force_chain)
|
138
|
+
|
139
|
+
alternative_urls = Array(response.headers.dig('link', 'alternate'))
|
140
|
+
alternative_urls.each do |alternate_url|
|
141
|
+
response = download(alternate_url, format: :pem)
|
142
|
+
pem = response.body
|
143
|
+
if ChainIdentifier.new(pem).match_name?(force_chain)
|
144
|
+
return pem
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
raise Acme::Client::Error::ForcedChainNotFound, "Could not find any matching chain for `#{force_chain}`"
|
133
149
|
end
|
134
150
|
|
135
151
|
def authorization(url:)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Acme::Client
|
2
|
+
class ChainIdentifier
|
3
|
+
def initialize(pem_certificate_chain)
|
4
|
+
@pem_certificate_chain = pem_certificate_chain
|
5
|
+
end
|
6
|
+
|
7
|
+
def match_name?(name)
|
8
|
+
issuers.any? do |issuer|
|
9
|
+
issuer.include?(name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def issuers
|
16
|
+
x509_certificates.map(&:issuer).map(&:to_s)
|
17
|
+
end
|
18
|
+
|
19
|
+
def x509_certificates
|
20
|
+
@x509_certificates ||= splitted_pem_certificates.map { |pem| OpenSSL::X509::Certificate.new(pem) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def splitted_pem_certificates
|
24
|
+
@pem_certificate_chain.each_line.slice_after(/END CERTIFICATE/).map(&:join)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/acme/client/error.rb
CHANGED
@@ -7,6 +7,7 @@ class Acme::Client::Error < StandardError
|
|
7
7
|
class UnsupportedChallengeType < ClientError; end
|
8
8
|
class NotFound < ClientError; end
|
9
9
|
class CertificateNotReady < ClientError; end
|
10
|
+
class ForcedChainNotFound < ClientError; end
|
10
11
|
|
11
12
|
class ServerError < Acme::Client::Error; end
|
12
13
|
class BadCSR < ServerError; end
|
@@ -82,18 +82,10 @@ class Acme::Client::FaradayMiddleware < Faraday::Middleware
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
-
LINK_MATCH = /<(.*?)>;rel="([\w-]+)"/
|
86
|
-
|
87
85
|
def decode_link_headers
|
88
86
|
return unless env.response_headers.key?('Link')
|
89
87
|
link_header = env.response_headers['Link']
|
90
|
-
|
91
|
-
links = link_header.split(', ').map { |entry|
|
92
|
-
_, link, name = *entry.match(LINK_MATCH)
|
93
|
-
[name, link]
|
94
|
-
}
|
95
|
-
|
96
|
-
Hash[*links.flatten]
|
88
|
+
Acme::Client::Util.decode_link_headers(link_header)
|
97
89
|
end
|
98
90
|
|
99
91
|
def store_nonce
|
@@ -5,7 +5,7 @@ class Acme::Client::Resources::Order
|
|
5
5
|
|
6
6
|
def initialize(client, **arguments)
|
7
7
|
@client = client
|
8
|
-
assign_attributes(arguments)
|
8
|
+
assign_attributes(**arguments)
|
9
9
|
end
|
10
10
|
|
11
11
|
def reload
|
@@ -24,9 +24,9 @@ class Acme::Client::Resources::Order
|
|
24
24
|
true
|
25
25
|
end
|
26
26
|
|
27
|
-
def certificate
|
27
|
+
def certificate(force_chain: nil)
|
28
28
|
if certificate_url
|
29
|
-
@client.certificate(url: certificate_url)
|
29
|
+
@client.certificate(url: certificate_url, force_chain: force_chain)
|
30
30
|
else
|
31
31
|
raise Acme::Client::Error::CertificateNotReady, 'No certificate_url to collect the order'
|
32
32
|
end
|
data/lib/acme/client/util.rb
CHANGED
@@ -3,6 +3,17 @@ module Acme::Client::Util
|
|
3
3
|
Base64.urlsafe_encode64(data).sub(/[\s=]*\z/, '')
|
4
4
|
end
|
5
5
|
|
6
|
+
LINK_MATCH = /<(.*?)>\s?;\s?rel="([\w-]+)"/
|
7
|
+
|
8
|
+
# See RFC 8288 - https://tools.ietf.org/html/rfc8288#section-3
|
9
|
+
def decode_link_headers(link_header)
|
10
|
+
link_header.split(',').each_with_object({}) { |entry, hash|
|
11
|
+
_, link, name = *entry.match(LINK_MATCH)
|
12
|
+
hash[name] ||= []
|
13
|
+
hash[name].push(link)
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
6
17
|
# Sets public key on CSR or cert.
|
7
18
|
#
|
8
19
|
# obj - An OpenSSL::X509::Certificate or OpenSSL::X509::Request instance.
|
data/lib/acme/client/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acme-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Barbier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -124,6 +124,7 @@ files:
|
|
124
124
|
- lib/acme/client.rb
|
125
125
|
- lib/acme/client/certificate_request.rb
|
126
126
|
- lib/acme/client/certificate_request/ec_key_patch.rb
|
127
|
+
- lib/acme/client/chain_identifier.rb
|
127
128
|
- lib/acme/client/error.rb
|
128
129
|
- lib/acme/client/faraday_middleware.rb
|
129
130
|
- lib/acme/client/jwk.rb
|
@@ -162,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
163
|
- !ruby/object:Gem::Version
|
163
164
|
version: '0'
|
164
165
|
requirements: []
|
165
|
-
rubygems_version: 3.
|
166
|
+
rubygems_version: 3.1.2
|
166
167
|
signing_key:
|
167
168
|
specification_version: 4
|
168
169
|
summary: Client for the ACME protocol.
|