Networking Security: Self-Managed / TLS for Self-Managed Deployments
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 three member replica set in 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 host name.
Keep this in mind because it'll be important once we start signing certificates.
In order to set up TLS, we 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 certificates signed by a reputable certificate authority, such as Let's Encrypt, DigiCert, GlobalSign, or Satigo.
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 or 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 a CA issued certificate.
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 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 certificates, we'll be using OpenSSL.
First, we'll generate the private key for the 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 /tmp 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 host name, 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 the 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, and you'll also specify your organization.
Let's say MDBU (MongoDB University).
We can also specify an organizational unit name, but we'll leave it blank for now. 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 mongod0.key.
Next, we'll 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 the certificate authority asking for an 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 New York 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 it's just a demonstration.
If you decide to add a password, you'll need to provide it in the MongoD configuration so the MongoD can provide the correct credentials.
I'll point out where to place the password when we update the configuration file.
Now, we'll specify our node certificate signing request or CSR to a certificate authority.
The CA checks to make sure that the request is authentic.
If everything looks good, the CA signs the request with its private key.
This creates the node certificate, which includes the CA signature, the public key we provided in the request, and the verified identity details.
We'll call this signed certificate mongod0.crt. Once we have our node signed certificate, we'll combine it with the node's private key into a PEM file. We'll include this file in our MongoD configuration as we enable TLS. We'll need to repeat this process for each node in the replica set. Each 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 mongod.pem file and our CA certificate to the temp folder on the node server using the secure copy protocol command or SCP.
On the node 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 the 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 servers are not connecting 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 choose 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 the "requireTLS" option. This will require all connections to present a trusted certificate and ensure that 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 certificate?
We decided not to, but if we did choose to set a password, we would need to specify it using the certificate key file password 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 the documentation on configuring TLS.
We'll need to repeat this process on 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 that 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 already 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, so 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 the 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.
