Skip to content

Instantly share code, notes, and snippets.

@leommoore
Last active August 16, 2022 17:35
Show Gist options
  • Star 44 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save leommoore/1e773a7d230ca4bbe1c2 to your computer and use it in GitHub Desktop.
Save leommoore/1e773a7d230ca4bbe1c2 to your computer and use it in GitHub Desktop.
MongoDB 3.2.x SSL with Letsencrypt

MongoDB 3.2.x SSL with Letsencrypt

Letsencrypt is an initative which aims to increase the use of encryption for websites. It basically allows people to apply for free certificates provided that they prove the they control the requested domain. We will look at the what is needed to secure your MongoDB installation. For more details on setting up a MongoDB server see MongoDB 3.2.x.

Set the hostname

We sould to set the hostname to match the name of the certificate we are going to optain.

sudo hostname mongo0.example.com

Then update the hostname file to set the server name permanently.

sudo nano /etc/hostname

Set the hostname in the file to:

mongo0.example.com

Modify the hosts file

Modify the hosts file. If you are using a replica set then, obviously on mongo1 the 127.0.0.1 will point at localhost mongo1.example.com. For more information on setting up a replica set see Setting up a Replica Set on AWS EC2.

sudo nano /etc/hosts

127.0.0.1           localhost mongo0.example.com
52.51.12.62         mongo0.example.com

Setup the DNS entry

The hosts file entry is fine for local name resolution but to obtain a SSL certificate from Letsencrypt it will need to be able to resolve the name externally. So you will need to create a DNS entry (A or AAAA) to point at your server.

Ports

To optain the SSL certificate you will need to ensure that your server is accessable over port 80 and 443 as Letsencrypt will use this to connect to confirm that you control the domain.

Getting the SSL certificate for your server.

Installation

To install the client, clone the repostiory from github.

sudo apt-get -y install git
sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt
cd /opt/letsencrypt

Request the Certificate

This process has got a lot easier over the last while.

./letsencrypt-auto certonly -d mongo0.example.com

You will be asked of you want letsencrypt to look for an entry in your web server.Presumable if this is just a database server then you will not need to install a web server like apache or nginx. In this case select verification option 2 Stand-alone Server. This should locate the file and create the certificates.

If you want to verify on a server with a web server you need to add the following to your default web site server block.

location ~ /.well-known {
        allow all;
}

Remember to restart your web server.

sudo systemctl reload nginx

Preparing the Letsencrypt cert for use with MongoDB

Letsencrypt will create the following certs:

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

The first thing is to combine the privkey and cert into a single file mongodb.pem.

cd /etc/letsencrypt/live/mongo0.example.com
cat privkey.pem cert.pem > /etc/ssl/mongodb.pem

Then you need to download IdenTrust DST Root CA X3 from https://www.identrust.com/certificates/trustid/root-download-x3.html

Save it to a file named ca.crt adding -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines.

Then run:

printf "\n" >> ca.crt
cat /etc/letsencrypt/live/mongo0.example.com/chain.pem >> /etc/ssl/ca.crt

Then convert the crt file to a pem using:

openssl x509 -in /etc/ssl/ca.crt -out /etc/ssl/ca.pem -outform PEM

Just to make sure that everything is setup correctly run:

openssl verify -CAfile /etc/ssl/ca.pem /etc/letsencrypt/live/mongo0.example.com/mongodb.pem

You should get:

mongodb.pem: OK

ca.pem

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow
SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8
SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA
a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T
AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv
bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF
AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/
wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG
PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----

Setup the Certs folder

chmod 600 /etc/ssl/ca.pem
chmod 600 /etc/ssl/mongodb.pem
chown -R mongodb:mongodb /etc/ssl/ca.pem
chown -R mongodb:mongodb /etc/ssl/mongodb.pem

Configure MongoDB

Edit the mongod.conf:

sudo nano /etc/mongod.conf

Specify the SSL locations. You may to specify a PEMKeyPassword if you got the cert from an different source than letsencrypt.

# network interfaces
net:
  port: 27017
  ssl:
     mode: requireSSL
     PEMKeyFile: /etc/ssl/mongodb.pem
     PEMKeyPassword:
     CAFile:     /etc/ssl/ca.pem

Restart MongoDB to make sure it is using the new settings:

sudo service mongod restart

Check that is is running:

tail -20  /var/log/mongodb/mongod.log

Try to connect. This should fail as it is now using a SSL connection is now required.

mongo

MongoDB shell version: 3.2.7
connecting to: test
2016-03-08T11:04:26.853+0000 E QUERY    [thread1] Error: network error while attempting to run command 'isMaster' on host '127.0.0.1:27017'  :
connect@src/mongo/shell/mongo.js:224:14
@(connect):1:6

exception: connect failed

Then log into the shell using ssl:

mongo --ssl -sslCAFile /etc/ssl/ca.pem --host mongo0.example.com --sslPEMKeyFile /etc/ssl/mongodb.pem

From inside the shell you can check that ssl is running:

db.serverStatus().security
{
        "SSLServerSubjectName" : "CN=mongo0.example.com",
        "SSLServerHasCertificateAuthority" : true,
        "SSLServerCertificateExpirationDate" : ISODate("2016-07-06T12:09:00Z")
}
@acrozes
Copy link

acrozes commented Apr 20, 2016

Now, Letsencrypt certificat are X3 and not X1 anymore, so you should update the "CA authority files" in "Preparing the Letsencrypt cert for use with MongoDB"...

@leommoore
Copy link
Author

Thanks acronzes. I checked https://letsencrypt.org/certificates/ and confirmed that they are now releasing X3 cross signed certs which are more compatible with Windows XP. I have updated the gist.

@JoJordens
Copy link

