mongo 2.13.1 → 2.14.0.rc1
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.tar.gz.sig +1 -4
- data/lib/mongo.rb +9 -0
- data/lib/mongo/address/ipv4.rb +1 -1
- data/lib/mongo/address/ipv6.rb +1 -1
- data/lib/mongo/bulk_write.rb +17 -0
- data/lib/mongo/caching_cursor.rb +74 -0
- data/lib/mongo/client.rb +47 -8
- data/lib/mongo/cluster.rb +3 -3
- data/lib/mongo/cluster/topology/single.rb +1 -1
- data/lib/mongo/collection.rb +26 -0
- data/lib/mongo/collection/view.rb +24 -20
- data/lib/mongo/collection/view/aggregation.rb +25 -4
- data/lib/mongo/collection/view/builder/find_command.rb +38 -18
- data/lib/mongo/collection/view/explainable.rb +27 -8
- data/lib/mongo/collection/view/iterable.rb +72 -12
- data/lib/mongo/collection/view/readable.rb +12 -2
- data/lib/mongo/collection/view/writable.rb +15 -1
- data/lib/mongo/crypt/encryption_io.rb +6 -6
- data/lib/mongo/cursor.rb +1 -0
- data/lib/mongo/database.rb +6 -0
- data/lib/mongo/error.rb +2 -0
- data/lib/mongo/error/invalid_read_concern.rb +28 -0
- data/lib/mongo/error/server_certificate_revoked.rb +22 -0
- data/lib/mongo/error/unsupported_option.rb +14 -12
- data/lib/mongo/lint.rb +2 -1
- data/lib/mongo/logger.rb +3 -3
- data/lib/mongo/operation.rb +2 -0
- data/lib/mongo/operation/aggregate/result.rb +9 -8
- data/lib/mongo/operation/collections_info/result.rb +2 -0
- data/lib/mongo/operation/delete/bulk_result.rb +2 -0
- data/lib/mongo/operation/delete/result.rb +3 -0
- data/lib/mongo/operation/explain/command.rb +4 -0
- data/lib/mongo/operation/explain/legacy.rb +4 -0
- data/lib/mongo/operation/explain/op_msg.rb +6 -0
- data/lib/mongo/operation/explain/result.rb +3 -0
- data/lib/mongo/operation/find/legacy/result.rb +2 -0
- data/lib/mongo/operation/find/result.rb +3 -0
- data/lib/mongo/operation/get_more/result.rb +3 -0
- data/lib/mongo/operation/indexes/result.rb +5 -0
- data/lib/mongo/operation/insert/bulk_result.rb +5 -0
- data/lib/mongo/operation/insert/result.rb +5 -0
- data/lib/mongo/operation/list_collections/result.rb +5 -0
- data/lib/mongo/operation/map_reduce/result.rb +10 -0
- data/lib/mongo/operation/parallel_scan/result.rb +4 -0
- data/lib/mongo/operation/result.rb +35 -6
- data/lib/mongo/operation/shared/bypass_document_validation.rb +1 -0
- data/lib/mongo/operation/shared/causal_consistency_supported.rb +1 -0
- data/lib/mongo/operation/shared/collections_info_or_list_collections.rb +2 -0
- data/lib/mongo/operation/shared/executable.rb +1 -0
- data/lib/mongo/operation/shared/idable.rb +2 -1
- data/lib/mongo/operation/shared/limited.rb +1 -0
- data/lib/mongo/operation/shared/object_id_generator.rb +1 -0
- data/lib/mongo/operation/shared/result/aggregatable.rb +1 -0
- data/lib/mongo/operation/shared/sessions_supported.rb +1 -0
- data/lib/mongo/operation/shared/specifiable.rb +1 -0
- data/lib/mongo/operation/shared/write.rb +1 -0
- data/lib/mongo/operation/shared/write_concern_supported.rb +1 -0
- data/lib/mongo/operation/update/legacy/result.rb +7 -0
- data/lib/mongo/operation/update/result.rb +8 -0
- data/lib/mongo/operation/users_info/result.rb +3 -0
- data/lib/mongo/query_cache.rb +242 -0
- data/lib/mongo/retryable.rb +8 -1
- data/lib/mongo/server.rb +5 -1
- data/lib/mongo/server/connection_common.rb +2 -2
- data/lib/mongo/server/connection_pool.rb +3 -0
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/monitor/connection.rb +3 -3
- data/lib/mongo/server/pending_connection.rb +2 -2
- data/lib/mongo/server/push_monitor.rb +1 -1
- data/lib/mongo/server_selector/base.rb +5 -1
- data/lib/mongo/session.rb +3 -0
- data/lib/mongo/socket.rb +6 -4
- data/lib/mongo/socket/ocsp_cache.rb +97 -0
- data/lib/mongo/socket/ocsp_verifier.rb +368 -0
- data/lib/mongo/socket/ssl.rb +45 -24
- data/lib/mongo/srv/monitor.rb +7 -13
- data/lib/mongo/srv/resolver.rb +14 -10
- data/lib/mongo/timeout.rb +2 -0
- data/lib/mongo/uri.rb +21 -390
- data/lib/mongo/uri/options_mapper.rb +582 -0
- data/lib/mongo/uri/srv_protocol.rb +3 -2
- data/lib/mongo/utils.rb +12 -1
- data/lib/mongo/version.rb +1 -1
- data/spec/NOTES.aws-auth.md +12 -7
- data/spec/README.md +56 -1
- data/spec/integration/bulk_write_spec.rb +48 -0
- data/spec/integration/client_authentication_options_spec.rb +55 -28
- data/spec/integration/connection_pool_populator_spec.rb +3 -1
- data/spec/integration/cursor_reaping_spec.rb +53 -17
- data/spec/integration/ocsp_connectivity_spec.rb +26 -0
- data/spec/integration/ocsp_verifier_cache_spec.rb +188 -0
- data/spec/integration/ocsp_verifier_spec.rb +334 -0
- data/spec/integration/query_cache_spec.rb +1045 -0
- data/spec/integration/query_cache_transactions_spec.rb +179 -0
- data/spec/integration/retryable_writes/retryable_writes_40_and_newer_spec.rb +1 -0
- data/spec/integration/retryable_writes/shared/performs_legacy_retries.rb +2 -0
- data/spec/integration/sdam_error_handling_spec.rb +68 -0
- data/spec/integration/server_selection_spec.rb +36 -0
- data/spec/integration/srv_monitoring_spec.rb +38 -3
- data/spec/integration/srv_spec.rb +56 -0
- data/spec/lite_spec_helper.rb +3 -1
- data/spec/mongo/address_spec.rb +1 -1
- data/spec/mongo/caching_cursor_spec.rb +70 -0
- data/spec/mongo/client_construction_spec.rb +54 -1
- data/spec/mongo/client_spec.rb +40 -0
- data/spec/mongo/cluster/topology/single_spec.rb +14 -5
- data/spec/mongo/cluster_spec.rb +3 -0
- data/spec/mongo/collection/view/explainable_spec.rb +87 -4
- data/spec/mongo/collection/view/map_reduce_spec.rb +2 -0
- data/spec/mongo/collection_spec.rb +60 -0
- data/spec/mongo/crypt/auto_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/auto_encryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_decryption_context_spec.rb +1 -1
- data/spec/mongo/crypt/explicit_encryption_context_spec.rb +1 -1
- data/spec/mongo/database_spec.rb +44 -0
- data/spec/mongo/error/no_server_available_spec.rb +1 -1
- data/spec/mongo/logger_spec.rb +13 -11
- data/spec/mongo/query_cache_spec.rb +279 -0
- data/spec/mongo/server/connection_pool_spec.rb +7 -3
- data/spec/mongo/server/connection_spec.rb +14 -7
- data/spec/mongo/socket/ssl_spec.rb +1 -1
- data/spec/mongo/socket_spec.rb +1 -1
- data/spec/mongo/uri/srv_protocol_spec.rb +64 -33
- data/spec/mongo/uri_option_parsing_spec.rb +11 -11
- data/spec/mongo/uri_spec.rb +68 -41
- data/spec/mongo/utils_spec.rb +39 -0
- data/spec/runners/auth.rb +3 -0
- data/spec/runners/connection_string.rb +35 -124
- data/spec/spec_tests/cmap_spec.rb +7 -3
- data/spec/spec_tests/data/change_streams/change-streams-errors.yml +0 -1
- data/spec/spec_tests/data/change_streams/change-streams.yml +0 -1
- data/spec/spec_tests/data/cmap/pool-checkout-connection.yml +6 -2
- data/spec/spec_tests/data/cmap/pool-create-min-size.yml +3 -0
- data/spec/spec_tests/data/connection_string/valid-warnings.yml +24 -0
- data/spec/spec_tests/data/sdam_monitoring/discovered_standalone.yml +1 -3
- data/spec/spec_tests/data/sdam_monitoring/standalone.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_repeated.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +2 -2
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +2 -2
- data/spec/spec_tests/data/uri_options/auth-options.yml +25 -0
- data/spec/spec_tests/data/uri_options/compression-options.yml +6 -3
- data/spec/spec_tests/data/uri_options/read-preference-options.yml +24 -0
- data/spec/spec_tests/data/uri_options/ruby-connection-options.yml +1 -0
- data/spec/spec_tests/data/uri_options/tls-options.yml +160 -4
- data/spec/spec_tests/dns_seedlist_discovery_spec.rb +9 -1
- data/spec/spec_tests/uri_options_spec.rb +31 -33
- data/spec/support/certificates/atlas-ocsp-ca.crt +28 -0
- data/spec/support/certificates/atlas-ocsp.crt +41 -0
- data/spec/support/client_registry_macros.rb +11 -2
- data/spec/support/common_shortcuts.rb +45 -0
- data/spec/support/constraints.rb +23 -0
- data/spec/support/lite_constraints.rb +24 -0
- data/spec/support/matchers.rb +16 -0
- data/spec/support/ocsp +1 -0
- data/spec/support/session_registry.rb +52 -0
- data/spec/support/spec_config.rb +22 -0
- data/spec/support/utils.rb +19 -1
- metadata +38 -3
- metadata.gz.sig +0 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'lite_spec_helper'
|
2
|
+
|
3
|
+
# These tests test the configurations described in
|
4
|
+
# https://github.com/mongodb/specifications/blob/master/source/ocsp-support/tests/README.rst#integration-tests-permutations-to-be-tested
|
5
|
+
describe 'OCSP connectivity' do
|
6
|
+
require_ocsp_connectivity
|
7
|
+
clear_ocsp_cache
|
8
|
+
|
9
|
+
let(:client) do
|
10
|
+
new_local_client(ENV.fetch('MONGODB_URI'),
|
11
|
+
server_selection_timeout: 5,
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
if ENV['OCSP_CONNECTIVITY'] == 'fail'
|
16
|
+
it 'fails to connect' do
|
17
|
+
lambda do
|
18
|
+
client.command(ping: 1)
|
19
|
+
end.should raise_error(Mongo::Error::NoServerAvailable, /UNKNOWN/)
|
20
|
+
end
|
21
|
+
else
|
22
|
+
it 'works' do
|
23
|
+
client.command(ping: 1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'lite_spec_helper'
|
2
|
+
require 'webrick'
|
3
|
+
|
4
|
+
describe Mongo::Socket::OcspVerifier do
|
5
|
+
require_ocsp_verifier
|
6
|
+
|
7
|
+
shared_examples 'verifies' do
|
8
|
+
context 'mri' do
|
9
|
+
fails_on_jruby
|
10
|
+
|
11
|
+
it 'verifies the first time and reads from cache the second time' do
|
12
|
+
RSpec::Mocks.with_temporary_scope do
|
13
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
14
|
+
|
15
|
+
verifier.verify_with_cache.should be true
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec::Mocks.with_temporary_scope do
|
19
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).not_to receive(:do_verify)
|
20
|
+
|
21
|
+
verifier.verify_with_cache.should be true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'jruby' do
|
27
|
+
require_jruby
|
28
|
+
|
29
|
+
# JRuby does not return OCSP endpoints, therefore we never perform
|
30
|
+
# any validation.
|
31
|
+
# https://github.com/jruby/jruby-openssl/issues/210
|
32
|
+
it 'does not verify' do
|
33
|
+
RSpec::Mocks.with_temporary_scope do
|
34
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
35
|
+
|
36
|
+
verifier.verify.should be false
|
37
|
+
end
|
38
|
+
|
39
|
+
RSpec::Mocks.with_temporary_scope do
|
40
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
41
|
+
|
42
|
+
verifier.verify.should be false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
shared_examples 'fails verification' do
|
49
|
+
context 'mri' do
|
50
|
+
fails_on_jruby
|
51
|
+
|
52
|
+
it 'verifies the first time, reads from cache the second time, raises an exception in both cases' do
|
53
|
+
RSpec::Mocks.with_temporary_scope do
|
54
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
55
|
+
|
56
|
+
lambda do
|
57
|
+
verifier.verify
|
58
|
+
# Redirect tests receive responses from port 8101,
|
59
|
+
# tests without redirects receive responses from port 8100.
|
60
|
+
end.should raise_error(Mongo::Error::ServerCertificateRevoked, %r,TLS certificate of 'foo' has been revoked according to 'http://localhost:810[01]/status',)
|
61
|
+
end
|
62
|
+
|
63
|
+
RSpec::Mocks.with_temporary_scope do
|
64
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).not_to receive(:do_verify)
|
65
|
+
|
66
|
+
lambda do
|
67
|
+
verifier.verify
|
68
|
+
# Redirect tests receive responses from port 8101,
|
69
|
+
# tests without redirects receive responses from port 8100.
|
70
|
+
end.should raise_error(Mongo::Error::ServerCertificateRevoked, %r,TLS certificate of 'foo' has been revoked according to 'http://localhost:810[01]/status',)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'jruby' do
|
76
|
+
require_jruby
|
77
|
+
|
78
|
+
# JRuby does not return OCSP endpoints, therefore we never perform
|
79
|
+
# any validation.
|
80
|
+
# https://github.com/jruby/jruby-openssl/issues/210
|
81
|
+
it 'does not verify' do
|
82
|
+
RSpec::Mocks.with_temporary_scope do
|
83
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
84
|
+
|
85
|
+
verifier.verify.should be false
|
86
|
+
end
|
87
|
+
|
88
|
+
RSpec::Mocks.with_temporary_scope do
|
89
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
90
|
+
|
91
|
+
verifier.verify.should be false
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
shared_examples 'does not verify' do
|
98
|
+
it 'does not verify and does not raise an exception' do
|
99
|
+
RSpec::Mocks.with_temporary_scope do
|
100
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
101
|
+
|
102
|
+
verifier.verify.should be false
|
103
|
+
end
|
104
|
+
|
105
|
+
RSpec::Mocks.with_temporary_scope do
|
106
|
+
expect_any_instance_of(Mongo::Socket::OcspVerifier).to receive(:do_verify).and_call_original
|
107
|
+
|
108
|
+
verifier.verify.should be false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
shared_context 'verifier' do |opts|
|
114
|
+
algorithm = opts[:algorithm]
|
115
|
+
|
116
|
+
let(:cert_path) { SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/server.pem") }
|
117
|
+
let(:ca_cert_path) { SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem") }
|
118
|
+
|
119
|
+
let(:cert) { OpenSSL::X509::Certificate.new(File.read(cert_path)) }
|
120
|
+
let(:ca_cert) { OpenSSL::X509::Certificate.new(File.read(ca_cert_path)) }
|
121
|
+
|
122
|
+
let(:cert_store) do
|
123
|
+
OpenSSL::X509::Store.new.tap do |store|
|
124
|
+
store.add_cert(ca_cert)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
let(:verifier) do
|
129
|
+
described_class.new('foo', cert, ca_cert, cert_store, timeout: 3)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
include_context 'verifier', algorithm: 'rsa'
|
134
|
+
algorithm = 'rsa'
|
135
|
+
|
136
|
+
%w(ca delegate).each do |responder_cert|
|
137
|
+
responder_cert_file_name = {
|
138
|
+
'ca' => 'ca',
|
139
|
+
'delegate' => 'ocsp-responder',
|
140
|
+
}.fetch(responder_cert)
|
141
|
+
|
142
|
+
context "when responder uses #{responder_cert} cert" do
|
143
|
+
context 'good response' do
|
144
|
+
with_ocsp_mock(
|
145
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
146
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
147
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
148
|
+
)
|
149
|
+
|
150
|
+
include_examples 'verifies'
|
151
|
+
|
152
|
+
it 'does not wait for the timeout' do
|
153
|
+
lambda do
|
154
|
+
verifier.verify
|
155
|
+
end.should take_shorter_than 3
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'revoked response' do
|
160
|
+
with_ocsp_mock(
|
161
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
162
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
163
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
164
|
+
fault: 'revoked'
|
165
|
+
)
|
166
|
+
|
167
|
+
include_examples 'fails verification'
|
168
|
+
end
|
169
|
+
|
170
|
+
context 'unknown response' do
|
171
|
+
with_ocsp_mock(
|
172
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
173
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
174
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
175
|
+
fault: 'unknown',
|
176
|
+
)
|
177
|
+
|
178
|
+
include_examples 'does not verify'
|
179
|
+
|
180
|
+
it 'does not wait for the timeout' do
|
181
|
+
lambda do
|
182
|
+
verifier.verify
|
183
|
+
end.should take_shorter_than 3
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,334 @@
|
|
1
|
+
require 'lite_spec_helper'
|
2
|
+
require 'webrick'
|
3
|
+
|
4
|
+
describe Mongo::Socket::OcspVerifier do
|
5
|
+
require_ocsp_verifier
|
6
|
+
|
7
|
+
shared_examples 'verifies' do
|
8
|
+
context 'mri' do
|
9
|
+
fails_on_jruby
|
10
|
+
|
11
|
+
it 'verifies' do
|
12
|
+
verifier.verify.should be true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'jruby' do
|
17
|
+
require_jruby
|
18
|
+
|
19
|
+
# JRuby does not return OCSP endpoints, therefore we never perform
|
20
|
+
# any validation.
|
21
|
+
# https://github.com/jruby/jruby-openssl/issues/210
|
22
|
+
it 'does not verify' do
|
23
|
+
verifier.verify.should be false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
shared_examples 'fails verification' do
|
29
|
+
context 'mri' do
|
30
|
+
fails_on_jruby
|
31
|
+
|
32
|
+
it 'raises an exception' do
|
33
|
+
lambda do
|
34
|
+
verifier.verify
|
35
|
+
# Redirect tests receive responses from port 8101,
|
36
|
+
# tests without redirects receive responses from port 8100.
|
37
|
+
end.should raise_error(Mongo::Error::ServerCertificateRevoked, %r,TLS certificate of 'foo' has been revoked according to 'http://localhost:810[01]/status',)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'does not wait for the timeout' do
|
41
|
+
lambda do
|
42
|
+
lambda do
|
43
|
+
verifier.verify
|
44
|
+
end.should raise_error(Mongo::Error::ServerCertificateRevoked)
|
45
|
+
end.should take_shorter_than 3
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'jruby' do
|
50
|
+
require_jruby
|
51
|
+
|
52
|
+
# JRuby does not return OCSP endpoints, therefore we never perform
|
53
|
+
# any validation.
|
54
|
+
# https://github.com/jruby/jruby-openssl/issues/210
|
55
|
+
it 'does not verify' do
|
56
|
+
verifier.verify.should be false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
shared_examples 'does not verify' do
|
62
|
+
it 'does not verify and does not raise an exception' do
|
63
|
+
verifier.verify.should be false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
shared_context 'basic verifier' do
|
68
|
+
|
69
|
+
let(:cert) { OpenSSL::X509::Certificate.new(File.read(cert_path)) }
|
70
|
+
let(:ca_cert) { OpenSSL::X509::Certificate.new(File.read(ca_cert_path)) }
|
71
|
+
|
72
|
+
let(:cert_store) do
|
73
|
+
OpenSSL::X509::Store.new.tap do |store|
|
74
|
+
store.add_cert(ca_cert)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
let(:verifier) do
|
79
|
+
described_class.new('foo', cert, ca_cert, cert_store, timeout: 3)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
shared_context 'verifier' do |opts|
|
84
|
+
algorithm = opts[:algorithm]
|
85
|
+
|
86
|
+
let(:cert_path) { SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/server.pem") }
|
87
|
+
let(:ca_cert_path) { SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem") }
|
88
|
+
|
89
|
+
include_context 'basic verifier'
|
90
|
+
end
|
91
|
+
|
92
|
+
%w(rsa ecdsa).each do |algorithm|
|
93
|
+
context "when using #{algorithm} cert" do
|
94
|
+
include_context 'verifier', algorithm: algorithm
|
95
|
+
|
96
|
+
context 'responder not responding' do
|
97
|
+
include_examples 'does not verify'
|
98
|
+
|
99
|
+
it 'does not wait for the timeout' do
|
100
|
+
# Loopback interface should be refusing connections, which will make
|
101
|
+
# the operation complete quickly.
|
102
|
+
lambda do
|
103
|
+
verifier.verify
|
104
|
+
end.should take_shorter_than 3
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
%w(ca delegate).each do |responder_cert|
|
109
|
+
responder_cert_file_name = {
|
110
|
+
'ca' => 'ca',
|
111
|
+
'delegate' => 'ocsp-responder',
|
112
|
+
}.fetch(responder_cert)
|
113
|
+
|
114
|
+
context "when responder uses #{responder_cert} cert" do
|
115
|
+
context 'good response' do
|
116
|
+
with_ocsp_mock(
|
117
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
118
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
119
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
120
|
+
)
|
121
|
+
|
122
|
+
include_examples 'verifies'
|
123
|
+
|
124
|
+
it 'does not wait for the timeout' do
|
125
|
+
lambda do
|
126
|
+
verifier.verify
|
127
|
+
end.should take_shorter_than 3
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'revoked response' do
|
132
|
+
with_ocsp_mock(
|
133
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
134
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
135
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
136
|
+
fault: 'revoked'
|
137
|
+
)
|
138
|
+
|
139
|
+
include_examples 'fails verification'
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'unknown response' do
|
143
|
+
with_ocsp_mock(
|
144
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
145
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
146
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
147
|
+
fault: 'unknown',
|
148
|
+
)
|
149
|
+
|
150
|
+
include_examples 'does not verify'
|
151
|
+
|
152
|
+
it 'does not wait for the timeout' do
|
153
|
+
lambda do
|
154
|
+
verifier.verify
|
155
|
+
end.should take_shorter_than 3
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'when OCSP responder redirects' do
|
164
|
+
algorithm = 'rsa'
|
165
|
+
responder_cert_file_name = 'ca'
|
166
|
+
let(:algorithm) { 'rsa' }
|
167
|
+
let(:responder_cert_file_name) { 'ca' }
|
168
|
+
|
169
|
+
context 'one time' do
|
170
|
+
|
171
|
+
around do |example|
|
172
|
+
server = WEBrick::HTTPServer.new(Port: 8100)
|
173
|
+
server.mount_proc '/' do |req, res|
|
174
|
+
res.status = 303
|
175
|
+
res['locAtion'] = "http://localhost:8101#{req.path}"
|
176
|
+
res.body = "See http://localhost:8101#{req.path}"
|
177
|
+
end
|
178
|
+
Thread.new { server.start }
|
179
|
+
begin
|
180
|
+
example.run
|
181
|
+
ensure
|
182
|
+
server.shutdown
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
include_context 'verifier', algorithm: algorithm
|
187
|
+
|
188
|
+
context 'good response' do
|
189
|
+
with_ocsp_mock(
|
190
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
191
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
192
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
193
|
+
port: 8101,
|
194
|
+
)
|
195
|
+
|
196
|
+
include_examples 'verifies'
|
197
|
+
|
198
|
+
it 'does not wait for the timeout' do
|
199
|
+
lambda do
|
200
|
+
verifier.verify
|
201
|
+
end.should take_shorter_than 3
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context 'revoked response' do
|
206
|
+
with_ocsp_mock(
|
207
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
208
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
209
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
210
|
+
fault: 'revoked',
|
211
|
+
port: 8101,
|
212
|
+
)
|
213
|
+
|
214
|
+
include_examples 'fails verification'
|
215
|
+
end
|
216
|
+
|
217
|
+
context 'unknown response' do
|
218
|
+
with_ocsp_mock(
|
219
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
220
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
221
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
222
|
+
fault: 'unknown',
|
223
|
+
port: 8101,
|
224
|
+
)
|
225
|
+
|
226
|
+
include_examples 'does not verify'
|
227
|
+
|
228
|
+
it 'does not wait for the timeout' do
|
229
|
+
lambda do
|
230
|
+
verifier.verify
|
231
|
+
end.should take_shorter_than 3
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context 'infinitely' do
|
237
|
+
with_ocsp_mock(
|
238
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/ca.pem"),
|
239
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.crt"),
|
240
|
+
SpecConfig.instance.ocsp_files_dir.join("#{algorithm}/#{responder_cert_file_name}.key"),
|
241
|
+
port: 8101,
|
242
|
+
)
|
243
|
+
|
244
|
+
around do |example|
|
245
|
+
server = WEBrick::HTTPServer.new(Port: 8100)
|
246
|
+
server.mount_proc '/' do |req, res|
|
247
|
+
res.status = 303
|
248
|
+
res['locAtion'] = req.path
|
249
|
+
res.body = "See #{req.path} indefinitely"
|
250
|
+
end
|
251
|
+
Thread.new { server.start }
|
252
|
+
begin
|
253
|
+
example.run
|
254
|
+
ensure
|
255
|
+
server.shutdown
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
include_context 'verifier', algorithm: algorithm
|
260
|
+
include_examples 'does not verify'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context 'responder returns unexpected status code' do
|
265
|
+
|
266
|
+
include_context 'verifier', algorithm: 'rsa'
|
267
|
+
|
268
|
+
context '40x / 50x' do
|
269
|
+
around do |example|
|
270
|
+
server = WEBrick::HTTPServer.new(Port: 8100)
|
271
|
+
server.mount_proc '/' do |req, res|
|
272
|
+
res.status = code
|
273
|
+
res.body = "HTTP #{code}"
|
274
|
+
end
|
275
|
+
Thread.new { server.start }
|
276
|
+
begin
|
277
|
+
example.run
|
278
|
+
ensure
|
279
|
+
server.shutdown
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
[400, 404, 500, 503].each do |_code|
|
284
|
+
context "code #{_code}" do
|
285
|
+
let(:code) { _code }
|
286
|
+
include_examples 'does not verify'
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context '204' do
|
292
|
+
around do |example|
|
293
|
+
server = WEBrick::HTTPServer.new(Port: 8100)
|
294
|
+
server.mount_proc '/' do |req, res|
|
295
|
+
res.status = 204
|
296
|
+
end
|
297
|
+
Thread.new { server.start }
|
298
|
+
begin
|
299
|
+
example.run
|
300
|
+
ensure
|
301
|
+
server.shutdown
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "code 204" do
|
306
|
+
let(:code) { 204 }
|
307
|
+
include_examples 'does not verify'
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context 'responder URI has no path' do
|
313
|
+
require_external_connectivity
|
314
|
+
|
315
|
+
include_context 'basic verifier'
|
316
|
+
|
317
|
+
let(:cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp.crt') }
|
318
|
+
let(:ca_cert_path) { File.join(File.dirname(__FILE__), '../support/certificates/atlas-ocsp-ca.crt') }
|
319
|
+
let(:cert_store) do
|
320
|
+
OpenSSL::X509::Store.new.tap do |store|
|
321
|
+
store.set_default_paths
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
before do
|
326
|
+
URI.parse(verifier.ocsp_uris.first).path.should == ''
|
327
|
+
end
|
328
|
+
|
329
|
+
it 'verifies' do
|
330
|
+
# TODO This test might fail if the certificate expires?
|
331
|
+
verifier.verify.should be true
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|