mongo 2.11.1 → 2.11.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -1
- data.tar.gz.sig +2 -1
- data/Rakefile +24 -0
- data/lib/mongo/address.rb +53 -37
- data/lib/mongo/auth.rb +30 -10
- data/lib/mongo/auth/cr.rb +1 -0
- data/lib/mongo/auth/cr/conversation.rb +13 -13
- data/lib/mongo/auth/ldap.rb +2 -1
- data/lib/mongo/auth/ldap/conversation.rb +9 -12
- data/lib/mongo/auth/scram.rb +1 -0
- data/lib/mongo/auth/scram/conversation.rb +36 -27
- data/lib/mongo/auth/user.rb +7 -1
- data/lib/mongo/auth/x509.rb +2 -1
- data/lib/mongo/auth/x509/conversation.rb +9 -9
- data/lib/mongo/bulk_write/transformable.rb +3 -3
- data/lib/mongo/client.rb +17 -6
- data/lib/mongo/cluster.rb +67 -49
- data/lib/mongo/cluster/sdam_flow.rb +87 -3
- data/lib/mongo/collection/view/readable.rb +3 -1
- data/lib/mongo/collection/view/writable.rb +3 -3
- data/lib/mongo/cursor/builder/kill_cursors_command.rb +8 -1
- data/lib/mongo/cursor/builder/op_kill_cursors.rb +8 -1
- data/lib/mongo/database.rb +1 -1
- data/lib/mongo/grid/file.rb +5 -0
- data/lib/mongo/grid/file/chunk.rb +2 -0
- data/lib/mongo/grid/fs_bucket.rb +15 -13
- data/lib/mongo/grid/stream/write.rb +9 -3
- data/lib/mongo/protocol/serializers.rb +12 -2
- data/lib/mongo/server.rb +13 -6
- data/lib/mongo/server/connection.rb +15 -8
- data/lib/mongo/server/connection_base.rb +7 -4
- data/lib/mongo/server/description.rb +34 -21
- data/lib/mongo/server/monitor.rb +1 -1
- data/lib/mongo/server/monitor/connection.rb +2 -3
- data/lib/mongo/session.rb +10 -10
- data/lib/mongo/socket.rb +10 -1
- data/lib/mongo/uri.rb +1 -1
- data/lib/mongo/version.rb +1 -1
- data/mongo.gemspec +1 -1
- data/spec/README.md +13 -0
- data/spec/integration/auth_spec.rb +27 -8
- data/spec/integration/bson_symbol_spec.rb +34 -0
- data/spec/integration/client_construction_spec.rb +14 -0
- data/spec/integration/client_options_spec.rb +5 -5
- data/spec/integration/connection_spec.rb +57 -9
- data/spec/integration/crud_spec.rb +45 -0
- data/spec/integration/cursor_reaping_spec.rb +2 -1
- data/spec/integration/grid_fs_bucket_spec.rb +48 -0
- data/spec/integration/retryable_errors_spec.rb +2 -2
- data/spec/integration/zlib_compression_spec.rb +25 -0
- data/spec/lite_spec_helper.rb +1 -0
- data/spec/mongo/address_spec.rb +19 -13
- data/spec/mongo/auth/ldap/conversation_spec.rb +1 -1
- data/spec/mongo/auth/scram/conversation_spec.rb +25 -14
- data/spec/mongo/auth/user/view_spec.rb +39 -7
- data/spec/mongo/auth/user_spec.rb +12 -0
- data/spec/mongo/auth/x509/conversation_spec.rb +1 -1
- data/spec/mongo/bulk_write_spec.rb +2 -2
- data/spec/mongo/client_construction_spec.rb +3 -22
- data/spec/mongo/cluster_spec.rb +57 -0
- data/spec/mongo/collection/view/map_reduce_spec.rb +1 -1
- data/spec/mongo/collection_spec.rb +26 -2
- data/spec/mongo/cursor/builder/op_kill_cursors_spec.rb +56 -0
- data/spec/mongo/server/connection_spec.rb +76 -8
- data/spec/mongo/server/monitor/connection_spec.rb +14 -7
- data/spec/mongo/socket/ssl_spec.rb +132 -98
- data/spec/mongo/socket/tcp_spec.rb +1 -9
- data/spec/mongo/uri_spec.rb +1 -1
- data/spec/runners/sdam/verifier.rb +6 -3
- data/spec/spec_tests/data/sdam/rs/primary_address_change.yml +29 -0
- data/spec/spec_tests/data/sdam/rs/primary_mismatched_me.yml +27 -23
- data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +56 -79
- data/spec/spec_tests/data/sdam/sharded/primary_address_change.yml +21 -0
- data/spec/spec_tests/data/sdam/sharded/primary_mismatched_me.yml +22 -0
- data/spec/spec_tests/data/sdam/single/primary_address_change.yml +24 -0
- data/spec/spec_tests/data/sdam/single/primary_mismatched_me.yml +25 -0
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +159 -0
- data/spec/spec_tests/data/sdam_monitoring/{replica_set_other_seed.yml → replica_set_with_primary_change.yml} +97 -101
- data/spec/spec_tests/data/sdam_monitoring/replica_set_with_primary_removal.yml +22 -18
- data/spec/spec_tests/data/sdam_monitoring/standalone_to_rs_with_me_mismatch.yml +90 -0
- data/spec/support/cluster_config.rb +36 -0
- data/spec/support/cluster_tools.rb +5 -3
- data/spec/support/command_monitoring.rb +1 -1
- data/spec/support/constraints.rb +18 -18
- data/spec/support/lite_constraints.rb +8 -0
- data/spec/support/server_discovery_and_monitoring.rb +2 -0
- data/spec/support/spec_config.rb +3 -3
- data/spec/support/utils.rb +11 -1
- metadata +661 -637
- metadata.gz.sig +0 -0
@@ -575,7 +575,7 @@ describe Mongo::Collection::View::MapReduce do
|
|
575
575
|
expect(map_reduce.send(:secondary_ok?)).to be false
|
576
576
|
end
|
577
577
|
|
578
|
-
context 'when the server is not
|
578
|
+
context 'when the server is not valid for writing' do
|
579
579
|
clean_slate
|
580
580
|
|
581
581
|
before do
|
@@ -278,9 +278,9 @@ describe Mongo::Collection do
|
|
278
278
|
require_topology :replica_set
|
279
279
|
|
280
280
|
let(:client_options) do
|
281
|
-
|
281
|
+
SpecConfig.instance.auth_options.merge(
|
282
282
|
read: { mode: :primary_preferred },
|
283
|
-
|
283
|
+
)
|
284
284
|
end
|
285
285
|
|
286
286
|
let(:subscriber) { EventSubscriber.new }
|
@@ -945,6 +945,30 @@ describe Mongo::Collection do
|
|
945
945
|
it_behaves_like 'a failed operation using a session'
|
946
946
|
end
|
947
947
|
end
|
948
|
+
|
949
|
+
context 'when collation has a strength' do
|
950
|
+
min_server_fcv '3.4'
|
951
|
+
|
952
|
+
let(:band_collection) do
|
953
|
+
described_class.new(database, :bands)
|
954
|
+
end
|
955
|
+
|
956
|
+
before do
|
957
|
+
band_collection.delete_many
|
958
|
+
band_collection.insert_many([{ name: "Depeche Mode" }, { name: "New Order" }])
|
959
|
+
end
|
960
|
+
|
961
|
+
let(:options) do
|
962
|
+
{ collation: { locale: 'en_US', strength: 2 } }
|
963
|
+
end
|
964
|
+
let(:band_result) do
|
965
|
+
band_collection.find({ name: 'DEPECHE MODE' }, options)
|
966
|
+
end
|
967
|
+
|
968
|
+
it 'finds Capitalize from UPPER CASE' do
|
969
|
+
expect(band_result.count_documents).to eq(1)
|
970
|
+
end
|
971
|
+
end
|
948
972
|
end
|
949
973
|
|
950
974
|
describe '#drop' do
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongo::Cursor::Builder::OpKillCursors do
|
4
|
+
|
5
|
+
let(:reply) do
|
6
|
+
Mongo::Protocol::Reply.allocate.tap do |reply|
|
7
|
+
allow(reply).to receive(:cursor_id).and_return(8000)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:result) do
|
12
|
+
Mongo::Operation::Result.new(reply)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:view) do
|
16
|
+
Mongo::Collection::View.new(
|
17
|
+
authorized_collection,
|
18
|
+
{},
|
19
|
+
tailable: true,
|
20
|
+
max_time_ms: 100
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:cursor) do
|
25
|
+
Mongo::Cursor.new(view, result, authorized_primary)
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:builder) do
|
29
|
+
described_class.new(cursor)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#specification' do
|
33
|
+
|
34
|
+
let(:specification) do
|
35
|
+
builder.specification
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'includes the cursor ids' do
|
39
|
+
expect(specification[:cursor_ids]).to eq([BSON::Int64.new(8000)])
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'includes the database name' do
|
43
|
+
expect(specification[:db_name]).to eq(SpecConfig.instance.test_db)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'includes the collection name' do
|
47
|
+
expect(specification[:coll_name]).to eq(TEST_COLL)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.get_cursors_list' do
|
52
|
+
it 'returns integer cursor ids' do
|
53
|
+
expect(described_class.get_cursors_list(builder.specification)).to eq([8000])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -137,12 +137,13 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
137
137
|
|
138
138
|
it 'logs a warning' do
|
139
139
|
messages = []
|
140
|
-
# Straightforward expectations are not working here for some reason
|
141
140
|
expect(Mongo::Logger.logger).to receive(:warn) do |msg|
|
142
141
|
messages << msg
|
143
142
|
end
|
143
|
+
|
144
144
|
expect(error).not_to be nil
|
145
|
-
|
145
|
+
|
146
|
+
messages.any? { |msg| msg.include?(expected_message) }.should be true
|
146
147
|
end
|
147
148
|
|
148
149
|
end
|
@@ -419,6 +420,73 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
419
420
|
end
|
420
421
|
end
|
421
422
|
|
423
|
+
context 'connecting to arbiter' do
|
424
|
+
require_topology :replica_set
|
425
|
+
|
426
|
+
before(:all) do
|
427
|
+
unless ENV['HAVE_ARBITER']
|
428
|
+
skip 'Test requires an arbiter in the deployment'
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
let(:arbiter_server) do
|
433
|
+
authorized_client.cluster.servers_list.each do |server|
|
434
|
+
server.scan!
|
435
|
+
end
|
436
|
+
server = authorized_client.cluster.servers_list.detect do |server|
|
437
|
+
server.arbiter?
|
438
|
+
end.tap do |server|
|
439
|
+
raise 'No arbiter in the deployment' unless server
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
shared_examples_for 'does not authenticate' do
|
444
|
+
let(:client) do
|
445
|
+
new_local_client([address],
|
446
|
+
SpecConfig.instance.test_options.merge(
|
447
|
+
:user => 'bogus',
|
448
|
+
:password => 'bogus',
|
449
|
+
:database => 'bogus'
|
450
|
+
).merge(connect: :direct),
|
451
|
+
)
|
452
|
+
end
|
453
|
+
|
454
|
+
let(:connection) do
|
455
|
+
described_class.new(
|
456
|
+
server,
|
457
|
+
)
|
458
|
+
end
|
459
|
+
|
460
|
+
let(:ping) do
|
461
|
+
client.database.command(ping: 1)
|
462
|
+
end
|
463
|
+
|
464
|
+
it 'does not authenticate' do
|
465
|
+
ClientRegistry.instance.close_all_clients
|
466
|
+
|
467
|
+
expect_any_instance_of(Mongo::Server::Connection).not_to receive(:authenticate!)
|
468
|
+
|
469
|
+
expect(ping.documents.first['ok']).to eq(1) rescue nil
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
context 'without me mismatch' do
|
474
|
+
let(:address) do
|
475
|
+
arbiter_server.address.to_s
|
476
|
+
end
|
477
|
+
|
478
|
+
it_behaves_like 'does not authenticate'
|
479
|
+
end
|
480
|
+
|
481
|
+
context 'with me mismatch' do
|
482
|
+
let(:address) do
|
483
|
+
"#{ClusterConfig.instance.alternate_address.host}:#{arbiter_server.address.port}"
|
484
|
+
end
|
485
|
+
|
486
|
+
it_behaves_like 'does not authenticate'
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
422
490
|
end
|
423
491
|
|
424
492
|
describe '#disconnect!' do
|
@@ -1012,7 +1080,7 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
1012
1080
|
end
|
1013
1081
|
|
1014
1082
|
it 'uses the connect_timeout for the address' do
|
1015
|
-
expect(connection.address.
|
1083
|
+
expect(connection.address.options[:connect_timeout]).to eq(3)
|
1016
1084
|
end
|
1017
1085
|
|
1018
1086
|
it 'uses the socket_timeout as the socket_timeout' do
|
@@ -1031,7 +1099,7 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
1031
1099
|
end
|
1032
1100
|
|
1033
1101
|
it 'uses the connect_timeout for the address' do
|
1034
|
-
expect(connection.address.
|
1102
|
+
expect(connection.address.options[:connect_timeout]).to eq(3)
|
1035
1103
|
end
|
1036
1104
|
|
1037
1105
|
it 'does not use a socket_timeout' do
|
@@ -1052,8 +1120,8 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
1052
1120
|
connection.connect!
|
1053
1121
|
end
|
1054
1122
|
|
1055
|
-
it '
|
1056
|
-
expect(connection.address.
|
1123
|
+
it 'does not specify connect_timeout for the address' do
|
1124
|
+
expect(connection.address.options[:connect_timeout]).to be nil
|
1057
1125
|
end
|
1058
1126
|
|
1059
1127
|
it 'uses the socket_timeout' do
|
@@ -1071,8 +1139,8 @@ describe Mongo::Server::Connection, retry: 3 do
|
|
1071
1139
|
connection.connect!
|
1072
1140
|
end
|
1073
1141
|
|
1074
|
-
it '
|
1075
|
-
expect(connection.address.
|
1142
|
+
it 'does not specify connect_timeout for the address' do
|
1143
|
+
expect(connection.address.options[:connect_timeout]).to be nil
|
1076
1144
|
end
|
1077
1145
|
|
1078
1146
|
it 'does not use a socket_timeout' do
|
@@ -66,7 +66,7 @@ describe Mongo::Server::Monitor::Connection do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'uses the connect_timeout for the address' do
|
69
|
-
expect(connection.address.
|
69
|
+
expect(connection.address.options[:connect_timeout]).to eq(3)
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'uses the connect_timeout as the socket_timeout' do
|
@@ -81,7 +81,7 @@ describe Mongo::Server::Monitor::Connection do
|
|
81
81
|
end
|
82
82
|
|
83
83
|
it 'uses the connect_timeout for the address' do
|
84
|
-
expect(connection.address.
|
84
|
+
expect(connection.address.options[:connect_timeout]).to eq(3)
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'uses the connect_timeout as the socket_timeout' do
|
@@ -98,8 +98,8 @@ describe Mongo::Server::Monitor::Connection do
|
|
98
98
|
SpecConfig.instance.test_options.merge(connect_timeout: nil, socket_timeout: 5)
|
99
99
|
end
|
100
100
|
|
101
|
-
it '
|
102
|
-
expect(connection.address.
|
101
|
+
it 'does not specify connect_timeout for the address' do
|
102
|
+
expect(connection.address.options[:connect_timeout]).to be nil
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'uses the connect_timeout as the socket_timeout' do
|
@@ -113,8 +113,8 @@ describe Mongo::Server::Monitor::Connection do
|
|
113
113
|
SpecConfig.instance.test_options.merge(connect_timeout: nil, socket_timeout: nil)
|
114
114
|
end
|
115
115
|
|
116
|
-
it '
|
117
|
-
expect(connection.address.
|
116
|
+
it 'does not specify connect_timeout for the address' do
|
117
|
+
expect(connection.address.options[:connect_timeout]).to be nil
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'uses the connect_timeout as the socket_timeout' do
|
@@ -189,10 +189,17 @@ describe Mongo::Server::Monitor::Connection do
|
|
189
189
|
|
190
190
|
it 'logs a warning' do
|
191
191
|
expect_any_instance_of(Mongo::Socket).to receive(:write).and_raise(Mongo::Error::SocketError, 'test error')
|
192
|
-
|
192
|
+
|
193
|
+
messages = []
|
194
|
+
expect(Mongo::Logger.logger).to receive(:warn) do |msg|
|
195
|
+
messages << msg
|
196
|
+
end
|
197
|
+
|
193
198
|
expect do
|
194
199
|
monitor.connection.connect!
|
195
200
|
end.to raise_error(Mongo::Error::SocketError, 'test error')
|
201
|
+
|
202
|
+
messages.any? { |msg| msg.include?(expected_message) }.should be true
|
196
203
|
end
|
197
204
|
end
|
198
205
|
end
|
@@ -3,27 +3,18 @@ require 'spec_helper'
|
|
3
3
|
# this test performs direct network connections without retries.
|
4
4
|
# In case of intermittent network issues, retry the entire failing test.
|
5
5
|
describe Mongo::Socket::SSL, retry: 3 do
|
6
|
+
clean_slate_for_all
|
6
7
|
require_tls
|
7
8
|
|
8
|
-
let(:
|
9
|
-
default_address.tap do
|
10
|
-
ClientRegistry.instance.close_all_clients
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
let!(:resolver) do
|
15
|
-
address.send(:create_resolver, {})
|
16
|
-
end
|
17
|
-
|
18
|
-
let(:socket_timeout) do
|
19
|
-
1
|
20
|
-
end
|
9
|
+
let(:host_name) { 'localhost' }
|
21
10
|
|
22
11
|
let(:socket) do
|
23
|
-
|
12
|
+
described_class.new('127.0.0.1', default_address.port,
|
13
|
+
host_name, 1, :INET, ssl_options.merge(
|
14
|
+
connect_timeout: 2.4))
|
24
15
|
end
|
25
16
|
|
26
|
-
let(:
|
17
|
+
let(:ssl_options) do
|
27
18
|
SpecConfig.instance.ssl_options
|
28
19
|
end
|
29
20
|
|
@@ -82,7 +73,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
82
73
|
|
83
74
|
context 'when a certificate and key are provided as strings' do
|
84
75
|
|
85
|
-
let(:
|
76
|
+
let(:ssl_options) do
|
86
77
|
{
|
87
78
|
:ssl => true,
|
88
79
|
:ssl_cert_string => cert_string,
|
@@ -99,7 +90,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
99
90
|
context 'when certificate and an encrypted key are provided as strings' do
|
100
91
|
require_local_tls
|
101
92
|
|
102
|
-
let(:
|
93
|
+
let(:ssl_options) do
|
103
94
|
{
|
104
95
|
:ssl => true,
|
105
96
|
:ssl_cert_string => cert_string,
|
@@ -116,7 +107,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
116
107
|
|
117
108
|
context 'when a certificate and key are provided as objects' do
|
118
109
|
|
119
|
-
let(:
|
110
|
+
let(:ssl_options) do
|
120
111
|
{
|
121
112
|
:ssl => true,
|
122
113
|
:ssl_cert_object => cert_object,
|
@@ -132,7 +123,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
132
123
|
|
133
124
|
context 'when the certificate is specified using both a file and a PEM-encoded string' do
|
134
125
|
|
135
|
-
let(:
|
126
|
+
let(:ssl_options) do
|
136
127
|
super().merge(
|
137
128
|
:ssl_cert_string => 'This is a random string, not a PEM-encoded certificate'
|
138
129
|
)
|
@@ -146,7 +137,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
146
137
|
|
147
138
|
context 'when the certificate is specified using both a file and an object' do
|
148
139
|
|
149
|
-
let(:
|
140
|
+
let(:ssl_options) do
|
150
141
|
super().merge(
|
151
142
|
:ssl_cert_object => 'This is a string, not a certificate'
|
152
143
|
)
|
@@ -160,7 +151,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
160
151
|
|
161
152
|
context 'when the certificate is specified using both a PEM-encoded string and an object' do
|
162
153
|
|
163
|
-
let(:
|
154
|
+
let(:ssl_options) do
|
164
155
|
{
|
165
156
|
:ssl => true,
|
166
157
|
:ssl_cert_string => cert_string,
|
@@ -178,7 +169,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
178
169
|
|
179
170
|
context 'when the key is specified using both a file and a PEM-encoded string' do
|
180
171
|
|
181
|
-
let(:
|
172
|
+
let(:ssl_options) do
|
182
173
|
super().merge(
|
183
174
|
:ssl_key_string => 'This is a normal string, not a PEM-encoded key'
|
184
175
|
)
|
@@ -192,7 +183,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
192
183
|
|
193
184
|
context 'when the key is specified using both a file and an object' do
|
194
185
|
|
195
|
-
let(:
|
186
|
+
let(:ssl_options) do
|
196
187
|
super().merge(
|
197
188
|
:ssl_cert_object => 'This is a string, not a key'
|
198
189
|
)
|
@@ -206,7 +197,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
206
197
|
|
207
198
|
context 'when the key is specified using both a PEM-encoded string and an object' do
|
208
199
|
|
209
|
-
let(:
|
200
|
+
let(:ssl_options) do
|
210
201
|
{
|
211
202
|
:ssl => true,
|
212
203
|
:ssl_cert => SpecConfig.instance.client_cert_path,
|
@@ -224,7 +215,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
224
215
|
|
225
216
|
context 'when a certificate is passed, but it is not of the right type' do
|
226
217
|
|
227
|
-
let(:
|
218
|
+
let(:ssl_options) do
|
228
219
|
cert = "This is a string, not an X.509 Certificate"
|
229
220
|
{
|
230
221
|
:ssl => true,
|
@@ -247,38 +238,27 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
247
238
|
end
|
248
239
|
|
249
240
|
context 'when the hostname is verified' do
|
250
|
-
it 'raises an error' do
|
251
|
-
error = nil
|
252
|
-
begin
|
253
|
-
described_class.new(
|
254
|
-
resolver.host,
|
255
|
-
resolver.port,
|
256
|
-
host_name,
|
257
|
-
30,
|
258
|
-
::Socket::PF_INET,
|
259
|
-
options.merge(ssl_verify: false, ssl_verify_hostname: true)
|
260
|
-
)
|
261
|
-
rescue => e
|
262
|
-
error = e
|
263
|
-
end
|
264
241
|
|
265
|
-
|
266
|
-
|
242
|
+
let(:ssl_options) do
|
243
|
+
SpecConfig.instance.ssl_options.merge(ssl_verify: false, ssl_verify_hostname: true)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'raises an error' do
|
247
|
+
lambda do
|
248
|
+
socket
|
249
|
+
end.should raise_error(Mongo::Error::SocketError, /SSL handshake failed due to a hostname mismatch/)
|
267
250
|
end
|
268
251
|
end
|
269
252
|
|
270
253
|
context 'when the hostname is not verified' do
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
options.merge(ssl_verify: false, ssl_verify_hostname: false)
|
280
|
-
)
|
281
|
-
}.not_to raise_error
|
254
|
+
let(:ssl_options) do
|
255
|
+
SpecConfig.instance.ssl_options.merge(ssl_verify: false, ssl_verify_hostname: false)
|
256
|
+
end
|
257
|
+
|
258
|
+
it 'does not raise an error' do
|
259
|
+
lambda do
|
260
|
+
socket
|
261
|
+
end.should_not raise_error
|
282
262
|
end
|
283
263
|
end
|
284
264
|
end
|
@@ -288,7 +268,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
288
268
|
|
289
269
|
context 'when a key is passed, but it is not of the right type' do
|
290
270
|
|
291
|
-
let(:
|
271
|
+
let(:ssl_options) do
|
292
272
|
key = "This is a string not a key"
|
293
273
|
{
|
294
274
|
:ssl => true,
|
@@ -315,7 +295,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
315
295
|
|
316
296
|
context 'when a key is passed, but it is not of the right type' do
|
317
297
|
|
318
|
-
let(:
|
298
|
+
let(:ssl_options) do
|
319
299
|
key = "This is a string not a key"
|
320
300
|
{
|
321
301
|
:ssl => true,
|
@@ -347,35 +327,82 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
347
327
|
end
|
348
328
|
end
|
349
329
|
|
350
|
-
context 'when a bad certificate is provided' do
|
330
|
+
context 'when a bad certificate/key is provided' do
|
351
331
|
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
332
|
+
shared_examples_for 'raises an exception' do
|
333
|
+
it 'raises an exception' do
|
334
|
+
expect do
|
335
|
+
socket
|
336
|
+
end.to raise_exception(*expected_exception)
|
337
|
+
end
|
356
338
|
end
|
357
339
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
340
|
+
context 'mri' do
|
341
|
+
only_mri
|
342
|
+
|
343
|
+
context 'when a bad certificate is provided' do
|
344
|
+
|
345
|
+
let(:expected_exception) do
|
346
|
+
# OpenSSL::X509::CertificateError: nested asn1 error
|
347
|
+
[OpenSSL::OpenSSLError, /asn1 error/i]
|
348
|
+
end
|
349
|
+
|
350
|
+
let(:ssl_options) do
|
351
|
+
super().merge(
|
352
|
+
:ssl_cert => COMMAND_MONITORING_TESTS.first,
|
353
|
+
:ssl_key => nil,
|
354
|
+
)
|
355
|
+
end
|
356
|
+
|
357
|
+
it_behaves_like 'raises an exception'
|
358
|
+
end
|
359
|
+
|
360
|
+
context 'when a bad key is provided' do
|
361
|
+
|
362
|
+
let(:expected_exception) do
|
363
|
+
if RUBY_VERSION >= '2.4.0'
|
364
|
+
# OpenSSL::PKey::PKeyError: Could not parse PKey: no start line
|
365
|
+
[OpenSSL::OpenSSLError, /Could not parse PKey/]
|
366
|
+
else
|
367
|
+
# ArgumentError: Could not parse PKey: no start line
|
368
|
+
[ArgumentError, /Could not parse PKey/]
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
let(:ssl_options) do
|
373
|
+
super().merge(
|
374
|
+
:ssl_cert => nil,
|
375
|
+
:ssl_key => COMMAND_MONITORING_TESTS.first,
|
376
|
+
)
|
371
377
|
end
|
378
|
+
|
379
|
+
it_behaves_like 'raises an exception'
|
372
380
|
end
|
373
381
|
end
|
374
382
|
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
383
|
+
context 'jruby' do
|
384
|
+
require_jruby
|
385
|
+
|
386
|
+
# On JRuby the key does not appear to be parsed, therefore only
|
387
|
+
# specifying the bad certificate produces an error.
|
388
|
+
|
389
|
+
context 'when a bad certificate is provided' do
|
390
|
+
|
391
|
+
let(:ssl_options) do
|
392
|
+
super().merge(
|
393
|
+
:ssl_cert => COMMAND_MONITORING_TESTS.first,
|
394
|
+
:ssl_key => nil,
|
395
|
+
)
|
396
|
+
end
|
397
|
+
|
398
|
+
let(:expected_exception) do
|
399
|
+
# java.lang.ClassCastException: org.bouncycastle.asn1.DERApplicationSpecific cannot be cast to org.bouncycastle.asn1.ASN1Sequence
|
400
|
+
# OpenSSL::X509::CertificateError: parsing issue: malformed PEM data: no header found
|
401
|
+
[OpenSSL::OpenSSLError, /malformed pem data/i]
|
402
|
+
end
|
403
|
+
|
404
|
+
it_behaves_like 'raises an exception'
|
405
|
+
end
|
379
406
|
end
|
380
407
|
end
|
381
408
|
|
@@ -384,7 +411,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
384
411
|
|
385
412
|
context 'as a path to a file' do
|
386
413
|
|
387
|
-
let(:
|
414
|
+
let(:ssl_options) do
|
388
415
|
super().merge(
|
389
416
|
:ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
|
390
417
|
:ssl_verify => true
|
@@ -398,7 +425,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
398
425
|
|
399
426
|
context 'as a string containing the PEM-encoded certificate' do
|
400
427
|
|
401
|
-
let(:
|
428
|
+
let(:ssl_options) do
|
402
429
|
super().merge(
|
403
430
|
:ssl_ca_cert_string => ca_cert_string,
|
404
431
|
:ssl_verify => true
|
@@ -411,7 +438,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
411
438
|
end
|
412
439
|
|
413
440
|
context 'as an array of Certificate objects' do
|
414
|
-
let(:
|
441
|
+
let(:ssl_options) do
|
415
442
|
cert = [OpenSSL::X509::Certificate.new(ca_cert_string)]
|
416
443
|
super().merge(
|
417
444
|
:ssl_ca_cert_object => cert,
|
@@ -426,7 +453,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
426
453
|
|
427
454
|
context 'both as a file and a PEM-encoded parameter' do
|
428
455
|
|
429
|
-
let(:
|
456
|
+
let(:ssl_options) do
|
430
457
|
super().merge(
|
431
458
|
:ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
|
432
459
|
:ssl_ca_cert_string => 'This is a string, not a certificate',
|
@@ -442,7 +469,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
442
469
|
|
443
470
|
context 'both as a file and as object parameter' do
|
444
471
|
|
445
|
-
let(:
|
472
|
+
let(:ssl_options) do
|
446
473
|
super().merge(
|
447
474
|
:ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
|
448
475
|
:ssl_ca_cert_object => 'This is a string, not an array of certificates',
|
@@ -457,7 +484,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
457
484
|
|
458
485
|
context 'both as a PEM-encoded string and as object parameter' do
|
459
486
|
|
460
|
-
let(:
|
487
|
+
let(:ssl_options) do
|
461
488
|
cert = File.read(SpecConfig.instance.local_ca_cert_path)
|
462
489
|
super().merge(
|
463
490
|
:ssl_ca_cert_string => cert,
|
@@ -480,11 +507,11 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
480
507
|
end
|
481
508
|
|
482
509
|
let(:connection) do
|
483
|
-
Mongo::Server::Connection.new(server,
|
510
|
+
Mongo::Server::Connection.new(server, ssl_options.merge(socket_timeout: 2))
|
484
511
|
end
|
485
512
|
|
486
513
|
context 'as a file' do
|
487
|
-
let(:
|
514
|
+
let(:ssl_options) do
|
488
515
|
SpecConfig.instance.test_options.merge(
|
489
516
|
ssl: true,
|
490
517
|
ssl_cert: SpecConfig.instance.client_cert_path,
|
@@ -511,11 +538,11 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
511
538
|
end
|
512
539
|
|
513
540
|
let(:connection) do
|
514
|
-
Mongo::Server::Connection.new(server,
|
541
|
+
Mongo::Server::Connection.new(server, ssl_options.merge(socket_timeout: 2))
|
515
542
|
end
|
516
543
|
|
517
544
|
context 'as a file' do
|
518
|
-
let(:
|
545
|
+
let(:ssl_options) do
|
519
546
|
SpecConfig.instance.test_options.merge(
|
520
547
|
ssl: true,
|
521
548
|
ssl_cert: SpecConfig.instance.client_cert_path,
|
@@ -537,7 +564,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
537
564
|
context 'when a CA certificate is not provided' do
|
538
565
|
require_local_tls
|
539
566
|
|
540
|
-
let(:
|
567
|
+
let(:ssl_options) do
|
541
568
|
super().merge(
|
542
569
|
:ssl_verify => true
|
543
570
|
)
|
@@ -566,12 +593,12 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
566
593
|
end
|
567
594
|
|
568
595
|
let(:connection) do
|
569
|
-
Mongo::Server::Connection.new(server,
|
596
|
+
Mongo::Server::Connection.new(server, ssl_options.merge(socket_timeout: 2))
|
570
597
|
end
|
571
598
|
|
572
599
|
context 'as a path to a file' do
|
573
600
|
context 'standalone' do
|
574
|
-
let(:
|
601
|
+
let(:ssl_options) do
|
575
602
|
SpecConfig.instance.test_options.merge(
|
576
603
|
ssl_cert: SpecConfig.instance.second_level_cert_path,
|
577
604
|
ssl_key: SpecConfig.instance.second_level_key_path,
|
@@ -581,6 +608,13 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
581
608
|
end
|
582
609
|
|
583
610
|
it 'fails' do
|
611
|
+
# This test provides a second level client certificate to the
|
612
|
+
# server *without* providing the intermediate certificate.
|
613
|
+
# If the server performs certificate verification, it will
|
614
|
+
# reject the connection (seen from the driver as a SocketError)
|
615
|
+
# and the test will succeed. If the server does not perform
|
616
|
+
# certificate verification, it will accept the connection,
|
617
|
+
# no SocketError will be raised and the test will fail.
|
584
618
|
connection
|
585
619
|
expect do
|
586
620
|
connection.connect!
|
@@ -593,7 +627,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
593
627
|
# https://github.com/jruby/jruby-openssl/issues/181
|
594
628
|
only_mri
|
595
629
|
|
596
|
-
let(:
|
630
|
+
let(:ssl_options) do
|
597
631
|
SpecConfig.instance.test_options.merge(
|
598
632
|
ssl: true,
|
599
633
|
ssl_cert: SpecConfig.instance.second_level_cert_bundle_path,
|
@@ -614,7 +648,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
614
648
|
|
615
649
|
context 'as a string' do
|
616
650
|
context 'standalone' do
|
617
|
-
let(:
|
651
|
+
let(:ssl_options) do
|
618
652
|
SpecConfig.instance.test_options.merge(
|
619
653
|
ssl_cert: nil,
|
620
654
|
ssl_cert_string: File.read(SpecConfig.instance.second_level_cert_path),
|
@@ -638,7 +672,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
638
672
|
# https://github.com/jruby/jruby-openssl/issues/181
|
639
673
|
only_mri
|
640
674
|
|
641
|
-
let(:
|
675
|
+
let(:ssl_options) do
|
642
676
|
SpecConfig.instance.test_options.merge(
|
643
677
|
ssl: true,
|
644
678
|
ssl_cert: nil,
|
@@ -668,11 +702,11 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
668
702
|
end
|
669
703
|
|
670
704
|
let(:connection) do
|
671
|
-
Mongo::Server::Connection.new(server,
|
705
|
+
Mongo::Server::Connection.new(server, ssl_options.merge(socket_timeout: 2))
|
672
706
|
end
|
673
707
|
|
674
|
-
let(:
|
675
|
-
SpecConfig.instance.
|
708
|
+
let(:ssl_options) do
|
709
|
+
SpecConfig.instance.ssl_options.merge(
|
676
710
|
ssl: true,
|
677
711
|
ssl_cert: SpecConfig.instance.client_pem_path,
|
678
712
|
ssl_key: SpecConfig.instance.client_pem_path,
|
@@ -692,7 +726,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
692
726
|
context 'when ssl_verify is not specified' do
|
693
727
|
require_local_tls
|
694
728
|
|
695
|
-
let(:
|
729
|
+
let(:ssl_options) do
|
696
730
|
super().merge(
|
697
731
|
:ssl_ca_cert => SpecConfig.instance.local_ca_cert_path
|
698
732
|
).tap { |options| options.delete(:ssl_verify) }
|
@@ -706,7 +740,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
706
740
|
context 'when ssl_verify is true' do
|
707
741
|
require_local_tls
|
708
742
|
|
709
|
-
let(:
|
743
|
+
let(:ssl_options) do
|
710
744
|
super().merge(
|
711
745
|
:ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
|
712
746
|
:ssl_verify => true
|
@@ -720,7 +754,7 @@ describe Mongo::Socket::SSL, retry: 3 do
|
|
720
754
|
|
721
755
|
context 'when ssl_verify is false' do
|
722
756
|
|
723
|
-
let(:
|
757
|
+
let(:ssl_options) do
|
724
758
|
super().merge(
|
725
759
|
:ssl_ca_cert => 'invalid',
|
726
760
|
:ssl_verify => false
|