Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB connecting over SSL: What am I doing wrong?

Overview: I have an application server running PHP 7, connecting to a separate database server running MongoDB 3.6.x using the MongoDB PHP userland library. I have firewall rules preventing access to the MongoDB server from all sources except the local and private interfaces (i.e. disallowing public IP access).

Connections via PHP look something like this:

$context_information = array(
    "ssl" => array(
        "allow_self_signed" => false,
        "verify_peer"       => true,
        "verify_peer_name"  => true,
        "verify_expiry"     => true,
        "cafile"            => "/path/to/ca_bundle"
));

$context = stream_context_create($context_information);
$connection = new MongoDB\Client(
    $host,
    array('ssl'=>true),
    array('context'=> $context)
);

My MongoDB configuration looks something like this:

net:
  port: 27017
  bindIp: 127.0.0.1,10.138.196.241
  ssl:
    mode: requireSSL
    PEMKeyFile: /path/to/my_ca_signed_cert
    CAFile: /path/to/my_ca_bundle

my_ca_signed_cert is a .pem file generated using my openssl-generated RSA private key, as well as the CA-provided .crt file, in the manner described in the MongoDB manual, e.g. cat mongodb.key mongodb.crt > mongodb.pem. my_ca_bundle is the .ca-bundle provided to me by the CA.

Additionally, the ca_bundle described in the PHP context is the same .ca-bundle file as in the MongoDB config.

Problem: I continue to receive the following error:

[23-Jul-2018 16:33:33 America/Los_Angeles] PHP Fatal error: Uncaught MongoDB\Driver\Exception\ConnectionTimeoutException: No suitable servers found (serverSelectionTryOnce set): [TLS handshake failed: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed calling ismaster on. . .

This issue persists even if I comment out the CAFile line for the MongoDB config. Also of note is that I can connect successfully when setting allow_self_signed to true if CAFile is commented out, but not when it's left uncommented.

Finally, when attempting to connect via the MongoDB shell, I get the following error:

2018-07-23T23:37:02.992+0000 E NETWORK [thread1] SSL peer certificate validation failed: unable to get issuer certificate

2018-07-23T23:37:02.992+0000 E QUERY [thread1] Error: socket exception [CONNECT_ERROR] for SSL peer certificate validation failed: unable to get issuer certificate :

connect@src/mongo/shell/mongo.js:251:13

@(connect):1:6

exception: connect failed

Expected Behavior: I don't want to use client certificate authentication for connecting to the database. All I want at present is for traffic to be encrypted. This means being able to connect to the database without allowing self-signed certificates.

Notes:

  1. I have a cert set up successfully on the application server for HTTPS connectivity. Additionally, when testing the cert referenced in this question itself, I've successfully run verification on the files using openssl verify -CAfile /path/to/my_ca_bundle /path/to/my_ca_signed_cert.

  2. Everything in my application code works when SSL is disabled or when enabled while allowing self-signed certs.

The documentation on all of this is incredibly vague on a number of points, so I'm not sure where my configuration is going wrong. What should I be looking into to resolve this problem?

like image 842
B. Fleming Avatar asked Jul 23 '18 23:07

B. Fleming


2 Answers

I think you can try adding the option allowConnectionsWithoutCertificates to ssl configuration. Your connection is encrypted but ignoring the certificate authentication.

net:
  port: 27017
  bindIp: 127.0.0.1,10.138.196.241
  ssl:
    mode: requireSSL
    PEMKeyFile: /path/to/my_ca_signed_cert
    CAFile: /path/to/my_ca_bundle
    allowConnectionsWithoutCertificates: true

More info here:

https://docs.mongodb.com/manual/reference/configuration-options/#net.ssl.allowConnectionsWithoutCertificates

like image 50
Dat Tran Avatar answered Oct 12 '22 23:10

Dat Tran


I decided to take another crack at this problem and finally found a solution.

First, I needed to move my /path/to/my_ca_bundle to /usr/share/ca-certificates/my_project/my_ca_bundle.

Second, I needed to update /etc/ca-certificates.conf with the line my_project/my_ca_bundle.

Third, I needed to run sudo update-ca-certificates.

Finally, I needed to remove the ssl.cafile option from my PHP stream context (I can't seem to get it to work with this line in place).

The CAFile option in /etc/mongod.conf is unnecessary as well, and is problematic unless it uses the allowConnectionsWithoutCertificates: true line noted in the other answer.

That was a mess, but everything works now!

like image 31
B. Fleming Avatar answered Oct 12 '22 23:10

B. Fleming