-
Notifications
You must be signed in to change notification settings - Fork 183
Description
I am trying use rust mongodb driver (v3.2.4) to connect to a mongodb replicaset with self-signed certificate.
At the very beginning, then connection string was like
mongodb://user:pass@IP1:27017,IP2:27017,IP3:27017/?replicaSet=myreplica&authSource=admin&ssl=true&tlsInsecure=true
and then I got error complaining about the invalid certificate.
Error: Kind: Server selection timeout: No available servers. Topology: { Type: ReplicaSetNoPrimary, Set Name: myreplica, Servers: [ { Address: IP1:27017, Type: Unknown, Error: Kind: I/O error: invalid peer certificate: UnknownIssuer, labels: {} }, { Address: IP2:27017, Type: Unknown, Error: Kind: I/O error: invalid peer certificate: UnknownIssuer, labels: {} }, { Address: IP3:27017, Type: Unknown, Error: Kind: I/O error: invalid peer certificate: UnknownIssuer, labels: {} } ] }, labels: {}
and the debug output of client options are like:
ClientOptions { hosts: [Tcp { host: "IP1", port: Some(27017) }, Tcp { host: "IP2", port: Some(27017) }, Tcp { host: "IP3", port: Some(27017) }], app_name: None, connect_timeout: None, credential: Some(Credential("REDACTED")), direct_connection: None, driver_info: None, heartbeat_freq: None, load_balanced: None, local_threshold: None, max_idle_time: None, max_pool_size: None, min_pool_size: None, max_connecting: None, read_concern: None, repl_set_name: Some("myreplica"), retry_reads: None, retry_writes: None, server_monitoring_mode: None, selection_criteria: None, server_api: None, server_selection_timeout: None, default_database: None, srv_service_name: None, tls: Some(Enabled(TlsOptions { allow_invalid_certificates: Some(false), ca_file_path: None, cert_key_file_path: None })), write_concern: None, srv_max_hosts: None, .. }
I notice the allow_invalid_certificates
is Some(false)
, so I manually set the TLS with code, and it works.
options.tls = Some(Tls::Enabled(
TlsOptions::builder()
.allow_invalid_certificates(true)
.build(),
));
I thought it was caused by lacking query parameter tlsAllowInvalidCertificates
(official docs), then I updated the connection string to:
mongodb://user:pass@IP1:27017,IP2:27017,IP3:27017/?replicaSet=myreplica&authSource=admin&ssl=true&tlsInsecure=true&tlsAllowInvalidCertificates=true
But this time, I got different error:
Error: Kind: An invalid argument was provided: all instances of 'tlsInsecure' and 'tlsAllowInvalidCertificates' must be consistent (e.g. 'tlsInsecure' cannot be true when 'tlsAllowInvalidCertificates' is false, or vice-versa), labels: {}
By check the source code, I found the code is raising this error on inconsistent way with the error description, by line let allow_invalid_certificates = if k == "tlsinsecure" { !val } else { val };
:
// src/client/options.rs, start on line 2067 at tag v3.2.4
...
...
k @ "tlsinsecure" | k @ "tlsallowinvalidcertificates" => {
let val = get_bool!(value, k);
let allow_invalid_certificates = if k == "tlsinsecure" { !val } else { val };
match self.tls {
Some(Tls::Disabled) => {
return Err(ErrorKind::InvalidArgument {
message: "'tlsInsecure' can't be set if tls=false".into(),
}
.into())
}
Some(Tls::Enabled(ref options))
if options.allow_invalid_certificates.is_some()
&& options.allow_invalid_certificates
!= Some(allow_invalid_certificates) =>
{
return Err(ErrorKind::InvalidArgument {
message: "all instances of 'tlsInsecure' and \
'tlsAllowInvalidCertificates' must be consistent (e.g. \
'tlsInsecure' cannot be true when \
'tlsAllowInvalidCertificates' is false, or vice-versa)"
.into(),
}
.into());
}
...
...
}
...
...
According to the source code, when parsing the URL and if it receives tlsinsecure
, it sets tlsallowinvalidcertificates
to the opposite value. But the error message says these two value should be consistent.
I am not sure what is the expected behavior, but now the error message is not match the code behavior.
My humble opinion it that, tlsincesure
should set tlsallowinvalidcertificates
to same value like what the error message says.