Skip to content

Commit a57ae98

Browse files
p-mongop
andauthored
RUBY-2132 fold ssl options into regular options in address/socket code (#1952)
Co-authored-by: Oleg Pudeyev <oleg@bsdpower.com>
1 parent 27818e1 commit a57ae98

File tree

14 files changed

+176
-32
lines changed

14 files changed

+176
-32
lines changed

lib/mongo/address.rb

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def initialize(seed, options = {})
7575
end
7676
@seed = seed
7777
@host, @port = parse_host_port
78-
@options = options
78+
@options = Hash[options.map { |k, v| [k.to_sym, v] }]
7979
end
8080

8181
# @return [ String ] seed The seed address.
@@ -172,28 +172,55 @@ def inspect
172172
# address.socket(5, :ssl => true)
173173
#
174174
# @param [ Float ] socket_timeout The socket timeout.
175-
# @param [ Hash ] ssl_options SSL options.
176-
# @param [ Hash ] options The options.
177-
#
178-
# @option options [ Float ] :connect_timeout Connect timeout.
175+
# @param [ Hash ] opts The options.
176+
#
177+
# @option opts [ Float ] :connect_timeout Connect timeout.
178+
# @option opts [ true | false ] :ssl Whether to use SSL.
179+
# @option opts [ String ] :ssl_ca_cert
180+
# Same as the corresponding Client/Socket::SSL option.
181+
# @option opts [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
182+
# Same as the corresponding Client/Socket::SSL option.
183+
# @option opts [ String ] :ssl_ca_cert_string
184+
# Same as the corresponding Client/Socket::SSL option.
185+
# @option opts [ String ] :ssl_cert
186+
# Same as the corresponding Client/Socket::SSL option.
187+
# @option opts [ OpenSSL::X509::Certificate ] :ssl_cert_object
188+
# Same as the corresponding Client/Socket::SSL option.
189+
# @option opts [ String ] :ssl_cert_string
190+
# Same as the corresponding Client/Socket::SSL option.
191+
# @option opts [ String ] :ssl_key
192+
# Same as the corresponding Client/Socket::SSL option.
193+
# @option opts [ OpenSSL::PKey ] :ssl_key_object
194+
# Same as the corresponding Client/Socket::SSL option.
195+
# @option opts [ String ] :ssl_key_pass_phrase
196+
# Same as the corresponding Client/Socket::SSL option.
197+
# @option opts [ String ] :ssl_key_string
198+
# Same as the corresponding Client/Socket::SSL option.
199+
# @option opts [ true, false ] :ssl_verify
200+
# Same as the corresponding Client/Socket::SSL option.
201+
# @option opts [ true, false ] :ssl_verify_certificate
202+
# Same as the corresponding Client/Socket::SSL option.
203+
# @option opts [ true, false ] :ssl_verify_hostname
204+
# Same as the corresponding Client/Socket::SSL option.
179205
#
180206
# @return [ Mongo::Socket::SSL | Mongo::Socket::TCP | Mongo::Socket::Unix ]
181207
# The socket.
182208
#
183209
# @raise [ Mongo::Error ] If network connection failed.
184210
#
185211
# @since 2.0.0
186-
def socket(socket_timeout, ssl_options = {}, options = {})
212+
# @api private
213+
def socket(socket_timeout, opts = {})
214+
opts = {
215+
connect_timeout: Server::CONNECT_TIMEOUT,
216+
}.update(options).update(Hash[opts.map { |k, v| [k.to_sym, v] }])
217+
187218
map_exceptions do
188219
if seed.downcase =~ Unix::MATCH
189220
specific_address = Unix.new(seed.downcase)
190-
return specific_address.socket(socket_timeout, ssl_options, options)
221+
return specific_address.socket(socket_timeout, opts)
191222
end
192223

193-
options = {
194-
connect_timeout: Server::CONNECT_TIMEOUT,
195-
}.update(Hash[options.map { |k, v| [k.to_sym, v] }])
196-
197224
# When the driver connects to "localhost", it only attempts IPv4
198225
# connections. When the driver connects to other hosts, it will
199226
# attempt both IPv4 and IPv6 connections.
@@ -210,7 +237,7 @@ def socket(socket_timeout, ssl_options = {}, options = {})
210237
results.each do |family, address_str|
211238
begin
212239
specific_address = FAMILY_MAP[family].new(address_str, port, host)
213-
socket = specific_address.socket(socket_timeout, ssl_options, options)
240+
socket = specific_address.socket(socket_timeout, opts)
214241
return socket
215242
rescue IOError, SystemCallError, Error::SocketTimeoutError, Error::SocketError => e
216243
error = e

lib/mongo/address/ipv4.rb

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,44 @@ def initialize(host, port, host_name=nil)
7878
# ipv4.socket(5, :ssl => true)
7979
#
8080
# @param [ Float ] socket_timeout The socket timeout.
81-
# @param [ Hash ] ssl_options SSL options.
8281
# @param [ Hash ] options The options.
8382
#
8483
# @option options [ Float ] :connect_timeout Connect timeout.
84+
# @option options [ true | false ] :ssl Whether to use SSL.
85+
# @option options [ String ] :ssl_ca_cert
86+
# Same as the corresponding Client/Socket::SSL option.
87+
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
88+
# Same as the corresponding Client/Socket::SSL option.
89+
# @option options [ String ] :ssl_ca_cert_string
90+
# Same as the corresponding Client/Socket::SSL option.
91+
# @option options [ String ] :ssl_cert
92+
# Same as the corresponding Client/Socket::SSL option.
93+
# @option options [ OpenSSL::X509::Certificate ] :ssl_cert_object
94+
# Same as the corresponding Client/Socket::SSL option.
95+
# @option options [ String ] :ssl_cert_string
96+
# Same as the corresponding Client/Socket::SSL option.
97+
# @option options [ String ] :ssl_key
98+
# Same as the corresponding Client/Socket::SSL option.
99+
# @option options [ OpenSSL::PKey ] :ssl_key_object
100+
# Same as the corresponding Client/Socket::SSL option.
101+
# @option options [ String ] :ssl_key_pass_phrase
102+
# Same as the corresponding Client/Socket::SSL option.
103+
# @option options [ String ] :ssl_key_string
104+
# Same as the corresponding Client/Socket::SSL option.
105+
# @option options [ true, false ] :ssl_verify
106+
# Same as the corresponding Client/Socket::SSL option.
107+
# @option options [ true, false ] :ssl_verify_certificate
108+
# Same as the corresponding Client/Socket::SSL option.
109+
# @option options [ true, false ] :ssl_verify_hostname
110+
# Same as the corresponding Client/Socket::SSL option.
85111
#
86112
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
87113
#
88114
# @since 2.0.0
89-
def socket(socket_timeout, ssl_options = {}, options = {})
90-
unless ssl_options.empty?
91-
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET, ssl_options.merge(options))
115+
# @api private
116+
def socket(socket_timeout, options = {})
117+
if options[:ssl]
118+
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET, options)
92119
else
93120
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET, options)
94121
end

