MongoDB - Configure a ReplicaSet to support TLS/SSL
How to configure a ReplicaSet to support TLS/SSL?
We will deploy a 3 Nodes ReplicaSet in your local environment and we will use a self-signed certificate. Do not use a self-signed certificate in PRODUCTION.
How to connect your Client to this ReplicaSet?
We will connect a Mongo Shell.
A description of TLS/SSL, PKI (Public Key Infrastructure) certificates, and Certificate Authority is beyond the scope of this documentation.
How to configure a ReplicaSet to support TLS/SSL?
Section titled “How to configure a ReplicaSet to support TLS/SSL?”Create the Root Certificate
Section titled “Create the Root Certificate”The Root Certificate (aka CA File) will be used to sign and identify your certificate. To generate it, run the command below.
openssl req -nodes -out ca.pem -new -x509 -keyout ca.keyKeep the root certificate and its key carefully, both will be used to sign your certificates. The root certificate might be used by your client as well.
Generate the Certificate Requests and the Private Keys
Section titled “Generate the Certificate Requests and the Private Keys”When generating the Certificate Signing Request (aka CSR), input the exact hostname (or IP) of your node in the Common Name (aka CN) field. The others fields must have exactly the same value. You might need to modify your /etc/hosts file.
The commands below will generate the CSR files and the RSA Private Keys (4096 bits).
openssl req -nodes -newkey rsa:4096 -sha256 -keyout mongodb_node_1.key -out mongodb_node_1.csropenssl req -nodes -newkey rsa:4096 -sha256 -keyout mongodb_node_2.key -out mongodb_node_2.csropenssl req -nodes -newkey rsa:4096 -sha256 -keyout mongodb_node_3.key -out mongodb_node_3.csrYou must generate one CSR for each node of your ReplicaSet. Remember that the Common Name is not the same from one node to another. Don’t base multiple CSRs on the same Private Key.
You must now have 3 CSRs and 3 Private Keys.
mongodb_node_1.key - mongodb_node_2.key - mongodb_node_3.keymongodb_node_1.csr - mongodb_node_2.csr - mongodb_node_3.csrSign your Certificate Requests
Section titled “Sign your Certificate Requests”Use the CA File (ca.pem) and its Private Key (ca.key) generated previously to sign each Certificate Request by running the commands below.
openssl x509 -req -in mongodb_node_1.csr -CA ca.pem -CAkey ca.key -set_serial 00 -out mongodb_node_1.crtopenssl x509 -req -in mongodb_node_2.csr -CA ca.pem -CAkey ca.key -set_serial 00 -out mongodb_node_2.crtopenssl x509 -req -in mongodb_node_3.csr -CA ca.pem -CAkey ca.key -set_serial 00 -out mongodb_node_3.crtYou must sign each CSR.
Your must now have 3 CSRs, 3 Private Keys and 3 self-signed Certificates. Only the Private Keys and the Certificates will be used by MongoDB.
mongodb_node_1.key - mongodb_node_2.key - mongodb_node_3.keymongodb_node_1.csr - mongodb_node_2.csr - mongodb_node_3.csrmongodb_node_1.crt - mongodb_node_2.crt - mongodb_node_3.crtEach certificate corresponds to one node. Remember carefully which CN / hostname your gave to each CSR.
Concat each Node Certificate with its key
Section titled “Concat each Node Certificate with its key”Run the commands below to concat each Node Certificate with its key in one file (MongoDB requirement).
cat mongodb_node_1.key mongodb_node_1.crt > mongodb_node_1.pemcat mongodb_node_2.key mongodb_node_2.crt > mongodb_node_2.pemcat mongodb_node_3.key mongodb_node_3.crt > mongodb_node_3.pemYour must now have 3 PEM files.
mongodb_node_1.pem - mongodb_node_2.pem - mongodb_node_3.pemDeploy your ReplicaSet
Section titled “Deploy your ReplicaSet”We will assume that your pem files are located in your current folder as well as data/data1, data/data2 and data/data3.
Run the commands below to deploy your 3 Nodes ReplicaSet listening on port 27017, 27018 and 27019.
mongod --dbpath data/data_1 --replSet rs0 --port 27017 --sslMode requireSSL --sslPEMKeyFile mongodb_node_1.pemmongod --dbpath data/data_2 --replSet rs0 --port 27018 --sslMode requireSSL --sslPEMKeyFile mongodb_node_2.pemmongod --dbpath data/data_3 --replSet rs0 --port 27019 --sslMode requireSSL --sslPEMKeyFile mongodb_node_3.pemYou now have a 3 Nodes ReplicaSet deployed on your local environment and all their transactions are encrypted. You cannot connect to this ReplicaSet without using TLS.
Deploy your ReplicaSet for Mutual SSL / Mutual Trust
Section titled “Deploy your ReplicaSet for Mutual SSL / Mutual Trust”To force your client to provide a Client Certificate (Mutual SSL), you must add the CA File when running your instances.
mongod --dbpath data/data_1 --replSet rs0 --port 27017 --sslMode requireSSL --sslPEMKeyFile mongodb_node_1.pem --sslCAFile ca.pemmongod --dbpath data/data_2 --replSet rs0 --port 27018 --sslMode requireSSL --sslPEMKeyFile mongodb_node_2.pem --sslCAFile ca.pemmongod --dbpath data/data_3 --replSet rs0 --port 27019 --sslMode requireSSL --sslPEMKeyFile mongodb_node_3.pem --sslCAFile ca.pemYou now have a 3 Nodes ReplicaSet deployed on your local environment and all their transactions are encrypted. You cannot connect to this ReplicaSet without using TLS or without providing a Client Certificate trusted by your CA.
How to connect your Client (Mongo Shell) to a ReplicaSet?
Section titled “How to connect your Client (Mongo Shell) to a ReplicaSet?”No Mutual SSL
Section titled “No Mutual SSL”In this example, we might use the CA File (ca.pem) that you generated during the “How to configure a ReplicaSet to support TLS/SSL?” section. We will assume that the CA file is located in your current folder.
We will assume that your 3 nodes are running on mongo1:27017, mongo2:27018 and mongo3:27019. (You might need to modify your /etc/hosts file.)
From MongoDB 3.2.6, if your CA File is registered in your Operating System Trust Store, you can connect to your ReplicaSet without providing the CA File.
mongo --ssl --host rs0/mongo1:27017,mongo2:27018,mongo3:27019Otherwise you must provide the CA File.
mongo --ssl --sslCAFile ca.pem --host rs0/mongo1:27017,mongo2:27018,mongo3:27019You are now connected to your ReplicaSet and all the transactions between your Mongo Shell and your ReplicaSet are encrypted.
With Mutual SSL
Section titled “With Mutual SSL”If your ReplicaSet asks for a Client Certificate, you must provide one signed by the CA used by the ReplicaSet Deployment. The steps to generate the Client Certificate are almost the same as the ones to generate the Server Certificate.
Indeed, you just need to modify the Common Name Field during the CSR creation. Instead of providing 1 Node Hostname in the Common Name Field, you need to provide all the ReplicaSet Hostnames separated by a comma.
openssl req -nodes -newkey rsa:4096 -sha256 -keyout mongodb_client.key -out mongodb_client.csr...Common Name (e.g. server FQDN or YOUR name) []: mongo1,mongo2,mongo3You might face the Common Name size limitation if the Common Name field is too long (more than 64 bytes long). To bypass this limitation, you must use the SubjectAltName when generating the CSR.
openssl req -nodes -newkey rsa:4096 -sha256 -keyout mongodb_client.key -out mongodb_client.csr -config <(cat <<-EOF[req]default_bits = 4096prompt = nodefault_md = sha256req_extensions = req_extdistinguished_name = dn
[ dn ]CN = .
[ req_ext ]subjectAltName = @alt_names
[ alt_names ]DNS.1 = mongo1DNS.2 = mongo2DNS.3 = mongo3EOF)Then you sign the CSR using the CA certificate and key.
openssl x509 -req -in mongodb_client.csr -CA ca.pem -CAkey ca.key -set_serial 00 -out mongodb_client.crtFinally, you concat the key and the signed certificate.
cat mongodb_client.key mongodb_client.crt > mongodb_client.pemTo connect to your ReplicaSet, you can now provide the newly generated Client Certificate.
mongo --ssl --sslCAFile ca.pem --host rs0/mongo1:27017,mongo2:27018,mongo3:27019 --sslPEMKeyFile mongodb_client.pemYou are now connected to your ReplicaSet and all the transactions between your Mongo Shell and your ReplicaSet are encrypted.