Skip to content

Commit 23ca714

Browse files
p-mongop
authored andcommitted
Fix RUBY-1830 TLS client cert specification via URI options does not work on JRuby (#1383)
1 parent c771ba1 commit 23ca714

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed

.evergreen/.evg.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,7 @@ buildvariants:
854854
-
855855
matrix_name: "local-tls"
856856
matrix_spec:
857-
# No JRuby due to https://jira.mongodb.org/browse/RUBY-1830
858-
ruby: ["ruby-2.6", "ruby-1.9"]
857+
ruby: "*"
859858
mongodb-version: '4.0'
860859
topology: standalone
861860
display_name: "Local TLS ${ruby}"

.evergreen/run-local-tls-tests.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,23 @@ mlaunch --dir "$dbdir" --binarypath "$BINDIR" --single \
3939
--sslCAFile spec/support/certificates/ca.crt \
4040
--sslClientCertificate spec/support/certificates/client.pem
4141

42+
if echo $RVM_RUBY |grep -q jruby; then
43+
# JRuby does not grok chained certificate bundles -
44+
# https://github.com/jruby/jruby-openssl/issues/181
45+
client_pem=client.pem
46+
else
47+
client_pem=client-second-level-bundle.pem
48+
fi
49+
4250
echo "Running specs"
4351
export MONGODB_URI="mongodb://localhost:27017/?tls=true&serverSelectionTimeoutMS=30000&"\
4452
"tlsCAFile=spec/support/certificates/ca.crt&"\
45-
"tlsCertificateKeyFile=spec/support/certificates/client-second-level-bundle.pem"
53+
"tlsCertificateKeyFile=spec/support/certificates/$client_pem"
4654
bundle exec rake spec:prepare
4755

4856
export MONGODB_URI="mongodb://localhost:27017/?tls=true&"\
4957
"tlsCAFile=spec/support/certificates/ca.crt&"\
50-
"tlsCertificateKeyFile=spec/support/certificates/client-second-level-bundle.pem"
58+
"tlsCertificateKeyFile=spec/support/certificates/$client_pem"
5159
bundle exec rspec spec/mongo/socket*
5260
test_status=$?
5361
echo "TEST STATUS"

lib/mongo/socket/ssl.rb

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,16 +199,35 @@ def set_cert(context, options)
199199
def set_key(context, options)
200200
passphrase = options[:ssl_key_pass_phrase]
201201
if options[:ssl_key]
202-
context.key = passphrase ? OpenSSL::PKey.read(File.read(options[:ssl_key]), passphrase) :
203-
OpenSSL::PKey.read(File.open(options[:ssl_key]))
202+
context.key = load_private_key(File.read(options[:ssl_key]), passphrase)
204203
elsif options[:ssl_key_string]
205-
context.key = passphrase ? OpenSSL::PKey.read(options[:ssl_key_string], passphrase) :
206-
OpenSSL::PKey.read(options[:ssl_key_string])
204+
context.key = load_private_key(options[:ssl_key_string], passphrase)
207205
elsif options[:ssl_key_object]
208206
context.key = options[:ssl_key_object]
209207
end
210208
end
211209

210+
def load_private_key(text, passphrase)
211+
args = if passphrase
212+
[text, passphrase]
213+
else
214+
[text]
215+
end
216+
# On JRuby, PKey.read does not grok cert+key bundles.
217+
# https://github.com/jruby/jruby-openssl/issues/176
218+
if BSON::Environment.jruby?
219+
[OpenSSL::PKey::RSA, OpenSSL::PKey::DSA].each do |cls|
220+
begin
221+
return cls.send(:new, *args)
222+
rescue OpenSSL::PKey::PKeyError
223+
# ignore
224+
end
225+
end
226+
# Neither RSA nor DSA worked, fall through to trying PKey
227+
end
228+
OpenSSL::PKey.send(:read, *args)
229+
end
230+
212231
def set_cert_verification(context, options)
213232
context.verify_mode = OpenSSL::SSL::VERIFY_PEER
214233
cert_store = OpenSSL::X509::Store.new

spec/mongo/socket/ssl_spec.rb

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,6 @@
559559
context 'when the client certificate uses an intermediate certificate' do
560560
require_local_tls
561561

562-
# https://github.com/jruby/jruby-openssl/issues/181
563-
fails_on_jruby
564-
565562
let(:server) do
566563
ClientRegistry.instance.global_client('authorized').cluster.next_primary
567564
end
@@ -590,6 +587,10 @@
590587
end
591588

592589
context 'bundled with intermediate cert' do
590+
591+
# https://github.com/jruby/jruby-openssl/issues/181
592+
fails_on_jruby
593+
593594
let(:options) do
594595
SpecConfig.instance.test_options.merge(
595596
ssl: true,
@@ -631,6 +632,10 @@
631632
end
632633

633634
context 'bundled with intermediate cert' do
635+
636+
# https://github.com/jruby/jruby-openssl/issues/181
637+
fails_on_jruby
638+
634639
let(:options) do
635640
SpecConfig.instance.test_options.merge(
636641
ssl: true,
@@ -653,6 +658,35 @@
653658
end
654659
end
655660

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+
656690
context 'when ssl_verify is not specified' do
657691
require_local_tls
658692

0 commit comments

Comments
 (0)