8

How do I correctly configure MongoDB to use Letsencrypt SSL on Ubuntu?

I have created an SSL certificate using Letsencrypt and combined it via:

cat /etc/letsencrypt/live/example.com/fullchain.pem /etc/letsencrypt/live/example.com/privkey.pem > /etc/ssl/mongo.pem

And setup mongo config like:

net:
  port: 27017
  bindIp: 0.0.0.0
  ssl:
    mode: requireSSL
    PEMKeyFile: /etc/ssl/mongo.pem

But I get this error when trying to start Mongo:

No SSL certificate validation can be performed since no CA file has been provided; please specify an sslCAFile parameter

How do I correctly set the CAFile? Doesn't Ubuntu typically use a "CA Path" with a bunch of different root certs in their own files? I tried using the CURL CA bundle but that didn't work either.

Im using Mongo v3.0.12 and Ubuntu 14.04

Petah
  • 650
  • 2
  • 13
  • 24
  • 3
    I would first try doing what the error message suggests. – Michael Hampton Sep 28 '16 at 22:55
  • @MichaelHampton But where/what CA File am I supposed to use? Doesn't Ubuntu typically use a "CA Path" with a bunch of different root certs in their own files? I tried using the CURL CA bundle but that didn't work either. – Petah Sep 29 '16 at 00:19

3 Answers3

10

You combine the wrong pem files. You need to combine privkey.pem with cert.pem.

cat /etc/letsencrypt/live/example.com/privkey.pem /etc/letsencrypt/live/example.com/cert.pem > /etc/ssl/mongo.pem

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

sudo touch /etc/ssl/ca.crt
sudo chmod 777 /etc/ssl/ca.crt

Add the certificate of the website, add -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- lines and make sure you end with a new line saving the file:

sudo vi /etc/ssl/ca.crt

Then convert the crt file to a pem using:

sudo touch /etc/ssl/ca.pem
sudo chmod 777 /etc/ssl/ca.pem
sudo openssl x509 -in /etc/ssl/ca.crt -out /etc/ssl/ca.pem -outform PEM

And combine with chain.pem from Let's Encrypt into a single file ca.pem

sudo cat /etc/letsencrypt/live/example.com/chain.pem >> /etc/ssl/ca.pem

To set the CAFile follow this mongo configuration setup:

net:  
  port: 27017
  bindIp: 0.0.0.0
  ssl:  
    mode: requireSSL  
    PEMKeyFile: /etc/ssl/mongo.pem
    CAFile: /etc/ssl/ca.pem

Restart MongoDB:

sudo systemctl restart mongod
sudo systemctl status mongod

Don't forget the moment when you renew the Let's Encrypt certificates, you need to renew also mongo.pem and ca.pem.

