acme-client 1.0.0 → 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/.rubocop.yml +36 -0
- data/README.md +138 -94
- data/lib/acme/client.rb +223 -63
- data/lib/acme/client/certificate_request.rb +0 -2
- data/lib/acme/client/error.rb +52 -13
- data/lib/acme/client/faraday_middleware.rb +23 -24
- data/lib/acme/client/jwk/base.rb +7 -6
- data/lib/acme/client/jwk/ecdsa.rb +0 -2
- data/lib/acme/client/resources.rb +4 -2
- data/lib/acme/client/resources/account.rb +49 -0
- data/lib/acme/client/resources/authorization.rb +62 -32
- data/lib/acme/client/resources/challenges.rb +20 -5
- data/lib/acme/client/resources/challenges/base.rb +26 -22
- data/lib/acme/client/resources/challenges/dns01.rb +1 -1
- data/lib/acme/client/resources/challenges/http01.rb +1 -1
- data/lib/acme/client/resources/directory.rb +75 -0
- data/lib/acme/client/resources/order.rb +58 -0
- data/lib/acme/client/version.rb +1 -1
- metadata +5 -5
- data/lib/acme/client/certificate.rb +0 -30
- data/lib/acme/client/resources/challenges/tls_sni01.rb +0 -25
- data/lib/acme/client/resources/registration.rb +0 -37
@@ -15,6 +15,6 @@ class Acme::Client::Resources::Challenges::DNS01 < Acme::Client::Resources::Chal
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def record_content
|
18
|
-
Acme::Client::Util.urlsafe_base64(DIGEST.digest(
|
18
|
+
Acme::Client::Util.urlsafe_base64(DIGEST.digest(key_authorization))
|
19
19
|
end
|
20
20
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Acme::Client::Resources::Directory
|
4
|
+
DIRECTORY_RESOURCES = {
|
5
|
+
new_nonce: 'newNonce',
|
6
|
+
new_account: 'newAccount',
|
7
|
+
new_order: 'newOrder',
|
8
|
+
new_authz: 'newAuthz',
|
9
|
+
revoke_certificate: 'revokeCert',
|
10
|
+
key_change: 'keyChange'
|
11
|
+
}
|
12
|
+
|
13
|
+
DIRECTORY_META = {
|
14
|
+
terms_of_service: 'termsOfService',
|
15
|
+
website: 'website',
|
16
|
+
caa_identities: 'caaIdentities',
|
17
|
+
external_account_required: 'externalAccountRequired'
|
18
|
+
}
|
19
|
+
|
20
|
+
def initialize(url, connection_options)
|
21
|
+
@url, @connection_options = url, connection_options
|
22
|
+
end
|
23
|
+
|
24
|
+
def endpoint_for(key)
|
25
|
+
directory.fetch(key) do |missing_key|
|
26
|
+
raise Acme::Client::Error::UnsupportedOperation,
|
27
|
+
"Directory at #{@url} does not include `#{missing_key}`"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def terms_of_service
|
32
|
+
meta[DIRECTORY_META[:terms_of_service]]
|
33
|
+
end
|
34
|
+
|
35
|
+
def website
|
36
|
+
meta[DIRECTORY_META[:website]]
|
37
|
+
end
|
38
|
+
|
39
|
+
def caa_identities
|
40
|
+
meta[DIRECTORY_META[:caa_identities]]
|
41
|
+
end
|
42
|
+
|
43
|
+
def external_account_required
|
44
|
+
meta[DIRECTORY_META[:external_account_required]]
|
45
|
+
end
|
46
|
+
|
47
|
+
def meta
|
48
|
+
directory[:meta]
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def directory
|
54
|
+
@directory ||= load_directory
|
55
|
+
end
|
56
|
+
|
57
|
+
def load_directory
|
58
|
+
body = fetch_directory
|
59
|
+
result = {}
|
60
|
+
result[:meta] = body.delete('meta')
|
61
|
+
DIRECTORY_RESOURCES.each do |key, entry|
|
62
|
+
result[key] = URI(body[entry]) if body[entry]
|
63
|
+
end
|
64
|
+
result
|
65
|
+
rescue JSON::ParserError => exception
|
66
|
+
raise InvalidDirectory, "Invalid directory url\n#{@directory} did not return a valid directory\n#{exception.inspect}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def fetch_directory
|
70
|
+
connection = Faraday.new(url: @directory, **@connection_options)
|
71
|
+
connection.headers[:user_agent] = Acme::Client::USER_AGENT
|
72
|
+
response = connection.get(@url)
|
73
|
+
JSON.parse(response.body)
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Acme::Client::Resources::Order
|
4
|
+
attr_reader :url, :status, :contact, :finalize_url, :identifiers, :authorization_urls, :expires, :certificate_url
|
5
|
+
|
6
|
+
def initialize(client, **arguments)
|
7
|
+
@client = client
|
8
|
+
assign_attributes(arguments)
|
9
|
+
end
|
10
|
+
|
11
|
+
def reload
|
12
|
+
assign_attributes **@client.order(url: url).to_h
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorizations
|
17
|
+
@authorization_urls.map do |authorization_url|
|
18
|
+
@client.authorization(url: authorization_url)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def finalize(csr:)
|
23
|
+
assign_attributes **@client.finalize(url: finalize_url, csr: csr).to_h
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def certificate
|
28
|
+
if certificate_url
|
29
|
+
@client.certificate(url: certificate_url)
|
30
|
+
else
|
31
|
+
raise Acme::Client::Error::CertificateNotReady, 'No certificate_url to collect the order'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_h
|
36
|
+
{
|
37
|
+
url: url,
|
38
|
+
status: status,
|
39
|
+
expires: expires,
|
40
|
+
finalize_url: finalize_url,
|
41
|
+
authorization_urls: authorization_urls,
|
42
|
+
identifiers: identifiers,
|
43
|
+
certificate_url: certificate_url
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def assign_attributes(url:, status:, expires:, finalize_url:, authorization_urls:, identifiers:, certificate_url: nil)
|
50
|
+
@url = url
|
51
|
+
@status = status
|
52
|
+
@expires = expires
|
53
|
+
@finalize_url = finalize_url
|
54
|
+
@authorization_urls = authorization_urls
|
55
|
+
@identifiers = identifiers
|
56
|
+
@certificate_url = certificate_url
|
57
|
+
end
|
58
|
+
end
|
data/lib/acme/client/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acme-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Barbier
|
@@ -146,7 +146,6 @@ files:
|
|
146
146
|
- bin/setup
|
147
147
|
- lib/acme-client.rb
|
148
148
|
- lib/acme/client.rb
|
149
|
-
- lib/acme/client/certificate.rb
|
150
149
|
- lib/acme/client/certificate_request.rb
|
151
150
|
- lib/acme/client/certificate_request/ec_key_patch.rb
|
152
151
|
- lib/acme/client/error.rb
|
@@ -156,13 +155,14 @@ files:
|
|
156
155
|
- lib/acme/client/jwk/ecdsa.rb
|
157
156
|
- lib/acme/client/jwk/rsa.rb
|
158
157
|
- lib/acme/client/resources.rb
|
158
|
+
- lib/acme/client/resources/account.rb
|
159
159
|
- lib/acme/client/resources/authorization.rb
|
160
160
|
- lib/acme/client/resources/challenges.rb
|
161
161
|
- lib/acme/client/resources/challenges/base.rb
|
162
162
|
- lib/acme/client/resources/challenges/dns01.rb
|
163
163
|
- lib/acme/client/resources/challenges/http01.rb
|
164
|
-
- lib/acme/client/resources/
|
165
|
-
- lib/acme/client/resources/
|
164
|
+
- lib/acme/client/resources/directory.rb
|
165
|
+
- lib/acme/client/resources/order.rb
|
166
166
|
- lib/acme/client/self_sign_certificate.rb
|
167
167
|
- lib/acme/client/util.rb
|
168
168
|
- lib/acme/client/version.rb
|
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
186
|
version: '0'
|
187
187
|
requirements: []
|
188
188
|
rubyforge_project:
|
189
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.7.6
|
190
190
|
signing_key:
|
191
191
|
specification_version: 4
|
192
192
|
summary: Client for the ACME protocol.
|
@@ -1,30 +0,0 @@
|
|
1
|
-
class Acme::Client::Certificate
|
2
|
-
extend Forwardable
|
3
|
-
|
4
|
-
attr_reader :x509, :x509_chain, :request, :private_key, :url
|
5
|
-
|
6
|
-
def_delegators :x509, :to_pem, :to_der
|
7
|
-
|
8
|
-
def initialize(certificate, url, chain, request)
|
9
|
-
@x509 = certificate
|
10
|
-
@url = url
|
11
|
-
@x509_chain = chain
|
12
|
-
@request = request
|
13
|
-
end
|
14
|
-
|
15
|
-
def chain_to_pem
|
16
|
-
x509_chain.map(&:to_pem).join
|
17
|
-
end
|
18
|
-
|
19
|
-
def x509_fullchain
|
20
|
-
[x509, *x509_chain]
|
21
|
-
end
|
22
|
-
|
23
|
-
def fullchain_to_pem
|
24
|
-
x509_fullchain.map(&:to_pem).join
|
25
|
-
end
|
26
|
-
|
27
|
-
def common_name
|
28
|
-
x509.subject.to_a.find { |name, _, _| name == 'CN' }[1]
|
29
|
-
end
|
30
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Acme::Client::Resources::Challenges::TLSSNI01 < Acme::Client::Resources::Challenges::Base
|
4
|
-
CHALLENGE_TYPE = 'tls-sni-01'.freeze
|
5
|
-
DIGEST = OpenSSL::Digest::SHA256
|
6
|
-
|
7
|
-
def hostname
|
8
|
-
digest = DIGEST.hexdigest(authorization_key)
|
9
|
-
"#{digest[0..31]}.#{digest[32..64]}.acme.invalid"
|
10
|
-
end
|
11
|
-
|
12
|
-
def certificate
|
13
|
-
self_sign_certificate.certificate
|
14
|
-
end
|
15
|
-
|
16
|
-
def private_key
|
17
|
-
self_sign_certificate.private_key
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def self_sign_certificate
|
23
|
-
@self_sign_certificate ||= Acme::Client::SelfSignCertificate.new(subject_alt_names: [hostname])
|
24
|
-
end
|
25
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
class Acme::Client::Resources::Registration
|
2
|
-
attr_reader :id, :key, :contact, :uri, :next_uri, :recover_uri, :term_of_service_uri
|
3
|
-
|
4
|
-
def initialize(client, response)
|
5
|
-
@client = client
|
6
|
-
@uri = response.headers['location']
|
7
|
-
assign_links(response.headers['Link'])
|
8
|
-
assign_attributes(response.body)
|
9
|
-
end
|
10
|
-
|
11
|
-
def get_terms
|
12
|
-
return unless @term_of_service_uri
|
13
|
-
|
14
|
-
@client.connection.get(@term_of_service_uri).body
|
15
|
-
end
|
16
|
-
|
17
|
-
def agree_terms
|
18
|
-
return true unless @term_of_service_uri
|
19
|
-
|
20
|
-
response = @client.connection.post(@uri, resource: 'reg', agreement: @term_of_service_uri)
|
21
|
-
response.success?
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def assign_links(links)
|
27
|
-
@next_uri = links['next']
|
28
|
-
@recover_uri = links['recover']
|
29
|
-
@term_of_service_uri = links['terms-of-service']
|
30
|
-
end
|
31
|
-
|
32
|
-
def assign_attributes(body)
|
33
|
-
@id = body['id']
|
34
|
-
@key = body['key']
|
35
|
-
@contact = body['contact']
|
36
|
-
end
|
37
|
-
end
|