acme-client 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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