#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. ``` git clone https://github.com/letsencrypt/letsencrypt.git cd letsencrypt ``` ###Request the Certificate ``` ./letsencrypt-auto certonly -a manual --rsa-key-size 4096 -d mongo0.example.com ``` ###Verify Domain Ownership The request will generate a similar response like: ``` Make sure your web server displays the following content at http://mongo0.example.com/.well-known/acme-challenge/A-xjoIljw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU before continuing: A-xjoI1jw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU.eefJYv1muREVb9TpEb3qjr9AQsM8IurTn-Svykj0wN0 If you don't have HTTP server configured, you can run the following command on the target server (as root): mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge cd /tmp/letsencrypt/public_html printf "%s" A-xjoI1jw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU.eefJYv1muREVb9TpEb3qjr9AQsM8IurTn-Svykj0wN0 > .well-known/acme-challenge/A-xjoI1jw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU # run only once per server: $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ "import BaseHTTPServer, SimpleHTTPServer; \ s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ s.serve_forever()" Press ENTER to continue ``` Note: Do not click ENTER as it will try to find the verification file and we have not set it up yet. ###Setting up the Verification File Since the mongo server is unlikely to have a web server like Apache or Nginx you should use the do the following to create the verification file and spin up a temporary web server. In a new terminal session: mkdir -p /tmp/letsencrypt/public_html/.well-known/acme-challenge cd /tmp/letsencrypt/public_html printf "%s" A-xjoI1jw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU.eefJYv1muREVb9TpEb3qjr9AQsM8IurTn-Svykj0wN0 > .well-known/acme-challenge/A-xjoI1jw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU # run only once per server: $(command -v python2 || command -v python2.7 || command -v python2.6) -c \ "import BaseHTTPServer, SimpleHTTPServer; \ s = BaseHTTPServer.HTTPServer(('', 80), SimpleHTTPServer.SimpleHTTPRequestHandler); \ s.serve_forever()" Once this temporary server is running you can go back to the original terminal server session and click RETURN. It will then look for the file at the location specified (http://mongo0.example.com/.well-known/acme-challenge/A-xjoIljw52X2SSQWqf9P5TQU9vv4HuPDBXN4qFDoRU). The correct response will look like: ``` IMPORTANT NOTES: - If you lose your account credentials, you can recover through e-mails sent to support@example.com. - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/mongo0.example.com/fullchain.pem. Your cert will expire on 2016-06-08. To obtain a new version of the certificate in the future, simply run Let's Encrypt again. - Your account credentials have been saved in your Let's Encrypt configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Let's Encrypt so making regular backups of this folder is ideal. - If you like Let's Encrypt, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le ``` For more details on renewing certificates Letsencrypt ##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 > 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 >> 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 Then convert the crt file to a pem using: openssl x509 -in ca.crt -out ca.pem -outform PEM #Setup the Certs folder mkdir /home/certs cp mongodb.pem /home/certs cp ca.pem /home/certs chown -R mongodb:mongodb /home/certs chmod 777 ca.pem chmod 777 mongodb ##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: /home/certs/mongodb.pem PEMKeyPassword: CAFile: /home/certs/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.3 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 /certs/ca.pem --host mongo0.example.com --sslPEMKeyFile /certs/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") }