mongo 2.11.1 → 2.11.6
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 +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
|