MongoDB® SSL with Self-Signed Certificates in C#

5 min read
MongoDB® SSL with Self-Signed Certificates in C#

SHARE THIS ARTICLE

When deploying MongoDB in production, using an SSL-enabled geo-distributed replica-set configuration is strongly recommended for maximum security and availability. ScaleGrid provides you with two options for setting up SSL.

One option is purchasing your CA-signed SSL certificates and configuring them on the MongoDB server. If your application connects to the production database over a public network, contact support@scalegrid.io to learn more about this.

But by default, we configure self-signed certificates for SSL when creating nodes for a new cluster. This avoids extra costs and can be equally secure when correctly configured. But this means that your MongoDB driver needs help validating the certificate chain.

When handling self-signed certificates, some developers circumvent validation altogether and seriously compromise security! In this blog post, we show you two methods to securely connect to a MongoDB server configured with self-signed certificates for SSL using the official C# MongoDB driver. You can provide your driver with the information to validate the server certificate and keep the connection secure with a few simple steps.

Prerequisites

Before you proceed,

  • Make sure your application can connect to your ScaleGrid deployment. Please refer to our MongoDB Connections help doc to review the general steps for connecting your application to a ScaleGrid deployment.
  • You need to have the MongoDB Driver installed. Please refer to the MongoDB Driver docs to review the steps for installing and using the C# MongoDB.Driver.

Note: All the code samples have been tested using MongoDB Driver v2.8.1 and .NET Framework v4.6.1. However, they should work on any reasonably recent version of .NET Framework and MongoDB Driver.

Remember to…


Modify the file paths and connection URLs in the code samples to your own file paths and URLs. Else the code samples will not work. Please see the bold parts of the code samples for where you need to make changes.For example:

  • <path-to-downloaded-CA-Cert.cer> = C:\Users\User\Folder\caCert.cer
  • <host1> = mongodb://admin: @SG-example.servers.example.com:27017

Method 1: Adding the ScaleGrid Certificate to Windows Trust Store

One of the simplest ways of using self-signed certificates with C# and the .NET Framework is adding the certificate as “Trusted Root” on the Windows Trust Store. Here’s how you can do it:

  1. Download your CA Certificate from the ScaleGrid UI.
  2. Open a PowerShell Prompt – if you wish to add the certificate as trusted-root for all users, you will have to open it in administrative mode.
  3. Execute the following command, or do this using the Microsoft Management Console.:
    • To add only for the current user:
    Import-Certificate -FilePath <path-to-downloaded-CA-Cert.cer> -CertStoreLocation 'Cert:\CurrentUser\Root'
    • To add for everyone:
    Import-Certificate -FilePath <path-to-downloaded-CA-Cert.cer> -CertStoreLocation Cert:\LocalMachine\Root'

That’s it! Now the self-signed certificate will pass all default validations, and you are ready to create a MongoDB client.

var connURL = "mongodb://admin:<password>@<host1>,<host2>:27017/admin?replicaSet=<ReplicaSetName>&ssl=true";
var client = new MongoClient(connURL);

Method 2: Using Custom Validation Callback

There are two problems with adding the ScaleGrid Certificate to the Windows Trust Store:

  • The settings apply to all programs running on the machine: this can be a security vulnerability.
  • This has to be done once per-machine. If you move your code to a new server, it can suddenly stop working. This leaves the method prone to human error.

Hence, the recommended way to connect using self-signed certificates is to use a custom validation callback that verifies the certificate. Here’s how you can do this:

  1. Download your CA Certificate and save it to a location your application can access (this will typically be its data directory).
  2. From your application, you can read this certificate and match the one you receive from the MongoDB Server.
  3. Alternatively, you can store a cryptographic hash of the certificate. Instead of reading the certificate and matching, you can compute the cryptographic hash over the received certificate and match the results.

Here’s a sample program that has the CA Certificate stored under its bin directory with the name caCert.cer. It simply prints out a list of all databases that exist on the MongoDB Server:

