mongo 2.9.0.rc0 → 2.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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