mongo 2.9.0.rc0 → 2.9.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +1 -3
  5. data/lib/mongo/client.rb +33 -16
  6. data/lib/mongo/collection/view/aggregation.rb +3 -2
  7. data/lib/mongo/collection/view/map_reduce.rb +3 -2
  8. data/lib/mongo/server/connectable.rb +8 -4
  9. data/lib/mongo/server/connection.rb +0 -1
  10. data/lib/mongo/server/monitor/connection.rb +0 -1
  11. data/lib/mongo/socket/ssl.rb +67 -10
  12. data/lib/mongo/version.rb +1 -1
  13. data/spec/README.md +39 -3
  14. data/spec/integration/auth_spec.rb +2 -2
  15. data/spec/integration/ssl_uri_options_spec.rb +7 -6
  16. data/spec/lite_spec_helper.rb +0 -16
  17. data/spec/mongo/client_construction_spec.rb +13 -13
  18. data/spec/mongo/collection/view/map_reduce_spec.rb +8 -0
  19. data/spec/mongo/server_spec.rb +2 -1
  20. data/spec/mongo/socket/ssl_spec.rb +213 -20
  21. data/spec/mongo/socket/tcp_spec.rb +1 -1
  22. data/spec/support/certificates/README.md +101 -0
  23. data/spec/support/certificates/ca.crt +76 -0
  24. data/spec/support/certificates/{client_key_encrypted.pem → client-encrypted.key} +0 -0
  25. data/spec/support/certificates/client-int.crt +78 -0
  26. data/spec/support/certificates/client-second-level-bundle.pem +179 -0
  27. data/spec/support/certificates/client-second-level.crt +74 -0
  28. data/spec/support/certificates/client-second-level.key +27 -0
  29. data/spec/support/certificates/client-second-level.pem +101 -0
  30. data/spec/support/certificates/client.crt +74 -0
  31. data/spec/support/certificates/{client_key.pem → client.key} +1 -1
  32. data/spec/support/certificates/client.pem +1 -1
  33. data/spec/support/certificates/multi-ca.crt +152 -0
  34. data/spec/support/certificates/python-ca.crt +76 -0
  35. data/spec/support/certificates/server-int.crt +78 -0
  36. data/spec/support/certificates/server-second-level-bundle.pem +179 -0
  37. data/spec/support/certificates/server-second-level.crt +74 -0
  38. data/spec/support/certificates/server-second-level.key +27 -0
  39. data/spec/support/certificates/server-second-level.pem +101 -0
  40. data/spec/support/certificates/server.pem +74 -22
  41. data/spec/support/constraints.rb +3 -7
  42. data/spec/support/spec_config.rb +84 -16
  43. metadata +36 -10
  44. metadata.gz.sig +0 -0
  45. data/spec/support/certificates/ca.pem +0 -22
  46. data/spec/support/certificates/client_cert.pem +0 -22
@@ -646,6 +646,14 @@ describe Mongo::Collection::View::MapReduce do
646
646
  end
647
647
 
648
648
  context 'when the server is a valid for writing' do
649
+ before do
650
+ # We are inspecting server state - kill monitor threads so that
651
+ # server state is not changed in background due to intermittent
652
+ # connectivity issues in Evergreen
653
+ authorized_collection.client.cluster.servers_list.map do |server|
654
+ server.monitor.stop!
655
+ end
656
+ end
649
657
 
650
658
  it 'does not reroute the operation to a primary' do
651
659
  expect(Mongo::Logger.logger).not_to receive(:warn?)
@@ -364,7 +364,8 @@ describe Mongo::Server do
364
364
 
365
365
  context 'server is unknown' do
366
366
  let(:server) do
367
- described_class.new(address, cluster, monitoring, listeners, SpecConfig.instance.test_options)
367
+ described_class.new(address, cluster, monitoring, listeners,
368
+ SpecConfig.instance.test_options.merge(monitoring_io: false))
368
369
  end
369
370
 
370
371
  before do
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongo::Socket::SSL do
4
- require_ssl
4
+ require_tls
5
5
 
6
6
  let(:address) do
7
7
  default_address.tap do
@@ -26,19 +26,19 @@ describe Mongo::Socket::SSL do
26
26
  end
27
27
 
28
28
  let (:key_string) do
29
- File.read(SpecConfig.instance.client_key_pem)
29
+ File.read(SpecConfig.instance.local_client_key_path)
30
30
  end
31
31
 
32
32
  let (:cert_string) do