wget https://letsencrypt.org/certs/isrgrootx3.pem
wget https://letsencrypt.org/certs/letsencryptauthorityx3.pem

These don't exist. Should I use something else or are these not live yet/anymore?

@FabianGort
Copy link

FabianGort commented May 4, 2016

First, thanks for sharing the info. I noted also like JoJordens that the X3 certificates are gone. I could still use the X1 certificates though.

I think I followed the procedure well, but I get a different error:

Error: couldn't connect to server 127.0.0.1:27017 (127.0.0.1), connection attempt failed

And then get kicked out from the daemon. I use mongodb 3.0 but I guess that shouldn't matter? And also not the X1 certificates should still be fine?

UPDATE: I used the command line and specified another db file/port and now it just worked find. So I guess there is something with my db file.

@FabianGort
Copy link

FabianGort commented May 4, 2016

After regenerating certificates for different sub domains I keep getting the same error:

NETWORK SSL peer certificate validation failed:unable to verify the first certificate

I tested the original certificates with an https server and they look fine.

@leommoore
Copy link
Author

Thanks Fabian, I'm still using the X1 certs too. Maybe the issue is something in the CA authority chain for the X3 cert.

@ciudilo
Copy link

ciudilo commented May 13, 2016

Fabian you need to download IdenTrust DST Root CA X3. It is mentioned here.

https://www.identrust.com/certificates/trustid/root-download-x3.html

Save it to a file named ca.crt adding -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines.

Then run:
printf "\n" >> ca.crt
cat /etc/letsencrypt/live/mongo0.example.com/chain.pem >> ca.crt

Just to make sure that everything is setup correctly run:
openssl verify -CAfile ca.crt /etc/letsencrypt/live/mongo0.example.com/mongodb.pem

You should get:
cert.pem: OK

@leommoore
Copy link
Author

Thanks ciudilo. I think I need to convert to a pem file too using:

openssl x509 -in ca.crt -out ca.pem -outform PEM

@ijat
Copy link

ijat commented Jun 17, 2016

I got
error 20 at 0 depth lookup:unable to get local issuer certificate
when verify with ca.pem file. Is it normal?

But OK when use with ca.crt.

@vitalybaev
Copy link

@ijat have the same issue. Did you find a solution?
@leommoore Do you know, how to solve this?
Thanks!

@rasmussyberg
Copy link

rasmussyberg commented Aug 31, 2016

@ijat same issue here. Anyone with a solution or an explanation?

Update:
Just solved it. I simply converted the ca.crt file to ca.pem before concat with chain.pem.

@danaketh
Copy link

@rasmussyberg Well, that didn't solved the problem for me sadly.

@unplugged216
Copy link

I am loving this, however, I have one problem.

Catch up: I have followed the steps here, plus added a few to include for the fullchain etc for letsencrypt. The standalone server works great. However, when I attempt to create a replica set, following the same steps on both servers for ssl, I get an odd error: "SSL peer certificate validation failed: unable to get issuer certificate". I get this error on both servers in the log.

Any suggestions? My brain is tired lol. I most likely made a dumb mistake but I cant find any answers to this handshake issue for mongodb.

@literalsands
Copy link

Thanks for the walkthrough!

Here's a fun way to download the IdenTrust DST Root CA X3.
sudo apt install html-xml-utils
curl -s https://www.identrust.com/certificates/trustid/root-download-x3.html | hxnormalize -x | hxselect -c textarea[name=cert] | sed 's/^[ ]*\r/-----BEGIN CERTIFICATE-----/' - | sed 's/^[ ]*$/-----END CERTIFICATE-----\n/' - | sed 's/\r//g' - > ca.crt

Takes care of the final newline, the BEGIN/END wrappings, the Windows line endings, and opening your browser.

@Freundschaft
Copy link

as far as I understand, this works for client authentication, but for member authentication this will not work, because, the distinguished name of letsencrypt doesnt include information about the organization, correct?

@delahee
Copy link

delahee commented Sep 1, 2017

pem conversion before concat to the chain worked for me too otherwise, was not working.

@Altiano
Copy link

Altiano commented Mar 16, 2018

What exactly this line do:
openssl x509 -in /etc/ssl/ca.crt -out /etc/ssl/ca.pem -outform PEM
I just concatenate IdenTrust DST Root CA X3 with chain.pem to ca.pem
And it works.
Am I missing something?

@dkimot
Copy link

dkimot commented Mar 23, 2018

I fixed some formatting errors I noticed, you can pull those from here. Feel free to just copy the raw across. I didn't change any content, just fixed some Markdown formatting errors.

@eddiejibson
Copy link

eddiejibson commented Apr 8, 2018

Getting this, followed all the steps perfectly:
/etc/letsencrypt/live/mydomain/mongodb.pem: CN = mydomain
error 20 at 0 depth lookup:unable to get local issuer certificate
Any idea how to debug this? Could anyone help?

@taralpandya
Copy link

taralpandya commented May 24, 2018

Seems like I am stuck on below:

2018-05-23T21:25:06.320-0400 E NETWORK [thread1] SSL peer certificate validation failed: unable to verify the first certificate
2018-05-23T21:25:06.320-0400 E QUERY [thread1] Error: socket exception [CONNECT_ERROR] for SSL peer certificate validation failed: unable to verify the first certificate :
connect@src/mongo/shell/mongo.js:231:14
@(connect):1:6

Would anyone be able to help?

@datatypevoid
Copy link

as far as I understand, this works for client authentication, but for member authentication this will not work, because, the distinguished name of letsencrypt doesnt include information about the organization, correct?

seems that way.

@slidenerd
Copy link

Dont think this is VALID in 2019, isnt CA certificate optional now on mongodb 4.0? Could you update your POST

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment