Configure MongoDB (and a client) for SSL/TLS

Configure MongoDB (and a client) for SSL/TLS

MongoDB supports encrypted data transport (communication between your application and the database engine) but requires some configuration on both the client and the server in order to set things up correctly.

Below, I'll be discussing generating your own SSL certificate and configuring the server to load this certificate on startup, as well as how to configure your application to connect to the server.

This information can be applied to a MongoDB instance on any OS, and the C# client (version 2.4.3 at time of writing) running on Windows, or any OS with C# Core running Mono.

NOTE: We're creating a self-signed certificate here for development purposes, but ultimately you would want to use a valid CA signed certificate (especially in production environments). Otherwise, validating your servers certificate on the client side either needs to be bypassed (as in the example below), or you would need to export and install your local CA certificate onto each client machine as a trusted/intermediate third-party CA... not ideal.

So, the following steps are going to be required:

  • Create a self-signed certificate with OpenSSL for development;
  • Configure the mongod server;
  • Configure the client;

Create a self-signed certificate with OpenSSL

NOTE: As previously noted, Self-Signing certificates is not recommended for production environments. This step is only for development environments.
As pointed out by Johan Eyrich, if you use self-signed certificates, you would need to bypass the verification step allowing for a possible man-in-the-middle attack on the CA. So, and I know this is bleedingly obvious, but, don't do this in production.

Make sure you have OpenSSL installed. If you're on Windows, you can find links to download the latest version of the OpenSSL binaries here: https://wiki.openssl.org/index.php/Binaries.

For other platforms, you can build it yourself: https://www.openssl.org/source/ (build and installation instructions can be found here: https://wiki.openssl.org/index.php/Compilation_and_Installation)

Enter the following commands into your favourite terminal / command prompt...

openssl genrsa -des3 -out server.key 2048  
openssl rsa -in server.key -out server.key  
openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=db-server-name'  
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt  

When prompted, enter a password for the certificate. (You will need this in the next step).

Mongo needs a .pem file. This is essentially a container format (text file) that contains the certificate and the private key in the same file. You can generate this in bash with the following command...

cat server.crt server.key > cert.pem  

** If you're running Windows and don't have bash installed, you can simply create an empty text file in your favourite editor (vscode, Sublime Text, Notepad++ etc.), paste in the contents of server.crt then the contents of server.key and save the new file as cert.pem.

Now, just copy the cert.pem file to your mongo server's bin directory.

Update the MongoDB Config file with SSL details

Open your MongoDB configuration file (you'll have normally set this up during mongo installation) and add the net section if it doesn't already exist.

Reminder: this is a YAML file, so indent with spaces (not tabs)!

net:  
   bindIp: localhost
   ssl:
      mode: requireSSL
      PEMKeyFile: /[path-to-mongo]/cert.pem
      PEMKeyPassword: <certificate password created in previous step>
      allowInvalidCertificates: true
      allowInvalidHostnames: true

Start mongod

Once you've configured mongo to load the certificate, you can re-start mongod.

If you've somehow broken the config file, any issues encountered will be written to the log file (as specified in the config prior to the broken section) or, output to the console if you run it manually via the command line.

You can quickly check client connectivity by running the mongo (client) executable. (Make sure you ONLY specify the parameters which instruct it to ignore the self-signed certificate in a DEV/DEMO environment.)

In production:

mongo --ssl  

If you need to test your DEV environment with a self-signed certificate, use:

# DEV ENVIRONMENT ONLY
mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates  

Any errors should be output to the console (and the mongod log file as specified).

Configure your client connection

Configuring the client connection to handle SSL with a self-signed certificate is fairly straightforward, you just need to instantiate an SSL settings instance.
In our demo, we also need to bypass validation on the self-signed development certificate...

C#:

public void getClientSettings()
{
    var url = new MongoUrl("mongodb://myUsername:myPassword@server1");
    var clientSettings = MongoClientSettings.FromUrl(url)
    {  
        UseSsl = true,
        SslSettings = new SslSettings()
        {
            CheckCertificateRevocation = true // *1
        },
        VerifySslCertificate = true // *1
    };
    return clientSettings;
}

/**
 * NOTE: *1 - if you are using self-signed certificates for testing
 * you will need to set the CA verification and revocation checks to false,
 * otherwise your certificates will appear to be invalid in any testing
 * you are performing. Never do this in production of course.
 */

php:


<?php
$client = new MongoDB\Client("mongodb://myUsername:myPassword@server1/?ssl=true");

// Alternatively, the authentication credentials and URI parameters
// may be specified in the constructor's $uriOptions parameter...
$client = new MongoDB\Client('mongodb://server1', [
        'username' => 'myUsername',
        'password' => 'myPassword',
        'ssl' => true,
        'authSource' => 'admin'
    ]);
?>