33
- File.read(SpecConfig.instance.client_cert_pem)
33
+ File.read(SpecConfig.instance.local_client_cert_path)
34
34
  end
35
35
 
36
36
  let (:ca_cert_string) do
37
- File.read(CA_PEM)
37
+ File.read(SpecConfig.instance.local_ca_cert_path)
38
38
  end
39
39
 
40
40
  let(:key_encrypted_string) do
41
- File.read(CLIENT_KEY_ENCRYPTED_PEM)
41
+ File.read(SpecConfig.instance.client_encrypted_key_path)
42
42
  end
43
43
 
44
44
  let(:cert_object) do
@@ -102,7 +102,7 @@ describe Mongo::Socket::SSL do
102
102
  :ssl => true,
103
103
  :ssl_cert_string => cert_string,
104
104
  :ssl_key_string => key_encrypted_string,
105
- :ssl_key_pass_phrase => CLIENT_KEY_PASSPHRASE,
105
+ :ssl_key_pass_phrase => SpecConfig.instance.client_encrypted_key_passphrase,
106
106
  :ssl_verify => false
107
107
  }
108
108
  end
@@ -163,7 +163,7 @@ describe Mongo::Socket::SSL do
163
163
  :ssl => true,
164
164
  :ssl_cert_string => cert_string,
165
165
  :ssl_cert_object => 'This is a string, not a Certificate',
166
- :ssl_key => CLIENT_KEY_PEM,
166
+ :ssl_key => SpecConfig.instance.client_key_path,
167
167
  :ssl_verify => false
168
168
  }
169
169
  end
@@ -207,7 +207,7 @@ describe Mongo::Socket::SSL do
207
207
  let(:options) do
208
208
  {
209
209
  :ssl => true,
210
- :ssl_cert => CLIENT_CERT_PEM,
210
+ :ssl_cert => SpecConfig.instance.client_cert_path,
211
211
  :ssl_key_string => key_string,
212
212
  :ssl_key_object => 'This is a string, not a PKey',
213
213
  :ssl_verify => false
@@ -227,7 +227,7 @@ describe Mongo::Socket::SSL do
227
227
  {
228
228
  :ssl => true,
229
229
  :ssl_cert_object => cert,
230
- :ssl_key => CLIENT_KEY_PEM,
230
+ :ssl_key => SpecConfig.instance.local_client_key_path,
231
231
  :ssl_verify => false
232
232
  }
233
233
  end
@@ -254,7 +254,7 @@ describe Mongo::Socket::SSL do
254
254
  host_name,
255
255
  30,
256
256
  ::Socket::PF_INET,
257
- options.merge(ssl_verify_hostname: true)
257
+ options.merge(ssl_verify: false, ssl_verify_hostname: true)
258
258
  )
259
259
  rescue => e
260
260
  error = e
@@ -274,7 +274,7 @@ describe Mongo::Socket::SSL do
274
274
  host_name,
275
275
  30,
276
276
  ::Socket::PF_INET,
277
- options.merge(ssl_verify_hostname: false)
277
+ options.merge(ssl_verify: false, ssl_verify_hostname: false)
278
278
  )
279
279
  }.not_to raise_error
280
280
  end
@@ -291,7 +291,7 @@ describe Mongo::Socket::SSL do
291
291
  {
292
292
  :ssl => true,
293
293
  :ssl_key_object => key,
294
- :ssl_cert => CLIENT_CERT_PEM,
294
+ :ssl_cert => SpecConfig.instance.client_cert_path,
295
295
  :ssl_verify => false
296
296
  }
297
297
  end
@@ -318,7 +318,7 @@ describe Mongo::Socket::SSL do
318
318
  {
319
319
  :ssl => true,
320
320
  :ssl_key_object => key,
321
- :ssl_cert => CLIENT_CERT_PEM,
321
+ :ssl_cert => SpecConfig.instance.client_cert_path,
322
322
  :ssl_verify => false
323
323
  }
324
324
  end
@@ -384,7 +384,7 @@ describe Mongo::Socket::SSL do
384
384
 
385
385
  let(:options) do
386
386
  super().merge(
387
- :ssl_ca_cert => CA_PEM,
387
+ :ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
388
388
  :ssl_verify => true
389
389
  )
390
390
  end
@@ -426,7 +426,7 @@ describe Mongo::Socket::SSL do
426
426
 
427
427
  let(:options) do
