acme-client 0.2.2 → 0.2.3
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 +4 -4
- data/Gemfile +1 -2
- data/README.md +3 -3
- data/acme-client.gemspec +2 -2
- data/bin/console +4 -11
- data/bin/setup +0 -2
- data/lib/acme-client.rb +7 -7
- data/lib/acme/client.rb +26 -10
- data/lib/acme/{certificate.rb → client/certificate.rb} +1 -1
- data/lib/acme/{certificate_request.rb → client/certificate_request.rb} +5 -3
- data/lib/acme/{crypto.rb → client/crypto.rb} +11 -9
- data/lib/acme/client/error.rb +12 -0
- data/lib/acme/{faraday_middleware.rb → client/faraday_middleware.rb} +8 -8
- data/lib/acme/client/resources.rb +5 -0
- data/lib/acme/{resources → client/resources}/authorization.rb +3 -3
- data/lib/acme/client/resources/challenges.rb +5 -0
- data/lib/acme/{resources → client/resources}/challenges/base.rb +2 -2
- data/lib/acme/{resources → client/resources}/challenges/dns01.rb +3 -3
- data/lib/acme/{resources → client/resources}/challenges/http01.rb +2 -2
- data/lib/acme/{resources → client/resources}/registration.rb +1 -1
- data/lib/acme/{version.rb → client/version.rb} +1 -1
- metadata +21 -15
- data/lib/acme/error.rb +0 -12
- data/lib/acme/resources.rb +0 -4
- data/lib/acme/resources/challenges.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f9c42703db71639a5e1f5f01ce79d793343bd13
|
4
|
+
data.tar.gz: a6e9dbb2adcd1246db1c67417b8b4ac3e54fbe2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62053ee6b500dbf4d239919f7b6522f47459fa08f78e62395877cde46dccc35ba3de028bdb032e305dd890c90b86de5d2e4b6b2c34f48e517198eca0ac162081
|
7
|
+
data.tar.gz: fca377ddccf602238402cbe0d49febe228690dd68fc4922a135b515d6178c8e0843c08225bb371853723717ce6794b22ca3399c505f804f0cf74a9e16acf9117
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -18,7 +18,7 @@ private_key = OpenSSL::PKey::RSA.new(2048)
|
|
18
18
|
endpoint = 'https://acme-v01.api.letsencrypt.org/'
|
19
19
|
|
20
20
|
# Initialize the client
|
21
|
-
require 'acme
|
21
|
+
require 'acme/client'
|
22
22
|
client = Acme::Client.new(private_key: private_key, endpoint: endpoint)
|
23
23
|
|
24
24
|
# If the private key is not known to the server, we need to register it for the first time.
|
@@ -67,12 +67,12 @@ challenge.verify_status # => 'valid'
|
|
67
67
|
|
68
68
|
# We're going to need a certificate signing request. If not explicitly
|
69
69
|
# specified, the first name listed becomes the common name.
|
70
|
-
csr = Acme::CertificateRequest.new(names: %w[example.org www.example.org])
|
70
|
+
csr = Acme::Client::CertificateRequest.new(names: %w[example.org www.example.org])
|
71
71
|
|
72
72
|
# We can now request a certificate, you can pass anything that returns
|
73
73
|
# a valid DER encoded CSR when calling to_der on it, for example a
|
74
74
|
# OpenSSL::X509::Request too.
|
75
|
-
certificate = client.new_certificate(csr) # => #<Acme::Certificate ....>
|
75
|
+
certificate = client.new_certificate(csr) # => #<Acme::Client::Certificate ....>
|
76
76
|
|
77
77
|
# Save the certificate and key
|
78
78
|
File.write("privkey.pem", certificate.request.private_key.to_pem)
|
data/acme-client.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'acme/version'
|
4
|
+
require 'acme/client/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'acme-client'
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
16
|
spec.require_paths = ['lib']
|
17
17
|
|
18
|
-
spec.add_development_dependency 'bundler', '>= 1.6.9'
|
18
|
+
spec.add_development_dependency 'bundler', '~> 1.6', '>= 1.6.9'
|
19
19
|
spec.add_development_dependency 'rake', '~> 10.0'
|
20
20
|
spec.add_development_dependency 'rspec', '~> 3.3', '>= 3.3.0'
|
21
21
|
spec.add_development_dependency 'vcr', '~> 2.9', '>= 2.9.3'
|
data/bin/console
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'acme-client'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require "pry"
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start
|
6
|
+
require 'pry'
|
7
|
+
Pry.start
|
data/bin/setup
CHANGED
data/lib/acme-client.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Acme; end
|
1
|
+
module Acme; class Client; end; end
|
2
2
|
|
3
3
|
require 'faraday'
|
4
4
|
require 'json'
|
@@ -7,10 +7,10 @@ require 'openssl'
|
|
7
7
|
require 'digest'
|
8
8
|
require 'forwardable'
|
9
9
|
|
10
|
-
require 'acme/certificate'
|
11
|
-
require 'acme/certificate_request'
|
12
|
-
require 'acme/crypto'
|
10
|
+
require 'acme/client/certificate'
|
11
|
+
require 'acme/client/certificate_request'
|
12
|
+
require 'acme/client/crypto'
|
13
13
|
require 'acme/client'
|
14
|
-
require 'acme/resources'
|
15
|
-
require 'acme/faraday_middleware'
|
16
|
-
require 'acme/error'
|
14
|
+
require 'acme/client/resources'
|
15
|
+
require 'acme/client/faraday_middleware'
|
16
|
+
require 'acme/client/error'
|
data/lib/acme/client.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require "acme-client"
|
2
|
+
|
1
3
|
class Acme::Client
|
2
4
|
DEFAULT_ENDPOINT = 'http://127.0.0.1:4000'
|
3
5
|
DIRECTORY_DEFAULT = {
|
@@ -21,7 +23,7 @@ class Acme::Client
|
|
21
23
|
}
|
22
24
|
|
23
25
|
response = connection.post(@operation_endpoints.fetch('new-reg'), payload)
|
24
|
-
::Acme::Resources::Registration.new(self, response)
|
26
|
+
::Acme::Client::Resources::Registration.new(self, response)
|
25
27
|
end
|
26
28
|
|
27
29
|
def authorize(domain:)
|
@@ -34,7 +36,7 @@ class Acme::Client
|
|
34
36
|
}
|
35
37
|
|
36
38
|
response = connection.post(@operation_endpoints.fetch('new-authz'), payload)
|
37
|
-
::Acme::Resources::Authorization.new(self, response)
|
39
|
+
::Acme::Client::Resources::Authorization.new(self, response)
|
38
40
|
end
|
39
41
|
|
40
42
|
def new_certificate(csr)
|
@@ -44,9 +46,30 @@ class Acme::Client
|
|
44
46
|
}
|
45
47
|
|
46
48
|
response = connection.post(@operation_endpoints.fetch('new-cert'), payload)
|
47
|
-
::Acme::Certificate.new(OpenSSL::X509::Certificate.new(response.body), fetch_chain(response), csr)
|
49
|
+
::Acme::Client::Certificate.new(OpenSSL::X509::Certificate.new(response.body), fetch_chain(response), csr)
|
50
|
+
end
|
51
|
+
|
52
|
+
def revoke_certificate(certificate)
|
53
|
+
payload = { resource: 'revoke-cert', certificate: Base64.urlsafe_encode64(certificate.to_der) }
|
54
|
+
endpoint = @operation_endpoints.fetch('revoke-cert')
|
55
|
+
response = connection.post(endpoint, payload)
|
56
|
+
response.success?
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.revoke_certificate(certificate, *arguments)
|
60
|
+
client = new(*arguments)
|
61
|
+
client.revoke_certificate(certificate)
|
62
|
+
end
|
63
|
+
|
64
|
+
def connection
|
65
|
+
@connection ||= Faraday.new(@endpoint) do |configuration|
|
66
|
+
configuration.use Acme::Client::FaradayMiddleware, client: self
|
67
|
+
configuration.adapter Faraday.default_adapter
|
68
|
+
end
|
48
69
|
end
|
49
70
|
|
71
|
+
private
|
72
|
+
|
50
73
|
def fetch_chain(response, limit=10)
|
51
74
|
if limit == 0 || response.headers["link"].nil? || response.headers["link"]["up"].nil?
|
52
75
|
[]
|
@@ -56,13 +79,6 @@ class Acme::Client
|
|
56
79
|
end
|
57
80
|
end
|
58
81
|
|
59
|
-
def connection
|
60
|
-
@connection ||= Faraday.new(@endpoint) do |configuration|
|
61
|
-
configuration.use Acme::FaradayMiddleware, client: self
|
62
|
-
configuration.adapter Faraday.default_adapter
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
82
|
def load_directory!
|
67
83
|
@operation_endpoints = if @directory_uri
|
68
84
|
response = connection.get(@directory_uri)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Acme::CertificateRequest
|
1
|
+
class Acme::Client::CertificateRequest
|
2
2
|
extend Forwardable
|
3
3
|
|
4
4
|
DEFAULT_KEY_LENGTH = 2048
|
@@ -21,7 +21,7 @@ class Acme::CertificateRequest
|
|
21
21
|
"L" => OpenSSL::ASN1::UTF8STRING
|
22
22
|
}.freeze
|
23
23
|
|
24
|
-
attr_reader :
|
24
|
+
attr_reader :private_key, :common_name, :names, :subject
|
25
25
|
|
26
26
|
def_delegators :csr, :to_pem, :to_der
|
27
27
|
|
@@ -43,8 +43,10 @@ class Acme::CertificateRequest
|
|
43
43
|
|
44
44
|
@subject[SUBJECT_KEYS[:common_name]] ||= @common_name
|
45
45
|
validate_subject
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
+
def csr
|
49
|
+
@csr ||= generate
|
48
50
|
end
|
49
51
|
|
50
52
|
private
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Acme::Crypto
|
1
|
+
class Acme::Client::Crypto
|
2
2
|
attr_reader :private_key
|
3
3
|
|
4
4
|
def initialize(private_key)
|
@@ -13,19 +13,21 @@ class Acme::Crypto
|
|
13
13
|
jwt.to_json(syntax: :flattened)
|
14
14
|
end
|
15
15
|
|
16
|
-
def jwk
|
17
|
-
@jwk ||= JSON::JWK.new(public_key)
|
18
|
-
end
|
19
|
-
|
20
16
|
def thumbprint
|
21
17
|
jwk.thumbprint
|
22
18
|
end
|
23
19
|
|
24
|
-
def public_key
|
25
|
-
@public_key ||= private_key.public_key
|
26
|
-
end
|
27
|
-
|
28
20
|
def digest
|
29
21
|
OpenSSL::Digest::SHA256.new
|
30
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def jwk
|
27
|
+
@jwk ||= JSON::JWK.new(public_key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def public_key
|
31
|
+
@public_key ||= private_key.public_key
|
32
|
+
end
|
31
33
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Acme::Client::Error < StandardError
|
2
|
+
class NotFound < Acme::Client::Error; end
|
3
|
+
class BadCSR < Acme::Client::Error; end
|
4
|
+
class BadNonce < Acme::Client::Error; end
|
5
|
+
class Connection < Acme::Client::Error; end
|
6
|
+
class Dnssec < Acme::Client::Error; end
|
7
|
+
class Malformed < Acme::Client::Error; end
|
8
|
+
class ServerInternal < Acme::Client::Error; end
|
9
|
+
class Acme::Tls < Acme::Client::Error; end
|
10
|
+
class Unauthorized < Acme::Client::Error; end
|
11
|
+
class UnknownHost < Acme::Client::Error; end
|
12
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Acme::FaradayMiddleware < Faraday::Middleware
|
1
|
+
class Acme::Client::FaradayMiddleware < Faraday::Middleware
|
2
2
|
attr_reader :env, :response, :client
|
3
3
|
|
4
4
|
def initialize(app, client:)
|
@@ -13,7 +13,7 @@ class Acme::FaradayMiddleware < Faraday::Middleware
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def on_complete(env)
|
16
|
-
raise Acme::Error::NotFound, env.url.to_s if env.status == 404
|
16
|
+
raise Acme::Client::Error::NotFound, env.url.to_s if env.status == 404
|
17
17
|
|
18
18
|
nonces << env.response_headers['replay-nonce']
|
19
19
|
|
@@ -27,7 +27,7 @@ class Acme::FaradayMiddleware < Faraday::Middleware
|
|
27
27
|
link_header = env.response_headers['Link']
|
28
28
|
links = link_header.split(', ').map do |entry|
|
29
29
|
link = entry.match(/<(.*?)>;/).captures.first
|
30
|
-
name = entry.match(/rel="([\
|
30
|
+
name = entry.match(/rel="([\w-]+)"/).captures.first
|
31
31
|
[name, link]
|
32
32
|
end
|
33
33
|
|
@@ -37,10 +37,10 @@ class Acme::FaradayMiddleware < Faraday::Middleware
|
|
37
37
|
return if env.success?
|
38
38
|
|
39
39
|
error_name = env.body['type'].gsub('urn:acme:error:', '').classify
|
40
|
-
error_class = if Acme::Error.qualified_const_defined?(error_name)
|
41
|
-
"Acme::Error::#{error_name}".constantize
|
40
|
+
error_class = if Acme::Client::Error.qualified_const_defined?(error_name)
|
41
|
+
"Acme::Client::Error::#{error_name}".constantize
|
42
42
|
else
|
43
|
-
Acme::Error
|
43
|
+
Acme::Client::Error
|
44
44
|
end
|
45
45
|
|
46
46
|
message = if env.body.is_a? Hash
|
@@ -49,7 +49,7 @@ class Acme::FaradayMiddleware < Faraday::Middleware
|
|
49
49
|
"Error message: #{env.body}"
|
50
50
|
end
|
51
51
|
|
52
|
-
raise error_class,
|
52
|
+
raise error_class, message
|
53
53
|
end
|
54
54
|
|
55
55
|
private
|
@@ -76,6 +76,6 @@ class Acme::FaradayMiddleware < Faraday::Middleware
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def crypto
|
79
|
-
@crypto ||= Acme::Crypto.new(private_key)
|
79
|
+
@crypto ||= Acme::Client::Crypto.new(private_key)
|
80
80
|
end
|
81
81
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
class Acme::Resources::Authorization
|
2
|
-
HTTP01 = Acme::Resources::Challenges::HTTP01
|
3
|
-
DNS01 = Acme::Resources::Challenges::DNS01
|
1
|
+
class Acme::Client::Resources::Authorization
|
2
|
+
HTTP01 = Acme::Client::Resources::Challenges::HTTP01
|
3
|
+
DNS01 = Acme::Client::Resources::Challenges::DNS01
|
4
4
|
|
5
5
|
attr_reader :domain, :status, :http01, :dns01
|
6
6
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Acme::Resources::Challenges::Base
|
1
|
+
class Acme::Client::Resources::Challenges::Base
|
2
2
|
|
3
3
|
attr_reader :client, :status, :uri, :token, :error
|
4
4
|
|
@@ -28,6 +28,6 @@ class Acme::Resources::Challenges::Base
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def crypto
|
31
|
-
@crypto ||= Acme::Crypto.new(@client.private_key)
|
31
|
+
@crypto ||= Acme::Client::Crypto.new(@client.private_key)
|
32
32
|
end
|
33
33
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
class Acme::Resources::Challenges::DNS01 < Acme::Resources::Challenges::Base
|
2
|
-
RECORD_NAME = '_acme-challenge'
|
3
|
-
RECORD_TYPE = 'TXT'
|
1
|
+
class Acme::Client::Resources::Challenges::DNS01 < Acme::Client::Resources::Challenges::Base
|
2
|
+
RECORD_NAME = '_acme-challenge'.freeze
|
3
|
+
RECORD_TYPE = 'TXT'.freeze
|
4
4
|
|
5
5
|
def record_name
|
6
6
|
RECORD_NAME
|
@@ -1,5 +1,5 @@
|
|
1
|
-
class Acme::Resources::Challenges::HTTP01 < Acme::Resources::Challenges::Base
|
2
|
-
CONTENT_TYPE = 'text/plain'
|
1
|
+
class Acme::Client::Resources::Challenges::HTTP01 < Acme::Client::Resources::Challenges::Base
|
2
|
+
CONTENT_TYPE = 'text/plain'.freeze
|
3
3
|
|
4
4
|
def content_type
|
5
5
|
CONTENT_TYPE
|
metadata
CHANGED
@@ -1,19 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acme-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Barbier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-12-
|
11
|
+
date: 2015-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
17
20
|
- - ">="
|
18
21
|
- !ruby/object:Gem::Version
|
19
22
|
version: 1.6.9
|
@@ -21,6 +24,9 @@ dependencies:
|
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.6'
|
24
30
|
- - ">="
|
25
31
|
- !ruby/object:Gem::Version
|
26
32
|
version: 1.6.9
|
@@ -156,20 +162,20 @@ files:
|
|
156
162
|
- bin/console
|
157
163
|
- bin/setup
|
158
164
|
- lib/acme-client.rb
|
159
|
-
- lib/acme/certificate.rb
|
160
|
-
- lib/acme/certificate_request.rb
|
161
165
|
- lib/acme/client.rb
|
162
|
-
- lib/acme/
|
163
|
-
- lib/acme/
|
164
|
-
- lib/acme/
|
165
|
-
- lib/acme/
|
166
|
-
- lib/acme/
|
167
|
-
- lib/acme/resources
|
168
|
-
- lib/acme/resources/
|
169
|
-
- lib/acme/resources/challenges
|
170
|
-
- lib/acme/resources/challenges/
|
171
|
-
- lib/acme/resources/
|
172
|
-
- lib/acme/
|
166
|
+
- lib/acme/client/certificate.rb
|
167
|
+
- lib/acme/client/certificate_request.rb
|
168
|
+
- lib/acme/client/crypto.rb
|
169
|
+
- lib/acme/client/error.rb
|
170
|
+
- lib/acme/client/faraday_middleware.rb
|
171
|
+
- lib/acme/client/resources.rb
|
172
|
+
- lib/acme/client/resources/authorization.rb
|
173
|
+
- lib/acme/client/resources/challenges.rb
|
174
|
+
- lib/acme/client/resources/challenges/base.rb
|
175
|
+
- lib/acme/client/resources/challenges/dns01.rb
|
176
|
+
- lib/acme/client/resources/challenges/http01.rb
|
177
|
+
- lib/acme/client/resources/registration.rb
|
178
|
+
- lib/acme/client/version.rb
|
173
179
|
homepage: http://github.com/unixcharles/acme-client
|
174
180
|
licenses:
|
175
181
|
- MIT
|
data/lib/acme/error.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
class Acme::Error < StandardError
|
2
|
-
class NotFound < Acme::Error; end
|
3
|
-
class BadCSR < Acme::Error; end
|
4
|
-
class BadNonce < Acme::Error; end
|
5
|
-
class Connection < Acme::Error; end
|
6
|
-
class Dnssec < Acme::Error; end
|
7
|
-
class Malformed < Acme::Error; end
|
8
|
-
class ServerInternal < Acme::Error; end
|
9
|
-
class Acme::Tls < Acme::Error; end
|
10
|
-
class Unauthorized < Acme::Error; end
|
11
|
-
class UnknownHost < Acme::Error; end
|
12
|
-
end
|
data/lib/acme/resources.rb
DELETED