lib/mongo/address/ipv6.rb

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,44 @@ def initialize(host, port, host_name=nil)
9292
# ipv4.socket(5, :ssl => true)
9393
#
9494
# @param [ Float ] socket_timeout The socket timeout.
95-
# @param [ Hash ] ssl_options SSL options.
9695
# @param [ Hash ] options The options.
9796
#
9897
# @option options [ Float ] :connect_timeout Connect timeout.
98+
# @option options [ true | false ] :ssl Whether to use SSL.
99+
# @option options [ String ] :ssl_ca_cert
100+
# Same as the corresponding Client/Socket::SSL option.
101+
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
102+
# Same as the corresponding Client/Socket::SSL option.
103+
# @option options [ String ] :ssl_ca_cert_string
104+
# Same as the corresponding Client/Socket::SSL option.
105+
# @option options [ String ] :ssl_cert
106+
# Same as the corresponding Client/Socket::SSL option.
107+
# @option options [ OpenSSL::X509::Certificate ] :ssl_cert_object
108+
# Same as the corresponding Client/Socket::SSL option.
109+
# @option options [ String ] :ssl_cert_string
110+
# Same as the corresponding Client/Socket::SSL option.
111+
# @option options [ String ] :ssl_key
112+
# Same as the corresponding Client/Socket::SSL option.
113+
# @option options [ OpenSSL::PKey ] :ssl_key_object
114+
# Same as the corresponding Client/Socket::SSL option.
115+
# @option options [ String ] :ssl_key_pass_phrase
116+
# Same as the corresponding Client/Socket::SSL option.
117+
# @option options [ String ] :ssl_key_string
118+
# Same as the corresponding Client/Socket::SSL option.
119+
# @option options [ true, false ] :ssl_verify
120+
# Same as the corresponding Client/Socket::SSL option.
121+
# @option options [ true, false ] :ssl_verify_certificate
122+
# Same as the corresponding Client/Socket::SSL option.
123+
# @option options [ true, false ] :ssl_verify_hostname
124+
# Same as the corresponding Client/Socket::SSL option.
99125
#
100126
# @return [ Mongo::Socket::SSL, Mongo::Socket::TCP ] The socket.
101127
#
102128
# @since 2.0.0
103-
def socket(socket_timeout, ssl_options = {}, options = {})
104-
unless ssl_options.empty?
105-
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET6, ssl_options.merge(options))
129+
# @api private
130+
def socket(socket_timeout, options = {})
131+
if options[:ssl]
132+
Socket::SSL.new(host, port, host_name, socket_timeout, Socket::PF_INET6, options)
106133
else
107134
Socket::TCP.new(host, port, socket_timeout, Socket::PF_INET6, options)
108135
end

