Networking Security: Self-Managed / TLS for Self-Managed Deployments

Video Transcript (English)

Welcome back! Now that we know how TLS works, let’s take a look at how we can configure our MongoDB deployment to use it. Let’s get started!

For this I've provisioned a 3-member replica set with each node running on its own Linux server.
Each node has a similar configuration. The one difference is that each node is bound to a unique identifying hostname. Keep this in mind because it'll be important once we begin signing certificates.

In order to set up TLS, we’ll need to generate certificates for the nodes. We’ll also need them to be signed by a Certificate authority or we can self-sign them.

For production environments it’s recommended that you have your certificates signed by a reputable Certificate Authority, such as Let's Encrypt, DigiCert, GlobalSign, or sec-ti-go.
If you do choose to use self-signed certificates, it’s important to ensure that your network is secure.

Self-signed certificates are created and authenticated by you rather than a trusted third-party Certificate Authority (CA). They're appropriate for development environments, testing, and internal networks where you control all connecting clients. However, they're not suitable for public-facing production systems as they generate security warnings and don't provide the same level of trust as CA-issued certificates.

Since this is a demonstration, we’ll be self-signing the root Certificate Authority certificate which in turn will be used to sign each node’s certificate.

In production, you'd use a reputable Certificate Authority instead - the process is similar, but trusted CAs provide automatic client validation and handle certificate management tasks you'd otherwise need to implement yourself.

To generate and sign our certificates we’ll be using OpenSSL.

First we’ll generate the private key for our Certificate Authority. We’ll name it ca.key and place it in the temp folder for now.

The primary function of the CA's private key is to sign digital certificates, which involves creating a cryptographic signature.

This signature verifies the authenticity of the certificates it signs. It’s important to keep this key private and secure.

Next, we use the CA's private key to create a self-signed CA certificate called ca.crt and place it in the temp folder. This sets up a local CA capable of signing certificates for replica set members.

This CA will then verify the identity of each node in the replica set by issuing certificates. These certificates bind the node's public key to its identity, such as its hostname, ensuring secure communication within the set.

After we run the command, we’ll be prompted to fill out some identifying information. The details we'll provide form part of the CA's identity, making it uniquely identifiable.

After setting up the CA, we'll use these credentials to sign certificates for each of the MongoDB replica set members. This step is crucial because it authenticates each node, enabling secure, encrypted TLS communication. It ensures that every node in the replica set is trustworthy and can securely transmit data.

Now let’s provide this information.

First, you'll enter your Country code, like "US" for the United States.

Next is the State, we’ll go with "New York."

Then, the City, such as "New York City."

You'll also specify your Organization, let's say "MDBU."

We can also specify an organizational unit name, but we’ll leave it blank.

For the Common Name, you’ll input something like "CA." This is used to identify the CA. You can choose a name that suits your needs.

Finally, we can include an Email Address, such as "example@example.com."

Now that we have our Certificate Authority in place, let's move on to generating certificates for each of our hosts.

First, we’ll start by generating the private key for our first node. We’ll label it mongod-zero dot key.

Next we create a certificate signing request or CSR for short using the node’s private key we just generated.

This is a formal request sent to a Certificate Authority asking for the issuance of a digital certificate.

This will prompt us to fill out identifying information for this node.

Starting with the node's location information. For this example, we'll specify NewYork City, New York.

Now, we need to enter the organization's details. It's required to provide at least one of the following: Organization, Organizational Unit, or Domain Component. These fields play a key role in verifying the certificate's authenticity.

After that, we need to specify a Common Name. It’s important that this field matches the node’s host name that we specified in the mongod configuration file, as we’ve done here for the first node

Next, we specify an email.

Finally, we’ll be asked if we would like to add a challenge password or optional company name. We’re going to leave these blank since this is just a demonstration.

If you decide to add a password, you’ll need to provide it in the mongod configuration file so the mongod can provide the correct credentials. I’ll point out where to place the password when we update our configuration file.