428
428
  super().merge(
429
- :ssl_ca_cert => CA_PEM,
429
+ :ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
430
430
  :ssl_ca_cert_string => 'This is a string, not a certificate',
431
431
  :ssl_verify => true
432
432
  )
@@ -442,7 +442,7 @@ describe Mongo::Socket::SSL do
442
442
 
443
443
  let(:options) do
444
444
  super().merge(
445
- :ssl_ca_cert => CA_PEM,
445
+ :ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
446
446
  :ssl_ca_cert_object => 'This is a string, not an array of certificates',
447
447
  :ssl_verify => true
448
448
  )
@@ -456,7 +456,7 @@ describe Mongo::Socket::SSL do
456
456
  context 'both as a PEM-encoded string and as object parameter' do
457
457
 
458
458
  let(:options) do
459
- cert = File.read(CA_PEM)
459
+ cert = File.read(SpecConfig.instance.local_ca_cert_path)
460
460
  super().merge(
461
461
  :ssl_ca_cert_string => cert,
462
462
  :ssl_ca_cert_object => 'This is a string, not an array of certificates',
@@ -470,6 +470,68 @@ describe Mongo::Socket::SSL do
470
470
  end
471
471
  end
472
472
 
473
+ context 'when CA certificate file is not what server cert is signed with' do
474
+ require_local_tls
475
+
476
+ let(:server) do
477
+ ClientRegistry.instance.global_client('authorized').cluster.next_primary
478
+ end
479
+
480
+ let(:connection) do
481
+ Mongo::Server::Connection.new(server, options)
482
+ end
483
+
484
+ context 'as a file' do
485
+ let(:options) do
486
+ SpecConfig.instance.test_options.merge(
487
+ ssl: true,
488
+ ssl_cert: SpecConfig.instance.client_cert_path,
489
+ ssl_key: SpecConfig.instance.client_key_path,
490
+ ssl_ca_cert: SpecConfig.instance.ssl_certs_dir.join('python-ca.crt').to_s,
491
+ ssl_verify: true,
492
+ )
493
+ end
494
+
495
+ it 'fails' do
496
+ connection
497
+ expect do
498
+ connection.connect!
499
+ end.to raise_error(Mongo::Error::SocketError, /SSLError/)
500
+ end
501
+ end
502
+ end
503
+
504
+ context 'when CA certificate file contains multiple certificates' do
505
+ require_local_tls
506
+
507
+ let(:server) do
508
+ ClientRegistry.instance.global_client('authorized').cluster.next_primary
509
+ end
510
+
511
+ let(:connection) do
512
+ Mongo::Server::Connection.new(server, options)
513
+ end
514
+
515
+ context 'as a file' do
516
+ let(:options) do
517
+ SpecConfig.instance.test_options.merge(
518
+ ssl: true,
519
+ ssl_cert: SpecConfig.instance.client_cert_path,
520
+ ssl_key: SpecConfig.instance.client_key_path,
521
+ ssl_ca_cert: SpecConfig.instance.multi_ca_path,
522
+ ssl_verify: true,
523
+ )
524
+ end
525
+
526
+ it 'succeeds' do
527
+ connection
528
+ expect do
529
+ connection.connect!
530
+ end.not_to raise_error
531
+ end
532
+ end
533
+ end
534
+
473
535
  context 'when a CA certificate is not provided' do
474
536
  require_local_tls
475
537
 
@@ -481,7 +543,7 @@ describe Mongo::Socket::SSL do
481
543
 
482
544
  around do |example|
483
545
  saved = ENV['SSL_CERT_FILE']
484
- ENV['SSL_CERT_FILE'] = CA_PEM
546
+ ENV['SSL_CERT_FILE'] = SpecConfig.instance.local_ca_cert_path
485
547
  begin
486
548
  example.run
487
549
  ensure
@@ -494,12 +556,143 @@ describe Mongo::Socket::SSL do
494
556
  end
495
557
  end
496
558
 
559
+ context 'when the client certificate uses an intermediate certificate' do
560
+ require_local_tls
561
+
562
+ let(:server) do
563
+ ClientRegistry.instance.global_client('authorized').cluster.next_primary
564
+ end
565
+
566
+ let(:connection) do
567
+ Mongo::Server::Connection.new(server, options)
568
+ end
569
+
570
+ context 'as a path to a file' do
571
+ context 'standalone' do
572
+ let(:options) do
573
+ SpecConfig.instance.test_options.merge(
574
+ ssl_cert: SpecConfig.instance.second_level_cert_path,
575
+ ssl_key: SpecConfig.instance.second_level_key_path,
576
+ ssl_ca_cert: SpecConfig.instance.local_ca_cert_path,
577
+ ssl_verify: true,
578
+ )
579
+ end
580
+
581
+ it 'fails' do
582
+ connection
583
+ expect do
584
+ connection.connect!
585
+ end.to raise_error(Mongo::Error::SocketError)
586
+ end
587
+ end
588
+
589
+ context 'bundled with intermediate cert' do
590
+
591
+ # https://github.com/jruby/jruby-openssl/issues/181
592
+ fails_on_jruby
593
+
594
+ let(:options) do
595
+ SpecConfig.instance.test_options.merge(
596
+ ssl: true,
597
+ ssl_cert: SpecConfig.instance.second_level_cert_bundle_path,
598
+ ssl_key: SpecConfig.instance.second_level_key_path,
599
+ ssl_ca_cert: SpecConfig.instance.local_ca_cert_path,
600
+ ssl_verify: true,
601
+ )
602
+ end
603
+
604
+ it 'succeeds' do
605
+ connection
606
+ expect do
607
+ connection.connect!
608
+ end.not_to raise_error
609
+ end
610
+ end
611
+ end
612
+
613
+ context 'as a string' do
614
+ context 'standalone' do
615
+ let(:options) do
616
+ SpecConfig.instance.test_options.merge(
617
+ ssl_cert: nil,
618
+ ssl_cert_string: File.read(SpecConfig.instance.second_level_cert_path),
619
+ ssl_key: nil,
620
+ ssl_key_string: File.read(SpecConfig.instance.second_level_key_path),
621
+ ssl_ca_cert: SpecConfig.instance.local_ca_cert_path,
622
+ ssl_verify: true,
623
+ )
624
+ end
625
+
626
+ it 'fails' do
627
+ connection
628
+ expect do
629
+ connection.connect!
630
+ end.to raise_error(Mongo::Error::SocketError)
631
+ end
632
+ end
633
+
634
+ context 'bundled with intermediate cert' do
635
+
636
+ # https://github.com/jruby/jruby-openssl/issues/181
637
+ fails_on_jruby
638
+
639
+ let(:options) do
640
+ SpecConfig.instance.test_options.merge(
641
+ ssl: true,
642
+ ssl_cert: nil,
643
+ ssl_cert_string: File.read(SpecConfig.instance.second_level_cert_bundle_path),
644
+ ssl_key: nil,
645
+ ssl_key_string: File.read(SpecConfig.instance.second_level_key_path),
646
+ ssl_ca_cert: SpecConfig.instance.local_ca_cert_path,
647
+ ssl_verify: true,
648
+ )
649
+ end
650
+
651
+ it 'succeeds' do
652
+ connection
653
+ expect do
654
+ connection.connect!
655
+ end.not_to raise_error
656
+ end
657
+ end
658
+ end
659
+ end
660
+
661
+ context 'when client certificate and private key are bunded in a pem file' do
662
+ require_local_tls
663
+
664
+ let(:server) do
665
+ ClientRegistry.instance.global_client('authorized').cluster.next_primary
666
+ end
667
+
668
+ let(:connection) do
669
+ Mongo::Server::Connection.new(server, options)
670
+ end
671
+
672
+ let(:options) do
673
+ SpecConfig.instance.test_options.merge(
674
+ ssl: true,
675
+ ssl_cert: SpecConfig.instance.client_pem_path,
676
+ ssl_key: SpecConfig.instance.client_pem_path,
677
+ ssl_ca_cert: SpecConfig.instance.local_ca_cert_path,
678
+ ssl_verify: true,
679
+ )
680
+ end
681
+
682
+ it 'succeeds' do
683
+ connection
684
+ expect do
685
+ connection.connect!
686
+ end.not_to raise_error
687
+ end
688
+ end
689
+
497
690
  context 'when ssl_verify is not specified' do
498
691
  require_local_tls
499
692
 
500
693
  let(:options) do
501
694
  super().merge(
502
- :ssl_ca_cert => CA_PEM
695
+ :ssl_ca_cert => SpecConfig.instance.local_ca_cert_path
503
696
  ).tap { |options| options.delete(:ssl_verify) }
504
697
  end
505
698
 
@@ -513,7 +706,7 @@ describe Mongo::Socket::SSL do
513
706
 
514
707
  let(:options) do
515
708
  super().merge(
516
- :ssl_ca_cert => CA_PEM,
709
+ :ssl_ca_cert => SpecConfig.instance.local_ca_cert_path,
517
710
  :ssl_verify => true
518
711
  )
519
712
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mongo::Socket::TCP do
4
- require_no_ssl
4
+ require_no_tls
5
5
 
6
6
  let(:address) { default_address }
7
7
 
@@ -0,0 +1,101 @@
1
+ # Ruby Driver Test TLS Certificates
2
+
3
+ ## File Types
4
+
5
+ All files in this directory are in the PEM format. They are generated by
6
+ the x509gen MongoDB tool.
7
+
8
+ The file extensions map to content as follows:
9
+
10
+ - `.key` - private key
11
+ - `.crt` - certificate
12
+ - `.pem` - certificate and private key combined in the same file
13
+
14
+ The file name fragments have the following meaning:
15
+
16
+ - `second-level` - these certificates are signed by the intermediate
17
+ certificates (`client-int.crt` & `server-int.crt`) rather than directly
18
+ by the CA certificates.
19
+ - `int` - these are intermediate certificates used for testing certificate
20
+ chains. The server and the client sides have their own intermediate certificates.
21
+ - `bundle` - these files contain the leaf certificates followed by intermediate
22
+ certificates up to the CA certificates, but do not include the CA certificates.
23
+
24
+ Keep in mind the following important notes:
25
+
26
+ - In multi-ca.crt, the Ruby driver CA certificate must be last (the first
27
+ certificate must be an unrelated certificate).
28
+
29
+ ## Tools
30
+
31
+ To inspect a certificate:
32
+
33
+ openssl x509 -text -in path.pem
34
+
35
+ ## Manual Testing - openssl
36
+
37
+ Start a test server using the simple certificate:
38
+
39
+ openssl s_server -port 29999 -CAfile ca.crt -cert server.pem -verify 1
40
+
41
+ Use OpenSSL's test client to test certificate verification using the
42
+ simple certificate:
43
+
44
+ openssl s_client -connect :29999 -CAfile ca.crt -cert client.pem \
45
+ -verify 1 -verify_return_error
46
+
47
+ Same thing but using the second level certificate with the intermediate
48
+ certificate (server follows chain up to the CA):
49
+
50
+ openssl s_client -connect :29999 -CAfile ca.crt \
51
+ -cert client-second-level-bundle.pem \
52
+ -verify 1 -verify_return_error
53
+
54
+ Note however, that even though a client to server connection succeeds using
55
+ the second level client bundle, openssl appears to be incapable to simply
56
+ verify the same certificate chain using the verify command:
57
+
58
+ # This fails
59
+ openssl verify -verbose -CAfile ca.crt -untrusted client-int.crt \
60
+ client-second-level.pem
61
+
62
+ # Also fails
63
+ openssl verify -trusted client-int.crt client-second-level.crt
64
+
65
+ And when the server's certificate uses an intermediate certificate, the
66
+ client seems to be unable to verify it also:
67
+
68
+ openssl s_server -port 29999 -CAfile ca.crt -verify 1 \
69
+ -cert server-second-level-bundle.pem
70
+
71
+ # This fails
72
+ openssl s_client -connect :29999 -CAfile ca.crt -cert client.pem \
73
+ -verify 1 -verify_return_error
74
+
75
+ To sum up, openssl's command line tools appear to only handle certificate
76
+ chains provided by the client when the server is verifying them, not the
77
+ other way around and not when trying to standalone verify the chain.
78
+
79
+ ## Manual Testing - mongo
80
+
81
+ When it comes to `mongod` and `mongo`, certificate chains are supported in
82
+ both directions:
83
+
84
+ mongod --sslMode requireSSL \
85
+ --sslCAFile ca.crt \
86
+ --sslPEMKeyFile server-second-level-bundle.pem \
87
+ --sslClientCertificate client.pem
88
+
89
+ mongo --host localhost --ssl \
90
+ --sslCAFile ca.crt \
91
+ --sslPEMKeyFile client-second-level-bundle.pem
92
+
93
+ The `--host` option needs to be given to `mongo` because the certificates here
94
+ do not include 127.0.0.1 in subject alternate name.
95
+
96
+ If the intermediate certificate is not provided, the connection should fail.
97
+
98
+ # Expected to fail
99
+ mongo --host localhost --ssl \
100
+ --sslCAFile ca.crt \
101
+ --sslPEMKeyFile client-second-level.pem