lib/mongo/address/unix.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ def initialize(host, port=nil, host_name=nil)
6363
# address.socket(5)
6464
#
6565
# @param [ Float ] socket_timeout The socket timeout.
66-
# @param [ Hash ] ssl_options SSL options - ignored.
6766
# @param [ Hash ] options The options.
6867
#
6968
# @option options [ Float ] :connect_timeout Connect timeout.
7069
#
7170
# @return [ Mongo::Socket::Unix ] The socket.
7271
#
7372
# @since 2.0.0
74-
def socket(socket_timeout, ssl_options = {}, options = {})
73+
# @api private
74+
def socket(socket_timeout, options = {})
7575
Socket::Unix.new(host, socket_timeout, options)
7676
end
7777
end

lib/mongo/server/connection.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ def connect!
181181
# returned socket.
182182
private def do_connect
183183
socket = add_server_diagnostics do
184-
address.socket(socket_timeout, ssl_options, address.options.merge(
185-
connection_address: address, connection_generation: generation).update(ssl_options))
184+
address.socket(socket_timeout, ssl_options.merge(
185+
connection_address: address, connection_generation: generation))
186186
end
187187

188188
begin

lib/mongo/server/connection_common.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,12 @@ def ssl_options
104104
@ssl_options ||= if options[:ssl]
105105
options.select { |k, v| k.to_s.start_with?('ssl') }
106106
else
107-
{}
107+
# Due to the way options are propagated from the client, if we
108+
# decide that we don't want to use TLS we need to have the ssl
109+
# options explicitly set to false or the value provided to the
110+
# connection might be overwritten by the default inherited from
111+
# the client.
112+
{ssl: false}
108113
end.freeze
109114
end
110115

lib/mongo/server/monitor/connection.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ def connect!
162162
end
163163

164164
@socket = add_server_diagnostics do
165-
address.socket(socket_timeout, ssl_options, address.options.merge(
166-
connection_address: address, monitor: true).update(ssl_options))
165+
address.socket(socket_timeout, ssl_options.merge(
166+
connection_address: address, monitor: true))
167167
end
168168
true
169169
end