<pre>using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace TestMongoDB
{
  class Program
  {
    static void Main(string[] args)
    {
      var connURL = "mongodb:<b>&lt;password&gt;</b>//admin:@<b>&lt;host1&gt;</b>,<b>&lt;host2&gt;</b>:27017/admin?replicaSet=<b>&lt;Replica-Set-Name&gt;</b>&amp;ssl=true";
      var clientSettings = MongoClientSettings.FromUrl(new MongoUrl(connURL));
      clientSettings.UseSsl = true;
      clientSettings.VerifySslCertificate = true;
      clientSettings.SslSettings = new SslSettings();
      clientSettings.SslSettings.ServerCertificateValidationCallback = ValidateServerCertficate;
      var client = new MongoClient(clientSettings);
      using (IAsyncCursor cursor = client.ListDatabases())
      {
        while (cursor.MoveNext())
        {
          foreach (var doc in cursor.Current)
          {
            Console.WriteLine(doc["name"]); // database name
          }
        }
      }
    }

    private static bool ValidateServerCertficate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
      bool certMatch = false; // Assume failure
      switch(sslPolicyErrors)
      {
        case SslPolicyErrors.None:
          Console.WriteLine("No validation errors - accepting certificate");
          certMatch = true;
          break;
        case SslPolicyErrors.RemoteCertificateChainErrors:
          Console.WriteLine("Failed to validate certificate chain. Most likely a self-signed certificate");
          if (chain.ChainElements.Count == 1 &amp;&amp; chain.ChainStatus[0].Status == X509ChainStatusFlags.UntrustedRoot) //It is a self-signed certificate, so chain length will be 1.
          {
            X509Certificate savedCert = X509Certificate.CreateFromCertFile("caCert.cer");
            if (savedCert.Equals(cert)) //This verifies that the issuer and serial number matches. You can also use a cryptographic hash, or match the two certificates byte by byte.
            {
              Console.WriteLine("The certificates match");
              certMatch = true;
            }
          }
          break;
        default:
          Console.WriteLine("Name mismatch or remote-cert not available. Rejecting connection");
          break;
      }
      return certMatch;
    }
  }
}</pre>

Troubleshooting

If you’re having trouble connecting to your SSL-enabled MongoDB deployment, here are a few tips for debugging:

  • First, verify that you can actually connect to the MongoDB server from the server where your application is running. The simplest way to do this is to install mongo shell on the client machine. On Linux, you wouldn’t need to install the entire MongoDB server – you can choose to install just the shell. Once the shell is available, try to use the ‘Command Line Syntax’ we provide to attempt to connect to the server.
  • If you are unable to connect via the mongo shell, it means that the client machine is unable to reach the port 27017 of the MongoDB servers. Look at your Security Group, VPC, and/or ScaleGrid firewall settings to ensure connectivity between the client and server machines.
  • If network connectivity is correct, the next thing to check is that you are using versions of MongoDB Driver and .NET Framework that are compatible with the version of your MongoDB server.
  • If you have confirmed that the driver versions are correct, try running a sample C# program in debug mode, similar to the above example. A step-by-step execution would help to identify root cause of the problem.
  • If you are still having trouble connecting to your instance, please contact us at support@scalegrid.io with detailed results of the above troubleshooting steps and the exact versions of C# and the Mongo Driver you are using.

Read Also:
Setting Up MongoDB SSL Encryption
MongoDB® SSL with Self-Signed Certificates in Node.js
MongoDB Rollback: How to Minimize Data Loss

If you are new to ScaleGrid and want to try this tutorial, sign up for a free 30-day trial to explore the platform and test out connecting MongoDB to your C# application.

For more information, please visit www.scalegrid.io. Connect with ScaleGrid on LinkedIn, X, Facebook, and YouTube.
Table of Contents

Stay Ahead with ScaleGrid Insights

Dive into the world of database management with our monthly newsletter. Get expert tips, in-depth articles, and the latest news, directly to your inbox.

Related Posts

Redis vs Memcached in 2024

Choosing between Redis and Memcached hinges on specific application requirements. In this comparison of Redis vs Memcached, we strip away...

multi cloud plan - scalegrid

Plan Your Multi Cloud Strategy

Thinking about going multi-cloud? A well-planned multi cloud strategy can seriously upgrade your business’s tech game, making you more agile....

hybrid cloud strategy - scalegrid

Mastering Hybrid Cloud Strategy

Mastering Hybrid Cloud Strategy Are you looking to leverage the best private and public cloud worlds to propel your business...

NEWS

Add Headline Here