letscert 0.4.0 → 0.4.1
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
- checksums.yaml.gz.sig +0 -0
- data/.gitignore +22 -0
- data/Gemfile +3 -0
- data/README.md +21 -4
- data/Rakefile +11 -2
- data/certs/gem-public_cert.pem +22 -0
- data/{tasks/gem.rake → letscert.gemspec} +11 -13
- data/lib/letscert/certificate.rb +15 -4
- data/lib/letscert/io_plugin.rb +1 -0
- data/lib/letscert/loggable.rb +3 -2
- data/lib/letscert/runner.rb +4 -2
- data/lib/letscert/version.rb +6 -0
- data/lib/letscert.rb +1 -4
- data.tar.gz.sig +1 -0
- metadata +65 -25
- metadata.gz.sig +2 -0
- data/spec/account_key.json +0 -1
- data/spec/cert.der +0 -0
- data/spec/cert.pem +0 -32
- data/spec/certificate_spec.rb +0 -185
- data/spec/chain.pem +0 -27
- data/spec/fullchain.pem +0 -59
- data/spec/io_plugin_spec.rb +0 -387
- data/spec/key.der +0 -0
- data/spec/key.pem +0 -15
- data/spec/loggable_spec.rb +0 -32
- data/spec/runner_spec.rb +0 -127
- data/spec/spec_helper.rb +0 -28
- data/spec/test.json +0 -1
- data/tasks/spec.rake +0 -3
- data/tasks/yard.rake +0 -6
data/spec/certificate_spec.rb
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
require_relative 'spec_helper'
|
2
|
-
|
3
|
-
module LetsCert
|
4
|
-
|
5
|
-
describe Certificate do
|
6
|
-
|
7
|
-
before(:all) { Certificate.logger = Logger.new('/dev/null') }
|
8
|
-
|
9
|
-
before(:all) do
|
10
|
-
root_key = OpenSSL::PKey::RSA.new(512)
|
11
|
-
|
12
|
-
@domains = %w(example.org www.example.org)
|
13
|
-
|
14
|
-
key = OpenSSL::PKey::RSA.new(512)
|
15
|
-
@cert = OpenSSL::X509::Certificate.new
|
16
|
-
@cert.version = 2
|
17
|
-
@cert.serial = 2
|
18
|
-
@cert.issuer = OpenSSL::X509::Name.parse "/DC=letscert/CN=CA"
|
19
|
-
@cert.public_key = key.public_key
|
20
|
-
@cert.not_before = Time.now
|
21
|
-
# 20 days validity
|
22
|
-
@cert.not_after = @cert.not_before + 20 * 24 * 60 * 60
|
23
|
-
ef = OpenSSL::X509::ExtensionFactory.new
|
24
|
-
ef.subject_certificate = @cert
|
25
|
-
@domains.each do |domain|
|
26
|
-
@cert.add_extension(ef.create_extension('subjectAltName',
|
27
|
-
"DNS:#{domain}",
|
28
|
-
false))
|
29
|
-
end
|
30
|
-
@cert.sign(root_key, OpenSSL::Digest::SHA256.new)
|
31
|
-
|
32
|
-
# minimum size accepted by ACME server
|
33
|
-
@account_key2048 = OpenSSL::PKey::RSA.new(2048)
|
34
|
-
end
|
35
|
-
|
36
|
-
let(:certificate) { Certificate.new(@cert) }
|
37
|
-
|
38
|
-
context '#get' do
|
39
|
-
|
40
|
-
it 'checks all domains have a root' do
|
41
|
-
runner = Runner.new
|
42
|
-
ARGV.clear
|
43
|
-
|
44
|
-
ARGV << '-d' << 'example.com:/var/ww/html'
|
45
|
-
ARGV << '--server' << 'https://acme-staging.api.letsencrypt.org/directory'
|
46
|
-
runner.parse_options
|
47
|
-
VCR.use_cassette('single-domain') do
|
48
|
-
# raise error because no e-mail address was given
|
49
|
-
expect { certificate.get(nil, nil, runner.options) }.
|
50
|
-
to raise_error(Acme::Client::Error)
|
51
|
-
end
|
52
|
-
|
53
|
-
ARGV.clear
|
54
|
-
ARGV << '-d' << 'example.com:/var/www/html'
|
55
|
-
ARGV << '-d' << 'www.example.com'
|
56
|
-
ARGV << '--server' << 'https://acme-staging.api.letsencrypt.org/directory'
|
57
|
-
runner.options[:domains] = []
|
58
|
-
runner.parse_options
|
59
|
-
expect { certificate.get(nil, nil, runner.options) }.
|
60
|
-
to raise_error(LetsCert::Error).
|
61
|
-
with_message(/not specified: www\.example\.com\./)
|
62
|
-
|
63
|
-
ARGV.clear
|
64
|
-
ARGV << '-d' << 'example.com:/var/www/html'
|
65
|
-
ARGV << '-d' << 'www.example.com'
|
66
|
-
ARGV << '--default-root' << '/opt/www'
|
67
|
-
ARGV << '--server' << 'https://acme-staging.api.letsencrypt.org/directory'
|
68
|
-
runner.parse_options
|
69
|
-
VCR.use_cassette('default-root') do
|
70
|
-
# raise error because no e-mail address was given
|
71
|
-
expect { certificate.get(nil, nil, runner.options) }.
|
72
|
-
to raise_error(Acme::Client::Error)
|
73
|
-
end
|
74
|
-
expect(runner.options[:roots]['example.com']).to eq('/var/www/html')
|
75
|
-
expect(runner.options[:roots]['www.example.com']).to eq('/opt/www')
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'uses existing account key' do
|
79
|
-
options = { roots: { 'example.com' => '/var/www/html' } }
|
80
|
-
|
81
|
-
VCR.use_cassette('no-server') do
|
82
|
-
# Connection error: no server to connect to
|
83
|
-
expect { certificate.get(@account_key2048, nil, options) }.
|
84
|
-
to raise_error(Faraday::ConnectionFailed)
|
85
|
-
end
|
86
|
-
expect(certificate.client.private_key).to eq(@account_key2048)
|
87
|
-
end
|
88
|
-
|
89
|
-
it 'creates an ACME account key if non exists' do
|
90
|
-
options = {
|
91
|
-
roots: { 'example.com' => '/var/www/html' },
|
92
|
-
account_key_size: 128,
|
93
|
-
}
|
94
|
-
|
95
|
-
VCR.use_cassette('no-server') do
|
96
|
-
# Connection error: no server to connect to
|
97
|
-
expect { certificate.get(nil, nil, options) }.
|
98
|
-
to raise_error(Faraday::ConnectionFailed)
|
99
|
-
end
|
100
|
-
expect(certificate.client.private_key).to be_a(OpenSSL::PKey::RSA)
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'creates an ACME client with provided account key and end point' do
|
104
|
-
options = {
|
105
|
-
roots: { 'example.com' => '/var/www/html' },
|
106
|
-
server: 'https://acme-staging.api.letsencrypt.org/directory',
|
107
|
-
}
|
108
|
-
|
109
|
-
VCR.use_cassette('create-acme-client') do
|
110
|
-
# Acme error: not valid e-mail address
|
111
|
-
expect { certificate.get(@account_key2048, nil, options) }.
|
112
|
-
to raise_error(Acme::Client::Error)
|
113
|
-
end
|
114
|
-
expect(certificate.client.private_key).to eq(@account_key2048)
|
115
|
-
expect(certificate.client.instance_eval { @endpoint }).to eq(options[:server])
|
116
|
-
end
|
117
|
-
|
118
|
-
it 'raises when register without e-mail' do
|
119
|
-
options = {
|
120
|
-
roots: { 'example.com' => '/var/www/html' },
|
121
|
-
server: 'https://acme-staging.api.letsencrypt.org/directory',
|
122
|
-
}
|
123
|
-
|
124
|
-
VCR.use_cassette('create-acme-client-but-bad-email') do
|
125
|
-
# Acme error: not valid e-mail address
|
126
|
-
expect { certificate.get(@account_key2048, nil, options) }.
|
127
|
-
to raise_error(Acme::Client::Error).
|
128
|
-
with_message('not a valid e-mail address')
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'responds to HTTP-01 challenge'
|
133
|
-
|
134
|
-
it 'raises if HTTP-01 challenge is unavailable' do
|
135
|
-
options = {
|
136
|
-
roots: { 'example.com' => '/var/www/html' },
|
137
|
-
server: 'https://acme-staging.api.letsencrypt.org/directory',
|
138
|
-
email: 'test@example.org',
|
139
|
-
}
|
140
|
-
|
141
|
-
VCR.use_cassette('no-http-01-challenge') do
|
142
|
-
certificate.get_acme_client(@account_key2048, options) do |client|
|
143
|
-
client.connection.builder.insert 0, RemoveHttp01Middleware
|
144
|
-
end
|
145
|
-
expect { certificate.get(@account_key2048, nil, options) }.
|
146
|
-
to raise_error(LetsCert::Error).with_message(/not offer http-01/)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
it 'reuses existing private key if --reuse-key is present'
|
151
|
-
|
152
|
-
end
|
153
|
-
|
154
|
-
context '#revoke' do
|
155
|
-
it 'raises if no certificate is given' do
|
156
|
-
certificate = Certificate.new(nil)
|
157
|
-
expect { certificate.revoke(@account_key2048) }.
|
158
|
-
to raise_error(LetsCert::Error)
|
159
|
-
end
|
160
|
-
|
161
|
-
it 'revokes an existing certificate'
|
162
|
-
end
|
163
|
-
|
164
|
-
context '#valid?' do
|
165
|
-
|
166
|
-
it 'checks whether a certificate is valid given a minimum valid duration' do
|
167
|
-
expect(certificate.valid?(@domains)).to be(true)
|
168
|
-
expect(certificate.valid?(@domains, 19)).to be(true)
|
169
|
-
expect(certificate.valid?(@domains, 21 * 24 * 3600)).to be(false)
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'raises whether a certificate does not validate a given domain' do
|
173
|
-
expect(certificate.valid?(@domains)).to be(true)
|
174
|
-
expect(certificate.valid?(@domains[0, 1])).to be(true)
|
175
|
-
|
176
|
-
domains = @domains + %w(another.tld)
|
177
|
-
expect { certificate.valid?(domains) }.to raise_error(LetsCert::Error)
|
178
|
-
expect { certificate.valid?(%w(another.tld)) }.to raise_error(LetsCert::Error)
|
179
|
-
end
|
180
|
-
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
|
185
|
-
end
|
data/spec/chain.pem
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
2
|
-
MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw
|
3
|
-
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
|
4
|
-
Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa
|
5
|
-
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
|
6
|
-
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD
|
7
|
-
ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB
|
8
|
-
BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg
|
9
|
-
PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG
|
10
|
-
dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1
|
11
|
-
gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4
|
12
|
-
4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud
|
13
|
-
EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy
|
14
|
-
BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j
|
15
|
-
b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv
|
16
|
-
ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ
|
17
|
-
MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH
|
18
|
-
AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw
|
19
|
-
MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM
|
20
|
-
LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3
|
21
|
-
pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd
|
22
|
-
v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd
|
23
|
-
ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW
|
24
|
-
ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk
|
25
|
-
6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj
|
26
|
-
f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk=
|
27
|
-
-----END CERTIFICATE-----
|
data/spec/fullchain.pem
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
-----BEGIN CERTIFICATE-----
|
2
|
-
MIIFmzCCBIOgAwIBAgISAVjEgN3oIZzLvwTkSOVu08NlMA0GCSqGSIb3DQEBCwUA
|
3
|
-
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
|
4
|
-
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTAeFw0xNjAyMTExNzQyMDBaFw0x
|
5
|
-
NjA1MTExNzQyMDBaMBIxEDAOBgNVBAMTB2xkNzcuZXUwggGiMA0GCSqGSIb3DQEB
|
6
|
-
AQUAA4IBjwAwggGKAoIBgQDPpsQCigwsWHwBhKGiXb8IDDVdV2q36tIsyP2WQmZy
|
7
|
-
G4JpasPpmVxuK2qPsYjEQRt+9VsKwOvuq1hNpQCJLtHXEweg8d4Px83WVQbcrdP5
|
8
|
-
U3hJgPbFFI6UXyx5BtsctDdYLxxi91tKn8g7nZgEGw1/NcSXkXQ6Q1/O5zwt2CME
|
9
|
-
/xGTASI74kR2nXhIU8ZPth52R99UpIYquy2n0cNyadgFuhNq+jWZ8ks+ZYY/b1s4
|
10
|
-
YL6cCx9SIAvDonrZGGG01ilZJWCxjgXxwXN5o78/22vyHcoBuwiK+6vPTKZ/+zvK
|
11
|
-
MjDXES7sM791mjgh7c+NL57SCw4D4zYq7ABmx7tCip5BGTT9n/BdoKxBK8vaU9tA
|
12
|
-
Qe3OYYXcdXN3g9up249U/+H9Hy/fu2/BYe7CDIkEU/1kQosYYKpSJv1WAU12gb77
|
13
|
-
k7u1DnR+5vP/EwA+/rLb9MvEuj8mA9oKnLVq6zOaY/LXxcVVXEJEktoDV+Y27VuU
|
14
|
-
yB5J1n7OL2SXzycj693Sk/sCAwEAAaOCAjEwggItMA4GA1UdDwEB/wQEAwIFoDAd
|
15
|
-
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV
|
16
|
-
HQ4EFgQUtxSm/clLMtOKm+p5seP4OsvYSFEwHwYDVR0jBBgwFoAUqEpqYwR93brm
|
17
|
-
0Tm3pkVl7/Oo7KEwcAYIKwYBBQUHAQEEZDBiMC8GCCsGAQUFBzABhiNodHRwOi8v
|
18
|
-
b2NzcC5pbnQteDEubGV0c2VuY3J5cHQub3JnLzAvBggrBgEFBQcwAoYjaHR0cDov
|
19
|
-
L2NlcnQuaW50LXgxLmxldHNlbmNyeXB0Lm9yZy8wOwYDVR0RBDQwMoIHbGQ3Ny5l
|
20
|
-
dYIMaW1hcC5sZDc3LmV1ggxzbXRwLmxkNzcuZXWCC3d3dy5sZDc3LmV1MIH+BgNV
|
21
|
-
HSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggrBgEFBQcC
|
22
|
-
ARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwICMIGeDIGb
|
23
|
-
VGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBieSBSZWx5
|
24
|
-
aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0
|
25
|
-
aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcv
|
26
|
-
cmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBAEUjrcJKy04CiIGMuJwdHUQ7
|
27
|
-
25YywkoVxo7K8GnLs1uf5XREJgil2GPD6uL//U2V8FzreP/eDQFluNJSYE3F9F1b
|
28
|
-
f2X3TOSnJnRllFputgWMiIL8BzAbrR5UgEhrsSWS0AxK5Zh3GNTFa3pjQWu6swIl
|
29
|
-
eDAj2iJHCOuL2t33vk8G2bYdFOih0EL6WwWjrwsu4lNmjxDqKe3VOM0HJE/DBbWw
|
30
|
-
sqhZv1UOZZl8hJ6iID/hL7Tco6r1LcH5Fsyq8Yd/qbd4+kErWEvz/CeGsMDHFgYn
|
31
|
-
oefVSYJ7mA/lJTWdydeUTkdQ04H8s/pjtI8SKpMmVTQa+xdqsH2YMBEv8dspMzk=
|
32
|
-
-----END CERTIFICATE-----
|
33
|
-
-----BEGIN CERTIFICATE-----
|
34
|
-
MIIEqDCCA5CgAwIBAgIRAJgT9HUT5XULQ+dDHpceRL0wDQYJKoZIhvcNAQELBQAw
|
35
|
-
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
|
36
|
-
Ew5EU1QgUm9vdCBDQSBYMzAeFw0xNTEwMTkyMjMzMzZaFw0yMDEwMTkyMjMzMzZa
|
37
|
-
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
|
38
|
-
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMTCCASIwDQYJKoZIhvcNAQEBBQAD
|
39
|
-
ggEPADCCAQoCggEBAJzTDPBa5S5Ht3JdN4OzaGMw6tc1Jhkl4b2+NfFwki+3uEtB
|
40
|
-
BaupnjUIWOyxKsRohwuj43Xk5vOnYnG6eYFgH9eRmp/z0HhncchpDpWRz/7mmelg
|
41
|
-
PEjMfspNdxIknUcbWuu57B43ABycrHunBerOSuu9QeU2mLnL/W08lmjfIypCkAyG
|
42
|
-
dGfIf6WauFJhFBM/ZemCh8vb+g5W9oaJ84U/l4avsNwa72sNlRZ9xCugZbKZBDZ1
|
43
|
-
gGusSvMbkEl4L6KWTyogJSkExnTA0DHNjzE4lRa6qDO4Q/GxH8Mwf6J5MRM9LTb4
|
44
|
-
4/zyM2q5OTHFr8SNDR1kFjOq+oQpttQLwNh9w5MCAwEAAaOCAZIwggGOMBIGA1Ud
|
45
|
-
EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMH8GCCsGAQUFBwEBBHMwcTAy
|
46
|
-
BggrBgEFBQcwAYYmaHR0cDovL2lzcmcudHJ1c3RpZC5vY3NwLmlkZW50cnVzdC5j
|
47
|
-
b20wOwYIKwYBBQUHMAKGL2h0dHA6Ly9hcHBzLmlkZW50cnVzdC5jb20vcm9vdHMv
|
48
|
-
ZHN0cm9vdGNheDMucDdjMB8GA1UdIwQYMBaAFMSnsaR7LHH62+FLkHX/xBVghYkQ
|
49
|
-
MFQGA1UdIARNMEswCAYGZ4EMAQIBMD8GCysGAQQBgt8TAQEBMDAwLgYIKwYBBQUH
|
50
|
-
AgEWImh0dHA6Ly9jcHMucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcwPAYDVR0fBDUw
|
51
|
-
MzAxoC+gLYYraHR0cDovL2NybC5pZGVudHJ1c3QuY29tL0RTVFJPT1RDQVgzQ1JM
|
52
|
-
LmNybDATBgNVHR4EDDAKoQgwBoIELm1pbDAdBgNVHQ4EFgQUqEpqYwR93brm0Tm3
|
53
|
-
pkVl7/Oo7KEwDQYJKoZIhvcNAQELBQADggEBANHIIkus7+MJiZZQsY14cCoBG1hd
|
54
|
-
v0J20/FyWo5ppnfjL78S2k4s2GLRJ7iD9ZDKErndvbNFGcsW+9kKK/TnY21hp4Dd
|
55
|
-
ITv8S9ZYQ7oaoqs7HwhEMY9sibED4aXw09xrJZTC9zK1uIfW6t5dHQjuOWv+HHoW
|
56
|
-
ZnupyxpsEUlEaFb+/SCI4KCSBdAsYxAcsHYI5xxEI4LutHp6s3OT2FuO90WfdsIk
|
57
|
-
6q78OMSdn875bNjdBYAqxUp2/LEIHfDBkLoQz0hFJmwAbYahqKaLn73PAAm1X2kj
|
58
|
-
f1w8DdnkabOLGeOVcj9LQ+s67vBykx4anTjURkbqZslUEUsn2k5xeua2zUk=
|
59
|
-
-----END CERTIFICATE-----
|
data/spec/io_plugin_spec.rb
DELETED
@@ -1,387 +0,0 @@
|
|
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
|
-
let(:ak) { IOPlugin.registered['account_key.json'] }
|
65
|
-
|
66
|
-
it 'persist account_key' do
|
67
|
-
persisted = ak.persisted
|
68
|
-
expect(persisted[:account_key]).to be(true)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "#load account key from account_key.json file" do
|
72
|
-
expect(ak).to be_a(AccountKey)
|
73
|
-
|
74
|
-
pwd = FileUtils.pwd
|
75
|
-
FileUtils.cd File.dirname(__FILE__)
|
76
|
-
|
77
|
-
begin
|
78
|
-
content = ak.load
|
79
|
-
expect(content).to be_a(Hash)
|
80
|
-
expect(content.keys.size).to eq(1)
|
81
|
-
expect(content[:account_key]).to be_a(OpenSSL::PKey::PKey)
|
82
|
-
rescue Exception
|
83
|
-
raise
|
84
|
-
ensure
|
85
|
-
FileUtils.cd pwd
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
it "#save account key to account_key.json file" do
|
90
|
-
data = { account_key: OpenSSL::PKey::RSA.new(1024) }
|
91
|
-
ak.save(data)
|
92
|
-
begin
|
93
|
-
expect(File.exist?('account_key.json')).to be_truthy
|
94
|
-
rescue Exception
|
95
|
-
raise
|
96
|
-
ensure
|
97
|
-
File.unlink('account_key.json')
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
describe KeyFile do
|
104
|
-
|
105
|
-
let(:keypem) { IOPlugin.registered['key.pem'] }
|
106
|
-
let(:keyder) { IOPlugin.registered['key.der'] }
|
107
|
-
|
108
|
-
it 'persist key' do
|
109
|
-
expect(keypem.persisted[:key]).to be(true)
|
110
|
-
expect(keyder.persisted[:key]).to be(true)
|
111
|
-
end
|
112
|
-
|
113
|
-
it '#load private key from key.pem file' do
|
114
|
-
pwd = FileUtils.pwd
|
115
|
-
FileUtils.cd File.dirname(__FILE__)
|
116
|
-
|
117
|
-
begin
|
118
|
-
data = keypem.load
|
119
|
-
expect(data[:key]).to be_a(OpenSSL::PKey::RSA)
|
120
|
-
expect(data[:key].params['d']).to eq(OpenSSL::BN.new(0x573C8C0EADCBA5E571CD57FAB4D9FE6AC9DC5F9ADF8FEC48667D836B6A0EA9E1240D2A5861258A7E6E5EA1052AFAD71176A49E90BA80F43C44F2BD415161C1E71AA37E7C2BE5C7C18CF964A5A7100C801F558C7B7825D082FEF79A76963786D8CDFE1058F7F178869A09F5377F51DD45EA05B428F41F09C9F29D37BB539512C5))
|
121
|
-
rescue Exception
|
122
|
-
raise
|
123
|
-
ensure
|
124
|
-
FileUtils.cd pwd
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
it '#save private key to key.pem file' do
|
129
|
-
data = { key: OpenSSL::PKey::RSA.new(512) }
|
130
|
-
keypem.save data
|
131
|
-
begin
|
132
|
-
expect(File.exist? 'key.pem').to be(true)
|
133
|
-
|
134
|
-
data2 = keypem.load
|
135
|
-
expect(data2[:key].params['d'].to_i).to eq(data[:key].params['d'].to_i)
|
136
|
-
rescue Exception
|
137
|
-
raise
|
138
|
-
ensure
|
139
|
-
File.unlink 'key.pem'
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
it '#load private key from key.der file' do
|
144
|
-
pwd = FileUtils.pwd
|
145
|
-
FileUtils.cd File.dirname(__FILE__)
|
146
|
-
|
147
|
-
begin
|
148
|
-
data = keyder.load
|
149
|
-
expect(data[:key]).to be_a(OpenSSL::PKey::RSA)
|
150
|
-
expect(data[:key].params['d']).to eq(OpenSSL::BN.new(0x648C2A57083D12CA32A89538DD1AD7BAC5C522E682F0AFD9C834BB44CC536A57880F24D9D8987A0FC2CEF5C8F7A9BA70223E3C3E06229C815955FCE06F198175))
|
151
|
-
rescue Exception
|
152
|
-
raise
|
153
|
-
ensure
|
154
|
-
FileUtils.cd pwd
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
it '#save private key to key.der file' do
|
159
|
-
data = { key: OpenSSL::PKey::RSA.new(512) }
|
160
|
-
keyder.save data
|
161
|
-
begin
|
162
|
-
expect(File.exist? 'key.der').to be(true)
|
163
|
-
|
164
|
-
data2 = keyder.load
|
165
|
-
expect(data2[:key].params['d'].to_i).to eq(data[:key].params['d'].to_i)
|
166
|
-
rescue Exception
|
167
|
-
raise
|
168
|
-
ensure
|
169
|
-
File.unlink 'key.der'
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
describe ChainFile do
|
175
|
-
let(:chain) { IOPlugin.registered['chain.pem'] }
|
176
|
-
|
177
|
-
it 'persist chain' do
|
178
|
-
expect(chain.persisted[:chain]).to be(true)
|
179
|
-
end
|
180
|
-
|
181
|
-
it '#load chain from chain.pem file' do
|
182
|
-
pwd = FileUtils.pwd
|
183
|
-
FileUtils.cd File.dirname(__FILE__)
|
184
|
-
|
185
|
-
begin
|
186
|
-
data = chain.load
|
187
|
-
expect(data[:cert]).to be_nil
|
188
|
-
expect(data[:chain]).to_not be_nil
|
189
|
-
expect(data[:chain]).to be_a(Array)
|
190
|
-
expect(data[:chain].first).to be_a(OpenSSL::X509::Certificate)
|
191
|
-
rescue Exception
|
192
|
-
raise
|
193
|
-
ensure
|
194
|
-
FileUtils.cd pwd
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
it '#save chain to chain.pem file' do
|
199
|
-
pwd = FileUtils.pwd
|
200
|
-
FileUtils.cd File.dirname(__FILE__)
|
201
|
-
|
202
|
-
begin
|
203
|
-
data = chain.load
|
204
|
-
expect(data[:cert]).to be_nil
|
205
|
-
expect(data[:chain]).to_not be_nil
|
206
|
-
rescue Exception
|
207
|
-
raise
|
208
|
-
ensure
|
209
|
-
FileUtils.cd pwd
|
210
|
-
end
|
211
|
-
|
212
|
-
chain.save data
|
213
|
-
|
214
|
-
begin
|
215
|
-
expect(File.exist? 'chain.pem').to be(true)
|
216
|
-
|
217
|
-
data2 = chain.load
|
218
|
-
data2[:chain].each_with_index do |cert, i|
|
219
|
-
expect(cert.to_pem).to eq(data[:chain][i].to_pem)
|
220
|
-
end
|
221
|
-
rescue Exception
|
222
|
-
raise
|
223
|
-
ensure
|
224
|
-
File.unlink 'chain.pem'
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
end
|
229
|
-
|
230
|
-
describe FullChainFile do
|
231
|
-
let(:fullchain) { IOPlugin.registered['fullchain.pem'] }
|
232
|
-
|
233
|
-
it 'persist chain' do
|
234
|
-
expect(fullchain.persisted[:chain]).to be(true)
|
235
|
-
end
|
236
|
-
|
237
|
-
it 'persist cert' do
|
238
|
-
expect(fullchain.persisted[:cert]).to be(true)
|
239
|
-
end
|
240
|
-
|
241
|
-
it '#load cert and chain from fullchain.pem file' do
|
242
|
-
pwd = FileUtils.pwd
|
243
|
-
FileUtils.cd File.dirname(__FILE__)
|
244
|
-
|
245
|
-
begin
|
246
|
-
data = fullchain.load
|
247
|
-
expect(data[:cert]).to_not be_nil
|
248
|
-
expect(data[:cert]).to be_a(OpenSSL::X509::Certificate)
|
249
|
-
expect(data[:chain]).to_not be_nil
|
250
|
-
expect(data[:chain]).to be_a(Array)
|
251
|
-
expect(data[:chain].first).to be_a(OpenSSL::X509::Certificate)
|
252
|
-
rescue Exception
|
253
|
-
raise
|
254
|
-
ensure
|
255
|
-
FileUtils.cd pwd
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
it '#save cert and chain to fullchain.pem file' do
|
260
|
-
pwd = FileUtils.pwd
|
261
|
-
FileUtils.cd File.dirname(__FILE__)
|
262
|
-
|
263
|
-
begin
|
264
|
-
data = fullchain.load
|
265
|
-
expect(data[:cert]).to_not be_nil
|
266
|
-
expect(data[:chain]).to_not be_nil
|
267
|
-
rescue Exception
|
268
|
-
raise
|
269
|
-
ensure
|
270
|
-
FileUtils.cd pwd
|
271
|
-
end
|
272
|
-
|
273
|
-
fullchain.save data
|
274
|
-
|
275
|
-
begin
|
276
|
-
expect(File.exist? 'fullchain.pem').to be(true)
|
277
|
-
|
278
|
-
data2 = fullchain.load
|
279
|
-
expect(data2[:cert].to_pem).to eq(data[:cert].to_pem)
|
280
|
-
data2[:chain].each_with_index do |cert, i|
|
281
|
-
expect(cert.to_pem).to eq(data[:chain][i].to_pem)
|
282
|
-
end
|
283
|
-
rescue Exception
|
284
|
-
raise
|
285
|
-
ensure
|
286
|
-
File.unlink 'fullchain.pem'
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
end
|
291
|
-
|
292
|
-
describe CertFile do
|
293
|
-
|
294
|
-
let(:certpem) { IOPlugin.registered['cert.pem'] }
|
295
|
-
let(:certder) { IOPlugin.registered['cert.der'] }
|
296
|
-
|
297
|
-
it 'persist cert' do
|
298
|
-
expect(certpem.persisted[:cert]).to be(true)
|
299
|
-
expect(certder.persisted[:cert]).to be(true)
|
300
|
-
end
|
301
|
-
|
302
|
-
it '#load cert from cert.pem' do
|
303
|
-
pwd = FileUtils.pwd
|
304
|
-
FileUtils.cd File.dirname(__FILE__)
|
305
|
-
|
306
|
-
begin
|
307
|
-
data = certpem.load
|
308
|
-
expect(data[:cert]).to_not be_nil
|
309
|
-
expect(data[:cert]).to be_a(OpenSSL::X509::Certificate)
|
310
|
-
rescue Exception
|
311
|
-
raise
|
312
|
-
ensure
|
313
|
-
FileUtils.cd pwd
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
it '#load cert from cert.der' do
|
318
|
-
pwd = FileUtils.pwd
|
319
|
-
FileUtils.cd File.dirname(__FILE__)
|
320
|
-
|
321
|
-
begin
|
322
|
-
data = certder.load
|
323
|
-
expect(data[:cert]).to_not be_nil
|
324
|
-
expect(data[:cert]).to be_a(OpenSSL::X509::Certificate)
|
325
|
-
rescue Exception
|
326
|
-
raise
|
327
|
-
ensure
|
328
|
-
FileUtils.cd pwd
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
it '#save cert to cert.pem' do
|
333
|
-
pwd = FileUtils.pwd
|
334
|
-
FileUtils.cd File.dirname(__FILE__)
|
335
|
-
|
336
|
-
begin
|
337
|
-
data = certpem.load
|
338
|
-
expect(data[:cert]).to_not be_nil
|
339
|
-
rescue Exception
|
340
|
-
raise
|
341
|
-
ensure
|
342
|
-
FileUtils.cd pwd
|
343
|
-
end
|
344
|
-
|
345
|
-
certpem.save data
|
346
|
-
|
347
|
-
begin
|
348
|
-
expect(File.exist? 'cert.pem').to be(true)
|
349
|
-
|
350
|
-
data2 = certpem.load
|
351
|
-
expect(data2[:cert].to_pem).to eq(data[:cert].to_pem)
|
352
|
-
rescue Exception
|
353
|
-
raise
|
354
|
-
ensure
|
355
|
-
File.unlink 'cert.pem'
|
356
|
-
end
|
357
|
-
end
|
358
|
-
|
359
|
-
it '#save cert to cert.der' do
|
360
|
-
pwd = FileUtils.pwd
|
361
|
-
FileUtils.cd File.dirname(__FILE__)
|
362
|
-
|
363
|
-
begin
|
364
|
-
data = certder.load
|
365
|
-
expect(data[:cert]).to_not be_nil
|
366
|
-
rescue Exception
|
367
|
-
raise
|
368
|
-
ensure
|
369
|
-
FileUtils.cd pwd
|
370
|
-
end
|
371
|
-
|
372
|
-
certder.save data
|
373
|
-
|
374
|
-
begin
|
375
|
-
expect(File.exist? 'cert.der').to be(true)
|
376
|
-
|
377
|
-
data2 = certder.load
|
378
|
-
expect(data2[:cert].to_pem).to eq(data[:cert].to_pem)
|
379
|
-
rescue Exception
|
380
|
-
raise
|
381
|
-
ensure
|
382
|
-
File.unlink 'cert.der'
|
383
|
-
end
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
end
|
data/spec/key.der
DELETED
Binary file
|
data/spec/key.pem
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
-----BEGIN RSA PRIVATE KEY-----
|
2
|
-
MIICXQIBAAKBgQCcUtDEgi7FE8IO5NINg6qNmxm4XBw24GYMCfPz+InzGu1naMoQ
|
3
|
-
Up83B9qlNJpNKj7MnaRFePWnEgS9JbUxEYPoUB6zRDnabgzABsy4Tcrg6F3LXsHG
|
4
|
-
T72QZfU/fInLr+Ib4qE+oJ8jpQY6zRb1/SMXEcPFF5zSLzT3IEYNrAgUoQIDAQAB
|
5
|
-
AoGAVzyMDq3LpeVxzVf6tNn+asncX5rfj+xIZn2Da2oOqeEkDSpYYSWKfm5eoQUq
|
6
|
-
+tcRdqSekLqA9DxE8r1BUWHB5xqjfnwr5cfBjPlkpacQDIAfVYx7eCXQgv73mnaW
|
7
|
-
N4bYzf4QWPfxeIaaCfU3f1HdReoFtCj0HwnJ8p03u1OVEsUCQQDQIUQZN9KyTv6B
|
8
|
-
EBc50RNjeUxz13Ivjn8lWX95yf2VFfFRbS9hwOzsDl3jNtWqEtoePZsqdjwHlbMI
|
9
|
-
ovfls/rTAkEAwEcs2u2+07EflbLkbmEF/5zJQXdslKd8Cx6Xp/jtyO09sPj9Jjnb
|
10
|
-
h6pWXRLHgn8JsojX6ALPpqOGpryKBgXiOwJBAMMwT4Mu/SRIPRqhEocgcwR5P5/s
|
11
|
-
T6QWCVvnwUtgibcFqxloQmV03zzKhHaQeHVV1MVDlX+O/uFGHW9eFwqPbg0CQQCA
|
12
|
-
aojgpsw+IhvQJSw/M/mHoDUhzhrspXdJDeOHwc891ITRP1oDP70IvJD1lGc/Fo1p
|
13
|
-
ec+JGueIicqSbXVZVHClAkBW8wwSK/QBG9eAkWH9i2WCJb3okYsmRoSwDAYIsnMO
|
14
|
-
GOn1TJ8b7rorKE6S3G1v+jQSXFx6Pc+HU+weS7Ux8UIV
|
15
|
-
-----END RSA PRIVATE KEY-----
|