Now, we’ll submit our node's certificate signing request (CSR) to a Certificate Authority (CA). The CA checks to make sure the request is authentic. If everything looks good, the CA signs the request with its private key. This creates the node's certificate, which includes the CA’s signature, the public key we provided in the request, and verified identity details. We’ll call this signed certificate "mongod0.crt."

Once we have our node’s signed certificate, we’ll combine it with the node’s private key in a .pem file. We’ll include this file in our mongod configuration file as we enable TLS.
We’ll need to repeat this process for each node in our replica set. Every node in your replica set must obtain its own unique signed certificate from a Certificate Authority in order to securely participate in the replica set's TLS-enabled communication.

Once we've generated all the certificates, we need to send each certificate to the correct node. Here we’re sending the mongod0 pem file and our CA certificate to the tmp folder on the node’s server using the secure copy protocol command or scp.

On the node’s server we’ll create a new directory that will hold our keys.

Then, we’ll copy the mongod pem file and the CA certificate to the new directory.

Afterwards, we’ll give MongoDB ownership of the directory and update the privileges accordingly.

Once all our certificates are in place, it's time to update our mongod configuration files.
Inside our mongod configuration file, we specify the tls option under the net field.

Next, we need to specify the mode.

For this we have three options:

allowTLS means the servers are not connected using TLS but incoming connections can use TLS.

preferTLS means connections between servers use TLS. For incoming connections, the server accepts both TLS and non-TLS.

requireTLS means all connections require TLS. Any clients that want to connect also require a certificate signed by a trusted CA.

So how do you determine which one to use?

When choosing a mode, there are key considerations to keep in mind.

For an existing replica set with active client connections, start with the preferTLS option. This allows you to transition smoothly by supporting both encrypted and unencrypted connections while updating nodes and clients to use TLS.

Going directly to requireTLS can disrupt communication between nodes or clients, so proceed with caution. Always test changes in a controlled environment before deploying to production.

Since this is a new replica set with no clients connecting yet,, we’ll go with requireTLS. This will require all connections to present a trusted certificate and ensure anything that connects is using network encryption.

Next, we specify the location of the certificate key file which is the pem file we created. Remember, this includes the node's signed certificate and private key.

And finally, we specify our CA certificate.

Remember when we had the option to set a challenge password for our certificates? We decided not to but if you did choose to set a password we would need to specify it using the certificateKeyFilePassword option. We didn’t set a password so we can forego this option.

These are just some of the options available, for a full list of options check out our documentation on configuring TLS.

We’ll need to repeat this process for each node. Once complete, we can perform a rolling update of each node. Keep in mind that you should test and stage any new configurations before releasing them in your production environment.

Once the rolling updates are complete, let’s verify that TLS is being used.

Let’s try connecting to our replica set using the MongoDB Shell.

After some time, it appears that our connection has timed out.

This is because we configured TLS to use the requireTLS mode. If you recall, this mode makes it so all connections need to present signed certificates by a trusted Certificate Authority. Since our shell client doesn't have a signed certificate, we can't connect.

So to connect via the shell client, we’ll need to go through the same process of generating public and private keys and get them signed. We won’t show those steps again since we've done this before.

Now when we connect using a client we need to provide the TLS flag, the location of the certificate authority certificate, and the pem file for the client.

Once we run the command, we can see that we've successfully connected with TLS enabled.
With that complete, we now have peace of mind knowing that our communication between our servers and clients is encrypted. That said, it’s still important that we stay vigilant to any security problems.

Great job! We covered a lot in this lesson, let's take a moment to recap the work we’ve done.
First we created and signed our Certificate Authority in order to establish a trusted entity that can authenticate and verify the identities of servers and clients within our MongoDB deployment

Then, we created and signed certificates for each node in our replica set.

Once we placed our certificates in the correct location, we set up TLS in the mongod configuration file for each node in the replica set

Finally, we verified that TLS was successfully enabled.