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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66b791acbcafdeb9a0cc7b1fc56977ff235771db
4
- data.tar.gz: fcc5bdffc2e7278301de2ad97745a0dd1400915e
3
+ metadata.gz: 9f9c42703db71639a5e1f5f01ce79d793343bd13
4
+ data.tar.gz: a6e9dbb2adcd1246db1c67417b8b4ac3e54fbe2c
5
5
  SHA512:
6
- metadata.gz: 1dda0e5460db94b43231b033513b28c6a88b7af1be4c201bd360b5fda5dab159eb684305177636f6a3327a5ef6b54359045c1f12a87c62312a510dddae3b8345
7
- data.tar.gz: c5d7b4f69f4455c56fdeb9611b66757e981ebd870582fca017656a6f9635bfd223cc1c2231c67a159682f66e369dad18e3ed81e259c9d931d4f0f5b11a3972de
6
+ metadata.gz: 62053ee6b500dbf4d239919f7b6522f47459fa08f78e62395877cde46dccc35ba3de028bdb032e305dd890c90b86de5d2e4b6b2c34f48e517198eca0ac162081
7
+ data.tar.gz: fca377ddccf602238402cbe0d49febe228690dd68fc4922a135b515d6178c8e0843c08225bb371853723717ce6794b22ca3399c505f804f0cf74a9e16acf9117
data/Gemfile CHANGED
@@ -1,8 +1,7 @@
1
1
  source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in acme-client.gemspec
4
2
  gemspec
5
3
 
6
4
  group :development, :test do
7
5
  gem 'pry'
6
+ gem 'ruby-prof', require: false
8
7
  end
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-client'
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)
@@ -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'
@@ -1,14 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "acme-client"
3
+ require 'bundler/setup'
4
+ require 'acme-client'
5
5
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
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
@@ -3,5 +3,3 @@ set -euo pipefail
3
3
  IFS=$'\n\t'
4
4
 
5
5
  bundle install
6
-
7
- # Do any other automated setup that you need to do here
@@ -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'
@@ -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::Certificate
1
+ class Acme::Client::Certificate
2
2
  extend Forwardable
3
3
 
4
4
  attr_reader :x509, :x509_chain, :request
@@ -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 :csr, :private_key, :common_name, :names, :subject
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
- @csr = generate
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="([\w_-]+)"/).captures.first
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, env.body['detail']
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
@@ -0,0 +1,5 @@
1
+ module Acme::Client::Resources; end
2
+
3
+ require 'acme/client/resources/registration'
4
+ require 'acme/client/resources/challenges'
5
+ require 'acme/client/resources/authorization'
@@ -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
 
@@ -0,0 +1,5 @@
1
+ module Acme::Client::Resources::Challenges; end
2
+
3
+ require 'acme/client/resources/challenges/base'
4
+ require 'acme/client/resources/challenges/http01'
5
+ require 'acme/client/resources/challenges/dns01'
@@ -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
@@ -1,4 +1,4 @@
1
- class Acme::Resources::Registration
1
+ class Acme::Client::Resources::Registration
2
2
  attr_reader :id, :key, :contact, :uri, :next_uri, :recover_uri, :term_of_service_uri
3
3
 
4
4
  def initialize(client, response)
@@ -1,5 +1,5 @@
1
1
  module Acme
2
2
  class Client
3
- VERSION = '0.2.2'
3
+ VERSION = '0.2.3'
4
4
  end
5
5
  end
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.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-07 00:00:00.000000000 Z
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/crypto.rb
163
- - lib/acme/error.rb
164
- - lib/acme/faraday_middleware.rb
165
- - lib/acme/resources.rb
166
- - lib/acme/resources/authorization.rb
167
- - lib/acme/resources/challenges.rb
168
- - lib/acme/resources/challenges/base.rb
169
- - lib/acme/resources/challenges/dns01.rb
170
- - lib/acme/resources/challenges/http01.rb
171
- - lib/acme/resources/registration.rb
172
- - lib/acme/version.rb
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
@@ -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
@@ -1,4 +0,0 @@
1
- module Acme::Resources; end
2
- require 'acme/resources/registration'
3
- require 'acme/resources/challenges'
4
- require 'acme/resources/authorization'
@@ -1,4 +0,0 @@
1
- module Acme::Resources::Challenges; end
2
- require 'acme/resources/challenges/base'
3
- require 'acme/resources/challenges/http01'
4
- require 'acme/resources/challenges/dns01'