rspec-ssltls 0.0.6 → 0.0.7
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/README.md +5 -0
- data/lib/rspec_ssltls/have_certificate.rb +40 -6
- data/lib/rspec_ssltls/version.rb +1 -1
- data/spec/rspec_ssltls/have_certificate_spec.rb +45 -38
- data/spec/spec_helper.rb +54 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22a5bfa0f3ceeea792d4ea2afaaf3b47602062af
|
4
|
+
data.tar.gz: 4a321f42d84d785870a4deef599e9c05a9c78216
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 324e3e06008f554cbd7386958106ce95249a48ed7db37f5cbc2ed2c05e49d42fd2a2a917c2202ff7c867d1fdb5cdd7c813add31da11f0599c8092f6731b79e5e
|
7
|
+
data.tar.gz: 57db920d7b9793975f26ba5b99941bdcb6efdb8b386b3d84191c94fa4fb6e5ff6ad3ea3ac44a6b8c0ce682855d4e87c19db036e09e11eab472c58d59613558e0
|
data/README.md
CHANGED
@@ -34,6 +34,11 @@ describe 'www.example.com:443' do
|
|
34
34
|
is_expected.to have_certificate
|
35
35
|
.subject(CN: '*.example.com').signature_algorithm('sha1WithRSAEncryption')
|
36
36
|
end
|
37
|
+
it { is_expected.to have_certificate.verified }
|
38
|
+
it do
|
39
|
+
is_expected.to have_certificate
|
40
|
+
.verified_with(File.read('example.org.cer'))
|
41
|
+
end
|
37
42
|
it { is_expected.to support_protocol('TLSv1_2') }
|
38
43
|
it { is_expected.to support_cipher('AES256-SHA').protocol('TLSv1') }
|
39
44
|
it { is_expected.to support_cipher('DES-CBC3-SHA').protocol('SSLv3') }
|
@@ -4,18 +4,23 @@ require 'time'
|
|
4
4
|
|
5
5
|
RSpec::Matchers.define :have_certificate do
|
6
6
|
match do |dest|
|
7
|
-
@chain_string
|
7
|
+
@chain_string ||= ''
|
8
8
|
@result_string ||= ''
|
9
|
-
@chain_number
|
9
|
+
@chain_number ||= 0
|
10
10
|
uri = URI.parse('https://' + dest)
|
11
11
|
socket = TCPSocket.open(uri.host, uri.port)
|
12
12
|
ssl_context = OpenSSL::SSL::SSLContext.new
|
13
|
+
ssl_context.verify_mode = @verify_mode if @verify_mode
|
14
|
+
ssl_context.cert_store = @cert_store if @cert_store
|
13
15
|
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
|
14
16
|
ssl_socket.sync_close = true
|
15
17
|
ssl_socket.connect
|
16
|
-
|
18
|
+
if ssl_socket.peer_cert_chain
|
19
|
+
@peer_cert = ssl_socket.peer_cert_chain[@chain_number]
|
20
|
+
end
|
21
|
+
@verify_result = ssl_socket.verify_result
|
17
22
|
ssl_socket.close
|
18
|
-
@peer_cert ? valid_cert? : false
|
23
|
+
@peer_cert ? valid_cert? && verified_cert? : false
|
19
24
|
end
|
20
25
|
|
21
26
|
chain :subject do |id|
|
@@ -32,16 +37,32 @@ RSpec::Matchers.define :have_certificate do
|
|
32
37
|
RspecSsltls::Util.add_string(@chain_string, "chain[#{n}]")
|
33
38
|
end
|
34
39
|
|
40
|
+
chain :verified do
|
41
|
+
@verify_mode = OpenSSL::SSL::VERIFY_PEER
|
42
|
+
@cert_store = OpenSSL::X509::Store.new
|
43
|
+
@cert_store.set_default_paths
|
44
|
+
@chain_string =
|
45
|
+
RspecSsltls::Util.add_string(@chain_string, 'verified')
|
46
|
+
end
|
47
|
+
|
48
|
+
chain :verified_with do |c|
|
49
|
+
@verify_mode = OpenSSL::SSL::VERIFY_PEER
|
50
|
+
@cert_store = OpenSSL::X509::Store.new
|
51
|
+
@cert_store.add_file(c)
|
52
|
+
@chain_string =
|
53
|
+
RspecSsltls::Util.add_string(@chain_string, "verified with #{c}")
|
54
|
+
end
|
55
|
+
|
35
56
|
chain :valid_at do |t|
|
36
57
|
@chain_string =
|
37
|
-
RspecSsltls::Util.add_string(@chain_string, "
|
58
|
+
RspecSsltls::Util.add_string(@chain_string, "valid at #{t}")
|
38
59
|
@t1 = t
|
39
60
|
@t2 = t
|
40
61
|
end
|
41
62
|
|
42
63
|
chain :valid_in do |t1, t2|
|
43
64
|
@chain_string = RspecSsltls::Util
|
44
|
-
.add_string(@chain_string, "
|
65
|
+
.add_string(@chain_string, "valid in #{t1} - #{t2}")
|
45
66
|
@t1 = t1
|
46
67
|
@t2 = t2
|
47
68
|
end
|
@@ -91,6 +112,17 @@ RSpec::Matchers.define :have_certificate do
|
|
91
112
|
RspecSsltls::Util.add_string(@chain_string, "#{key} #{kv}", ' ')
|
92
113
|
end
|
93
114
|
|
115
|
+
def verified_cert?
|
116
|
+
return true if @verify_mode.nil?
|
117
|
+
@result_string += " expected: verified\n"
|
118
|
+
if @verify_result == OpenSSL::X509::V_OK
|
119
|
+
@result_string += " actual: verified\n"
|
120
|
+
else
|
121
|
+
@result_string += " actual: unverified(errorcode: #{@verify_result})\n"
|
122
|
+
end
|
123
|
+
@verify_result == OpenSSL::X509::V_OK
|
124
|
+
end
|
125
|
+
|
94
126
|
def valid_in?
|
95
127
|
return true unless @t1 && @t2
|
96
128
|
fail 'Input time range is incorrect' if @t2 < @t1
|
@@ -133,5 +165,7 @@ RSpec::Matchers.define :have_certificate do
|
|
133
165
|
failure_message_when_negated do
|
134
166
|
s = "expected not to have a certificate#{@chain_string}, but did."
|
135
167
|
s + "\n#{@result_string}"
|
168
|
+
.sub(/(expected:)/, 'expected not:')
|
169
|
+
.sub(/(actual:)/, 'actual: ')
|
136
170
|
end
|
137
171
|
end
|
data/lib/rspec_ssltls/version.rb
CHANGED
@@ -1,44 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rspec_ssltls'
|
3
3
|
|
4
|
-
|
5
|
-
allow(TCPSocket).to receive(:open).and_return(nil)
|
6
|
-
allow(OpenSSL::SSL::SSLSocket).to receive(:new) do
|
7
|
-
ssl_socket = double('ssl_socket')
|
8
|
-
allow(ssl_socket).to receive(:method_missing).and_return(nil)
|
9
|
-
params.each_pair do |k, v|
|
10
|
-
allow(ssl_socket).to receive(k).and_return(v)
|
11
|
-
end if params
|
12
|
-
ssl_socket
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# See http://www.ietf.org/rfc/rfc5280.txt 4.1.2.4
|
17
|
-
# See https://github.com/openssl/openssl/blob/master/crypto/objects/obj_xref.txt
|
18
|
-
|
19
|
-
example_ca_cert_name =
|
20
|
-
OpenSSL::X509::Name.new([%w(C US),
|
21
|
-
%w(O Example\ Org.),
|
22
|
-
%w(OU Example\ Org.\ Div.),
|
23
|
-
%w(CN ca.example.org)
|
24
|
-
])
|
25
|
-
example_ca_cert = OpenSSL::X509::Certificate.new
|
26
|
-
example_ca_cert.subject = example_ca_cert_name
|
27
|
-
example_ca_cert.not_before = Time.utc(0, 0, 0, 1, 10, 2014, nil, nil, nil, nil)
|
28
|
-
example_ca_cert.not_after = Time.utc(0, 0, 0, 1, 10, 2022, nil, nil, nil, nil)
|
29
|
-
|
30
|
-
example_cert_name =
|
31
|
-
OpenSSL::X509::Name.new([%w(C JP),
|
32
|
-
%w(ST Tokyo),
|
33
|
-
%w(O Example\ Co.,\ Ltd.),
|
34
|
-
%w(OU Example\ Div.),
|
35
|
-
%w(CN *.example.com)
|
36
|
-
])
|
37
|
-
example_cert = OpenSSL::X509::Certificate.new
|
38
|
-
example_cert.subject = example_cert_name
|
39
|
-
example_cert.issuer = example_ca_cert_name
|
40
|
-
example_cert.not_before = Time.utc(5, 0, 19, 12, 9, 2014, nil, nil, nil, nil)
|
41
|
-
example_cert.not_after = Time.utc(0, 0, 0, 1, 10, 2015, nil, nil, nil, nil)
|
4
|
+
example_ca_cert, example_cert = prepare_ca_certs
|
42
5
|
|
43
6
|
describe 'rspec-ssltls matchers' do
|
44
7
|
describe '#have_certificate' do
|
@@ -49,6 +12,10 @@ describe 'rspec-ssltls matchers' do
|
|
49
12
|
.and_return('sha1WithRSAEncryption')
|
50
13
|
end
|
51
14
|
|
15
|
+
after :all do
|
16
|
+
cleanup_ca_certs
|
17
|
+
end
|
18
|
+
|
52
19
|
## Having certificate
|
53
20
|
it 'can evalutate having certificate' do
|
54
21
|
stub_ssl_socket(peer_cert_chain: [nil])
|
@@ -227,5 +194,45 @@ describe 'rspec-ssltls matchers' do
|
|
227
194
|
.subject(CN: '*.example.com')
|
228
195
|
.signature_algorithm('sha1WithRSAEncryption')
|
229
196
|
end
|
197
|
+
|
198
|
+
## Verified
|
199
|
+
it 'can evalutate certificate verified' do
|
200
|
+
stub_ssl_socket(peer_cert_chain: [example_cert, example_ca_cert],
|
201
|
+
verify_result: OpenSSL::X509::V_OK)
|
202
|
+
expect('www.example.com:443').to have_certificate
|
203
|
+
.verified
|
204
|
+
stub_ssl_socket(peer_cert_chain: nil,
|
205
|
+
verify_result: OpenSSL::X509::V_ERR_CERT_REJECTED)
|
206
|
+
expect('www.example.com:443').not_to have_certificate
|
207
|
+
.verified
|
208
|
+
end
|
209
|
+
|
210
|
+
# show default description
|
211
|
+
it do
|
212
|
+
stub_ssl_socket(peer_cert_chain: [example_cert],
|
213
|
+
verify_result: OpenSSL::X509::V_OK)
|
214
|
+
expect('www.example.com:443').to have_certificate
|
215
|
+
.verified
|
216
|
+
end
|
217
|
+
|
218
|
+
## Verified with CA certficate
|
219
|
+
it 'can evalutate certificate verified with CA certificate' do
|
220
|
+
stub_ssl_socket(peer_cert_chain: [example_cert, example_ca_cert],
|
221
|
+
verify_result: OpenSSL::X509::V_OK)
|
222
|
+
expect('www.example.com:443').to have_certificate
|
223
|
+
.verified_with('tmp/ca_cert.cer')
|
224
|
+
stub_ssl_socket(peer_cert_chain: nil,
|
225
|
+
verify_result: OpenSSL::X509::V_ERR_CERT_UNTRUSTED)
|
226
|
+
expect('www.example.com:443').not_to have_certificate
|
227
|
+
.verified_with('tmp/cert.cer')
|
228
|
+
end
|
229
|
+
|
230
|
+
# show default description
|
231
|
+
it do
|
232
|
+
stub_ssl_socket(peer_cert_chain: [example_cert],
|
233
|
+
verify_result: OpenSSL::X509::V_OK)
|
234
|
+
expect('www.example.com:443').to have_certificate
|
235
|
+
.verified_with('tmp/ca_cert.cer')
|
236
|
+
end
|
230
237
|
end
|
231
238
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,6 +14,8 @@ end
|
|
14
14
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
15
15
|
|
16
16
|
require 'rspec_ssltls'
|
17
|
+
require 'openssl'
|
18
|
+
require 'fileutils'
|
17
19
|
|
18
20
|
def stub_ssl_socket(params = nil)
|
19
21
|
allow(TCPSocket).to receive(:open).and_return(nil)
|
@@ -26,3 +28,55 @@ def stub_ssl_socket(params = nil)
|
|
26
28
|
ssl_socket
|
27
29
|
end
|
28
30
|
end
|
31
|
+
|
32
|
+
def prepare_ca_certs
|
33
|
+
example_ca_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
|
34
|
+
example_ca_cert = OpenSSL::X509::Certificate.new
|
35
|
+
example_ca_cert.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
|
36
|
+
example_ca_cert.serial = 1
|
37
|
+
example_ca_cert.subject =
|
38
|
+
OpenSSL::X509::Name.new([%w(C US),
|
39
|
+
%w(O Example\ Org.),
|
40
|
+
%w(OU Example\ Org.\ Div.),
|
41
|
+
%w(CN ca.example.org)
|
42
|
+
])
|
43
|
+
example_ca_cert.issuer = example_ca_cert.subject # self-signed
|
44
|
+
example_ca_cert.public_key = example_ca_key.public_key
|
45
|
+
example_ca_cert.not_before =
|
46
|
+
Time.utc(0, 0, 0, 1, 10, 2014, nil, nil, nil, nil)
|
47
|
+
example_ca_cert.not_after =
|
48
|
+
Time.utc(0, 0, 0, 1, 10, 2022, nil, nil, nil, nil)
|
49
|
+
example_ca_cert.sign(example_ca_key, OpenSSL::Digest::SHA256.new)
|
50
|
+
|
51
|
+
example_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
|
52
|
+
example_cert = OpenSSL::X509::Certificate.new
|
53
|
+
example_cert.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
|
54
|
+
example_cert.serial = 1
|
55
|
+
example_cert.subject =
|
56
|
+
OpenSSL::X509::Name.new([%w(C JP),
|
57
|
+
%w(ST Tokyo),
|
58
|
+
%w(O Example\ Co.,\ Ltd.),
|
59
|
+
%w(OU Example\ Div.),
|
60
|
+
%w(CN *.example.com)
|
61
|
+
])
|
62
|
+
example_cert.issuer = example_ca_cert.subject
|
63
|
+
example_cert.public_key = example_key.public_key
|
64
|
+
example_cert.not_before =
|
65
|
+
Time.utc(5, 0, 19, 12, 9, 2014, nil, nil, nil, nil)
|
66
|
+
example_cert.not_after =
|
67
|
+
Time.utc(0, 0, 0, 1, 10, 2015, nil, nil, nil, nil)
|
68
|
+
example_cert.sign(example_ca_key, OpenSSL::Digest::SHA256.new)
|
69
|
+
|
70
|
+
FileUtils.mkdir_p('tmp')
|
71
|
+
File.open('tmp/ca_cert.key', 'wb') { |f| f.print example_ca_key.to_pem }
|
72
|
+
File.open('tmp/ca_cert.cer', 'wb') { |f| f.print example_ca_cert.to_pem }
|
73
|
+
File.open('tmp/cert.key', 'wb') { |f| f.print example_key.to_pem }
|
74
|
+
File.open('tmp/cert.cer', 'wb') { |f| f.print example_cert.to_pem }
|
75
|
+
|
76
|
+
[example_ca_cert, example_cert]
|
77
|
+
end
|
78
|
+
|
79
|
+
def cleanup_ca_certs
|
80
|
+
%w(tmp/ca_cert.key tmp/ca_cert.cer tmp/cert.key tmp/cert.cer)
|
81
|
+
.each { |f| File.delete(f) if File.exist?(f) }
|
82
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-ssltls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OTA Hiroshi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|