lib/mongo/socket/ssl.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,64 @@ class SSL < Socket
3939
# connection (for non-monitoring connections) that created this socket.
4040
# @option options [ true | false ] :monitor Whether this socket was
4141
# created by a monitoring connection.
42+
# @option options [ String ] :ssl_ca_cert The file containing concatenated
43+
# certificate authority certificates used to validate certs passed from the
44+
# other end of the connection. Intermediate certificates should NOT be
45+
# specified in files referenced by this option. One of :ssl_ca_cert,
46+
# :ssl_ca_cert_string or :ssl_ca_cert_object (in order of priority) is
47+
# required when using :ssl_verify.
48+
# @option options [ Array<OpenSSL::X509::Certificate> ] :ssl_ca_cert_object
49+
# An array of OpenSSL::X509::Certificate objects representing the
50+
# certificate authority certificates used to validate certs passed from
51+
# the other end of the connection. Intermediate certificates should NOT
52+
# be specified in files referenced by this option. One of :ssl_ca_cert,
53+
# :ssl_ca_cert_string or :ssl_ca_cert_object (in order of priority)
54+
# is required when using :ssl_verify.
55+
# @option options [ String ] :ssl_ca_cert_string A string containing
56+
# certificate authority certificate used to validate certs passed from the
57+
# other end of the connection. This option allows passing only one CA
58+
# certificate to the driver. Intermediate certificates should NOT
59+
# be specified in files referenced by this option. One of :ssl_ca_cert,
60+
# :ssl_ca_cert_string or :ssl_ca_cert_object (in order of priority) is
61+
# required when using :ssl_verify.
62+
# @option options [ String ] :ssl_cert The certificate file used to identify
63+
# the connection against MongoDB. A certificate chain may be passed by
64+
# specifying the client certificate first followed by any intermediate
65+
# certificates up to the CA certificate. The file may also contain the
66+
# certificate's private key, which will be ignored. This option, if present,
67+
# takes precedence over the values of :ssl_cert_string and :ssl_cert_object
68+
# @option options [ OpenSSL::X509::Certificate ] :ssl_cert_object The OpenSSL::X509::Certificate
69+
# used to identify the connection against MongoDB. Only one certificate
70+
# may be passed through this option.
71+
# @option options [ String ] :ssl_cert_string A string containing the PEM-encoded
72+
# certificate used to identify the connection against MongoDB. A certificate
73+
# chain may be passed by specifying the client certificate first followed
74+
# by any intermediate certificates up to the CA certificate. The string
75+
# may also contain the certificate's private key, which will be ignored,
76+
# This option, if present, takes precedence over the value of :ssl_cert_object
77+
# @option options [ String ] :ssl_key The private keyfile used to identify the
78+
# connection against MongoDB. Note that even if the key is stored in the same
79+
# file as the certificate, both need to be explicitly specified. This option,
80+
# if present, takes precedence over the values of :ssl_key_string and :ssl_key_object
81+
# @option options [ OpenSSL::PKey ] :ssl_key_object The private key used to identify the
82+
# connection against MongoDB
83+
# @option options [ String ] :ssl_key_pass_phrase A passphrase for the private key.
84+
# @option options [ String ] :ssl_key_string A string containing the PEM-encoded private key
85+
# used to identify the connection against MongoDB. This parameter, if present,
86+
# takes precedence over the value of option :ssl_key_object
87+
# @option options [ true, false ] :ssl_verify Whether to perform peer certificate validation and
88+
# hostname verification. Note that the decision of whether to validate certificates will be
89+
# overridden if :ssl_verify_certificate is set, and the decision of whether to validate
90+
# hostnames will be overridden if :ssl_verify_hostname is set.
91+
# @option options [ true, false ] :ssl_verify_certificate Whether to perform peer certificate
92+
# validation. This setting overrides :ssl_verify with respect to whether certificate
93+
# validation is performed.
94+
# @option options [ true, false ] :ssl_verify_hostname Whether to perform peer hostname
95+
# validation. This setting overrides :ssl_verify with respect to whether hostname validation
96+
# is performed.
4297
#
4398
# @since 2.0.0
99+
# @api private
44100
def initialize(host, port, host_name, timeout, family, options = {})
45101
super(timeout, options)
46102
@host, @port, @host_name = host, port, host_name

lib/mongo/socket/tcp.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class TCP < Socket
4141
# created by a monitoring connection.
4242
#
4343
# @since 2.0.0
44+
# @api private
4445
def initialize(host, port, timeout, family, options = {})
4546
super(timeout, options)
4647
@host, @port = host, port

lib/mongo/socket/unix.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class Unix < Socket
3838
# created by a monitoring connection.
3939
#
4040
# @since 2.0.0
41+
# @api private
4142
def initialize(path, timeout, options = {})
4243
super(timeout, options)
4344
@path = path

0 commit comments

Comments
 (0)