letscert 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: 7794f56c134e1437cbb2d89cf9bcf3b2da6f5bc1
4
- data.tar.gz: 735bb555113c95eb110500c3fcd43b435c7e41aa
3
+ metadata.gz: 13246f0cc94eb264f9dcc01fb55a2e55250d5e63
4
+ data.tar.gz: d543f27b0a2d55a1e0fc17950bb662bbfbb3a932
5
5
  SHA512:
6
- metadata.gz: 8d1369f91acfe830d02461a442eeac66d14995944996dac69c1d6120c42077566701eb0aca6bdc34ec9a0a17e82d2765a315086ba5ad0d97b7c58772701e0102
7
- data.tar.gz: 5cc07fe0b35bab4b652ac29a1807ae39b62cae562fcbb73dd8fc9320f2bbef3be338471094baca01bdc41c9309fb6c8b375080b01013c91538467ecaddbae05b
6
+ metadata.gz: ebbdc254cd7cfea90f1b23308673a839baeaa564450dc18fa5340ed30a8fa5e93e84180fdbe66360f70db449671bd276352c3a2081a5aa8b76b58604f341df7e
7
+ data.tar.gz: 4ae2cdc6a2fa18eb7e9606c909e6260cee6878000ab5c601ce0482352e15333e8bd048a8b33d2614459d0c9ba36dc7c72d753936e21489a584fafb9894457720
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/letscert.svg)](https://badge.fury.io/rb/letscert)
2
+
1
3
  # letscert
2
4
  A simple `Let's Encrypt` client in ruby.
3
5
 
@@ -7,12 +9,17 @@ in Ruby.
7
9
 
8
10
  # Usage
9
11
 
10
- Generate a key pair and get signed certificate
12
+ Generate a key pair and get signed certificate:
13
+ ```bash
14
+ letscert -d example.com:/var/www/example.com/html -f account_key.json -f key.pem -f cert.pem -f fullchain.pem
15
+ ```
16
+
17
+ Generate a key pair and get a signed certificate for multi-domains:
11
18
  ```bash
12
- letscert -d example.com:/var/www/example.com/html -f key.pem -f cert.pem -f fullchain.pem
19
+ letscert -d example.com -d www.example.com --default_root /var/www/html -f account_key.json -f key.pem -f cert.pem -f fullchain.pem
13
20
  ```
14
21
 
15
- The command is the same for certificate renewal.
22
+ Commands are the sames for certificate renewal.
16
23
 
17
24
  # What `letscert` do
18
25
 
@@ -30,4 +37,4 @@ The command is the same for certificate renewal.
30
37
  * 2 in case of errors.
31
38
 
32
39
  # Todo
33
- Add support to revocation.
40
+ Add support to revocation.
@@ -54,15 +54,17 @@ module LetsCert
54
54
  key = data[:key]
55
55
  else
56
56
  logger.info { 'Generate new private key' }
57
- key = OpenSSL::PKey::RSA.generate(@options[:cert_key_size])
57
+ key = OpenSSL::PKey::RSA.generate(options[:cert_key_size])
58
58
  end
59
59
 
60
- csr = Acme::Client::CertificateRequest.new(names: roots.keys, private_key: key)
60
+ csr = Acme::Client::CertificateRequest.new(names: roots.keys,
61
+ private_key: key)
61
62
  cert = client.new_certificate(csr)
62
63
 
63
- IOPlugin.registered.each do |name, plugin|
64
- plugin.save( account_key: client.private_key, key: key, cert: cert.x509,
65
- chain: cert.x509_chain)
64
+ options[:files].each do |plugname|
65
+ IOPlugin.registered[plugname].save(account_key: client.private_key,
66
+ key: key, cert: cert.x509,
67
+ chain: cert.x509_chain)
66
68
  end
67
69
  end
68
70
 
@@ -19,8 +19,7 @@
19
19
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
- require 'json'
23
- require 'base64'
22
+ require 'json/jwt'
24
23
  require_relative 'loggable'
25
24
 
26
25
  module LetsCert
@@ -145,43 +144,14 @@ module LetsCert
145
144
  def load_jwk(data)
146
145
  return nil if data.empty?
147
146
 
148
- hsh = JSON.parse(data)
149
-
150
- key = OpenSSL::PKey::RSA.new
151
- key.n = OpenSSL::BN.new(Base64.strict_decode64(hsh['n']))
152
- key.e = OpenSSL::BN.new(Base64.strict_decode64(hsh['e']))
153
- key.d = OpenSSL::BN.new(Base64.strict_decode64(hsh['e']))
154
- key.p = OpenSSL::BN.new(Base64.strict_decode64(hsh['p']))
155
- key.q = OpenSSL::BN.new(Base64.strict_decode64(hsh['q']))
156
- key.dmp1 = OpenSSL::BN.new(Base64.strict_decode64(hsh['dp']))
157
- key.dmq1 = OpenSSL::BN.new(Base64.strict_decode64(hsh['dq']))
158
- key.iqmp = OpenSSL::BN.new(Base64.strict_decode64(hsh['qi']))
159
-
160
- key
147
+ JSON::JWK.new(JSON.parse(data)).to_key
161
148
  end
162
149
 
163
150
  # Dump crypto data (key) to a JSON-encoded string
164
- # @param [OpenSSL::PKey] jwk
151
+ # @param [OpenSSL::PKey] key
165
152
  # @return [String]
166
- def dump_jwk(jwk)
167
- hsh = jwk.params
168
-
169
- # Add and rename some fields to be compatible with simp_le
170
- hsh['kty'] = 'RSA'
171
- hsh['qi'] = hsh['iqmp'].dup
172
- hsh['dp'] = hsh['dmp1'].dup
173
- hsh['dq'] = hsh['dmq1'].dup
174
- hsh.delete('iqmp')
175
- hsh.delete('dmpl')
176
- hsh.delete('dmql')
177
- hsh.rehash
178
-
179
- hsh.each_key do |key|
180
- if hsh[key].is_a?(OpenSSL::BN)
181
- hsh[key] = Base64.strict_encode64(hsh[key].to_s)
182
- end
183
- end
184
- hsh.to_json
153
+ def dump_jwk(key)
154
+ key.to_jwk.to_json
185
155
  end
186
156
  end
187
157
 
data/lib/letscert.rb CHANGED
@@ -24,7 +24,7 @@
24
24
  module LetsCert
25
25
 
26
26
  # Letscert version number
27
- VERSION = '0.2.2'
27
+ VERSION = '0.2.3'
28
28
 
29
29
 
30
30
  # Base error class
@@ -0,0 +1 @@
1
+ {"kty":"RSA","e":"AQAB","n":"ugv1o2Fg5N-RBScXrLpRRoPgDjFgHcM_BD2fHZYzXJ4k1AnspAgS-soaWuoN0WK4mwRsSGwF7cemLEA1zZiCpc6Q3WUxLDsM8oF8P_S0euAEhe8FQPON3vtNqYth2yPqAQ4-me43mZyXS94yzTrCVjowlnZsdaA54uUW0AxOD_0","d":"Qo-6zzwspVXTFYvZ7YMvRtIxnAJQR_Wtmv_M6JHvSEiQFoiCcGEvISijazlnvizarSNU9kgnit2t9xD17tuMidbqdPC0x0mkJ6BszB7lau6Nzfz6ACSqtH8eKmkGDBJTnRqzg45Z6-3-gQ9vlmvc3T029Gv7xfA-XOt_cNgFnGE","p":"7nhrSRbf6FZ6LA2FKzcdFOTSI7UlgEwWsrSC_7pyzYyXJC44crlWUDxxJJXNeC9OyOEJOXlgn-0hShAWkl9-CQ","q":"x7kFmj6GYbh0SaLeg9CFhnY-y_UMO9wFxu0NLi2JgL31gvIDrKGJYiSZ3xESi6FwpmHX_vbtFXpZXBbvMy0_VQ"}
@@ -0,0 +1,104 @@
1
+ require_relative 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ module LetsCert
5
+
6
+ describe IOPlugin do
7
+
8
+ it '.empty_data always returns the same hash' do
9
+ hsh = IOPlugin.empty_data
10
+
11
+ expect(hsh.keys.size).to eq(4)
12
+ [:account_key, :key, :cert, :chain].each do |key|
13
+ expect(hsh.keys).to include(key)
14
+ expect(hsh[key]).to be_nil
15
+ end
16
+ end
17
+
18
+ it '.register registers known subclasses' do
19
+ names = %w(account_key.json key.pem key.der chain.pem fullchain.pem)
20
+ names += %w(cert.pem cert.der)
21
+
22
+ expect(IOPlugin.registered.size).to eq(names.size)
23
+
24
+ names.each do |name|
25
+ expect(IOPlugin.registered.keys).to include(name)
26
+ end
27
+ end
28
+
29
+ it '.register may register new classes' do
30
+ class NewIO < IOPlugin;end
31
+ IOPlugin.register(NewIO, 'newio')
32
+
33
+ expect(IOPlugin.registered.keys).to include('newio')
34
+ expect(IOPlugin.registered['newio']).to be_a(NewIO)
35
+ end
36
+
37
+ end
38
+
39
+ describe JWKIOPluginMixin do
40
+
41
+ class Test; include JWKIOPluginMixin; end
42
+
43
+ let(:test) { Test.new }
44
+
45
+ it "#load_jwk loads a RSA key from a JSON Web Key raw string" do
46
+ jwk = File.read(File.join(File.dirname(__FILE__), 'test.json'))
47
+ key = test.load_jwk(jwk)
48
+
49
+ expect(key).to be_a(OpenSSL::PKey::PKey)
50
+ end
51
+
52
+ it "#dump_jwk dumps a RSA key to a JSON Web Key raw string" do
53
+ jwk = File.read(File.join(File.dirname(__FILE__), 'test.json'))
54
+ key = test.load_jwk(jwk)
55
+
56
+ jwk2 = test.dump_jwk(key)
57
+ expect(jwk2).to eq(jwk)
58
+ end
59
+ end
60
+
61
+ describe AccountKey do
62
+
63
+ before(:all) { IOPlugin.logger = Logger.new('/dev/null') }
64
+
65
+ let(:ak) { IOPlugin.registered['account_key.json'] }
66
+
67
+ it 'persist account_key' do
68
+ persisted = ak.persisted
69
+ expect(persisted[:account_key]).to be(true)
70
+ end
71
+
72
+ it "#load account key from account_key.json file" do
73
+ expect(ak).to be_a(AccountKey)
74
+
75
+ pwd = FileUtils.pwd
76
+ FileUtils.cd File.dirname(__FILE__)
77
+
78
+ begin
79
+ content = ak.load
80
+ expect(content).to be_a(Hash)
81
+ expect(content.keys.size).to eq(1)
82
+ expect(content[:account_key]).to be_a(OpenSSL::PKey::PKey)
83
+ rescue Exception
84
+ raise
85
+ ensure
86
+ FileUtils.cd pwd
87
+ end
88
+ end
89
+
90
+ it "#save account key to account_key.json file" do
91
+ data = { account_key: OpenSSL::PKey::RSA.new(1024) }
92
+ ak.save(data)
93
+ begin
94
+ expect(File.exist?('account_key.json')).to be_truthy
95
+ rescue Exception
96
+ raise
97
+ ensure
98
+ File.unlink('account_key.json')
99
+ end
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,16 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module LetsCert
4
+
5
+ describe IOPlugin do
6
+
7
+ it '.empty_data always returns the same hash' do
8
+ hsh = IOPlugin.empty_data
9
+
10
+ expect(hsh.keys.size).to eq(4)
11
+ expect(hsh.keys).to include(:account_key)
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module LetsCert
4
+
5
+ describe Loggable do
6
+
7
+ it 'extend a class to add loggability' do
8
+ class TestA; include Loggable; end
9
+
10
+ expect(TestA.methods).to include(:logger=)
11
+
12
+ my_logger = Logger.new(STDERR)
13
+ TestA.logger = my_logger
14
+ expect(TestA.new.logger).to eq(my_logger)
15
+ end
16
+
17
+ it 'extend a class and its subclasses to add loggability' do
18
+ class TestA; include Loggable; end
19
+ class TestB < TestA; end
20
+
21
+ expect(TestA.methods).to include(:logger=)
22
+ expect(TestB.methods).to include(:logger=)
23
+
24
+ my_logger = Logger.new(STDERR)
25
+ TestA.logger = my_logger
26
+ expect(TestA.new.logger).to eq(my_logger)
27
+ expect(TestB.new.logger).to eq(my_logger)
28
+ end
29
+
30
+ end
31
+
32
+ end
@@ -0,0 +1 @@
1
+ require_relative 'spec_helper'
@@ -0,0 +1,2 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'letscert'
@@ -0,0 +1 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
data/spec/test.json ADDED
@@ -0,0 +1 @@
1
+ {"kty":"RSA","e":"AQAB","n":"ugv1o2Fg5N-RBScXrLpRRoPgDjFgHcM_BD2fHZYzXJ4k1AnspAgS-soaWuoN0WK4mwRsSGwF7cemLEA1zZiCpc6Q3WUxLDsM8oF8P_S0euAEhe8FQPON3vtNqYth2yPqAQ4-me43mZyXS94yzTrCVjowlnZsdaA54uUW0AxOD_0","d":"Qo-6zzwspVXTFYvZ7YMvRtIxnAJQR_Wtmv_M6JHvSEiQFoiCcGEvISijazlnvizarSNU9kgnit2t9xD17tuMidbqdPC0x0mkJ6BszB7lau6Nzfz6ACSqtH8eKmkGDBJTnRqzg45Z6-3-gQ9vlmvc3T029Gv7xfA-XOt_cNgFnGE","p":"7nhrSRbf6FZ6LA2FKzcdFOTSI7UlgEwWsrSC_7pyzYyXJC44crlWUDxxJJXNeC9OyOEJOXlgn-0hShAWkl9-CQ","q":"x7kFmj6GYbh0SaLeg9CFhnY-y_UMO9wFxu0NLi2JgL31gvIDrKGJYiSZ3xESi6FwpmHX_vbtFXpZXBbvMy0_VQ"}
data/tasks/gem.rake CHANGED
@@ -22,6 +22,7 @@ EOF
22
22
  s.executables = ['letscert']
23
23
 
24
24
  s.add_dependency 'acme-client', '~>0.3.0'
25
+ s.add_dependency 'json-jwt', '~>1.5'
25
26
  s.add_dependency 'yard', '~>0.8'
26
27
 
27
28
  #s.add_development_dependency 'rspec', '~>3.4'
data/tasks/spec.rake ADDED
@@ -0,0 +1,3 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letscert
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
  - Sylvain Daubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-05 00:00:00.000000000 Z
11
+ date: 2016-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: acme-client
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: json-jwt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.5'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: yard
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -55,13 +69,20 @@ files:
55
69
  - lib/letscert.rb
56
70
  - lib/letscert.rb~
57
71
  - lib/letscert/certificate.rb
58
- - lib/letscert/certificate.rb~
59
72
  - lib/letscert/io_plugin.rb
60
73
  - lib/letscert/loggable.rb
61
- - lib/letscert/loggable.rb~
62
74
  - lib/letscert/runner.rb
75
+ - spec/account_key.json
76
+ - spec/io_plugin_spec.rb
77
+ - spec/io_plugin_spec.rb~
78
+ - spec/loggable_spec.rb
79
+ - spec/loggable_spec.rb~
80
+ - spec/spec_helper.rb
81
+ - spec/spec_helper.rb~
82
+ - spec/test.json
63
83
  - tasks/gem.rake
64
84
  - tasks/gem.rake~
85
+ - tasks/spec.rake
65
86
  - tasks/yard.rake
66
87
  homepage: https://github.com/sdaubert/letscert
67
88
  licenses:
@@ -83,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
104
  version: '0'
84
105
  requirements: []
85
106
  rubyforge_project:
86
- rubygems_version: 2.2.2
107
+ rubygems_version: 2.4.5.1
87
108
  signing_key:
88
109
  specification_version: 4
89
110
  summary: letscert, a simple Let's Encrypt client
@@ -1,8 +0,0 @@
1
-
2
- module LetsCert
3
-
4
- # Class to handle ACME operations on certificates
5
- class Certificate
6
- end
7
-
8
- end
@@ -1,24 +0,0 @@
1
- module LetsCert
2
-
3
- module Loggable
4
-
5
- module ClassMethods
6
-
7
- # Set logger
8
- # @param [Logger] logger
9
- def self.logger=(logger)
10
- @@logger = logger
11
- end
12
-
13
- end
14
-
15
-
16
- # Get logger instance
17
- # @return [Logger]
18
- def logger
19
- @logger ||= self.class.class_variable_get(:@@logger)
20
- end
21
-
22
- end
23
-
24
- end