Herman Fransen
  • 201
  • 2
  • 4
  • 1
    Awesome answer! I can't thank you enough. Why did you use a CAFile from Identrust instead of Let's Encrypt (https://letsencrypt.org/certificates)? – Rodrigo Pinto Jan 10 '18 at 05:10
  • @RodrigoPedroso - Good question, don't know. – Herman Fransen Jan 12 '18 at 11:47
  • 2
    Because let's encrypt is quite new at that time, they are using Identrust to cross sign their certificates. You can download it directly from https://letsencrypt.org/certs/trustid-x3-root.pem.txt. Now Let's encrypt is widely trusted – devansvd Nov 05 '19 at 10:30
3

The CA file you need can be obtained from Letsencrypt, look for one of the intermediate certificates here:

https://letsencrypt.org/certificates/

Then, specify the path to that certificate with the SSL CAFile option.

Adam C
  • 5,222
  • 2
  • 30
  • 52
0

mongod needs the whole certificate chain including intermediaries and crucially, the root ca. for whatever reason, certbot does not include the root ca on your filesystem when it obtains or renews a cert so you must do a little work to establish the root ca (it can change over time, depending on normal cert expiries or extraordinary revocations).

on may 5th, 2023, a valid mechanism for determining the root ca is as follows:

  • give your host a fully qualified domain name for a domain that you control (make sure to update dns to resolve the name to your host):
    sudo hostnamectl set-hostname alpha.example.com
    
  • obtain a let's encrypt cert with certbot. supply a post-hook argument to ensure you get a copy of the cert in the format mongod requires (private_key+cert+intermediaries) and that the copy stays up to date when certbot renews your cert in the future:
    sudo certbot certonly \
      --noninteractive \
      --cert-name $(hostname -f) \
      --key-type ecdsa \
      --force-renewal \
      --post-hook "cat /etc/letsencrypt/live/$(hostname -f)/privkey.pem /etc/letsencrypt/live/$(hostname -f)/fullchain.pem > /etc/ssl/$(hostname -f).pem" \
      --expand \
      --allow-subset-of-names \
      -m ops@example.com \
      --agree-tos \
      --no-eff-email \
      --preferred-challenges http \
      --standalone \
      -d $(hostname -f)
    
  • split the fullchain.pem file obtained by certbot into separate temporary files for each cert that it contains:
    sudo csplit \
      --prefix /tmp/cert \
      --elide-empty-files \
      /etc/letsencrypt/live/$(hostname -f)/fullchain.pem \
      '/-----BEGIN CERTIFICATE-----/' \
      '{*}'
    
  • determine the root ca by examining the cert and intermediaries:
    for cert in /tmp/cert*; do
      echo ${cert}
      openssl \
        x509 \
        -in ${cert} \
        -inform PEM \
        -subject \
        -issuer \
        -nameopt RFC2253 \
        -fingerprint \
        -noout
      echo
    done
    
    output might look like this (your first block, will definitely be different):
    /tmp/cert00
    subject=CN=alpha.example.com
    issuer=CN=R3,O=Let's Encrypt,C=US
    SHA1 Fingerprint=60:50:DE:3E:FA:F1:DF:30:3F:1B:73:F0:1B:F4:44:51:92:C5:CB:0D
    
    /tmp/cert01
    subject=CN=R3,O=Let's Encrypt,C=US
    issuer=CN=ISRG Root X1,O=Internet Security Research Group,C=US
    SHA1 Fingerprint=A0:53:37:5B:FE:84:E8:B7:48:78:2C:7C:EE:15:82:7A:6A:F5:A4:05
    
    /tmp/cert02
    subject=CN=ISRG Root X1,O=Internet Security Research Group,C=US
    issuer=CN=DST Root CA X3,O=Digital Signature Trust Co.
    SHA1 Fingerprint=93:3C:6D:DE:E9:5C:9C:41:A4:0F:9F:50:49:3D:82:BE:03:AD:87:BF
    
    the example output shows the subject and issuer for each cert extracted from fullchain.pem it shows the issuer for each cert in the chain, except the final one, the root CA:
    • CN=alpha.example.com was issued by CN=R3,O=Let's Encrypt,C=US
    • CN=R3,O=Let's Encrypt,C=US was issued by CN=ISRG Root X1,O=Internet Security Research Group,C=US
    • CN=ISRG Root X1,O=Internet Security Research Group,C=US was issued by CN=DST Root CA X3,O=Digital Signature Trust Co.
  • the final issuer (CN=DST Root CA X3,O=Digital Signature Trust Co.) cert is missing from the filesystem, but that's ok, we know the sha fingerprint of a cert it issued (933C6DDEE95C9C41A40F9F50493D82BE03AD87BF with colons removed) and we can look that up on censys, who provide a link to the issuer (DST Root CA X3) cert and its pem file:
    -----BEGIN CERTIFICATE-----
    MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
    MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
    DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTI0MDkzMDE4MTQwM1ow
    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-----
    
    once you have the pem file on your filesystem, you can add a CAFile entry to your mongod.conf and restart your mongod.service which should make mongo and it's cluster peers happy.
grenade
  • 312
  • 1
  • 3
  • 8