Adding you to my servers trust?


#1

Which pem file is the one that lets me sslValidate you as a ca?

http://mongodb.github.io/node-mongodb-native/2.1/reference/connecting/ssl/#driver-should-validate-server-certificate

Right now it looks like my centos 7 server hasn’t got you in it list of trusted cas

/etc/pki/ca-trust/source/README.md says:

This directory /etc/pki/ca-trust/source/ contains CA certificates and
trust settings in the PEM file format. The trust settings found here will be
interpreted with a high priority - higher than the ones found in
/usr/share/pki/ca-trust-source/.

=============================================================================
QUICK HELP: To add a certificate in the simple PEM or DER file formats to the
list of CAs trusted on the system:

        Copy it to the
                /etc/pki/ca-trust/source/anchors/
        subdirectory, and run the
                update-ca-trust
        command.

        If your certificate is in the extended BEGIN TRUSTED file format,
        then place it into the main source/ directory instead.

=============================================================================

Please refer to the update-ca-trust(8) manual page for additional information.

is it lets-encrypt-x3-cross-signed.pem or isrgrootx1.pem? downloaded from https://letsencrypt.org/certificates/


#2

linked to issue: https://jira.mongodb.org/browse/NODE-703


#3

Certificates are currently cross-signed by an intermediate certificate that leads up to the IdenTrust X3 root certificate.

The IdenTrust root certificate should be included by default in CentOS. Try pointing sslCA to /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt.

Another thing: You’re setting the sslKey and sslCert in the client code. Those parameters are used for client certificate authentication; they’re not related to verifying the SSL connection to the server. You also mention that you’re using a username and password for MongoDB. I’m not familiar with MongoDB, but you usually have either password-based authentication or certificate-based authentication for clients, not both. You’d also probably have to configure things on the server end for that to work (at least that’s how it works in things like MySQL). tl;dr: You probably want to get rid of sslKey and sslCert in your client code.


#4

I don’t know if this helps but, this is server-to-server not client-to-server


#5

Now the error has changed from

MongoError: unable to get issuer certificate

to

MongoError: unable to get local issuer certificate

#6

Also Mongodb docs specify:

Driver should validate Server certificate and present valid Certificate
If the server is configured to perform certificate validation we need to pass a certificate through the driver as well as verify the one retrieved.

http://mongodb.github.io/node-mongodb-native/2.1/reference/connecting/ssl/#driver-should-validate-server-certificate-and-present-valid-certificate


#7

To clarify - the user:password is for mongodb to use internally (has nothing to do with the ssl auth). It is the mongo user outlined by the db admin. This user has specific read / write privlages on a part of the database.


#8

In my mongod.log on site1.com

2016-05-08T14:59:20.747+0200 I NETWORK  [initandlisten] waiting for connections on port 27017 ssl
2016-05-08T15:07:26.818+0200 I NETWORK  [initandlisten] connection accepted from site2.com:48133 #1 (1 connection now open)
2016-05-08T15:07:26.828+0200 E NETWORK  [conn1] SSL peer certificate validation failed:certificate not trusted
2016-05-08T15:07:26.828+0200 I NETWORK  [conn1] end connection site2.com:48133 (0 connections now open)

#9

I guess that site1 tries to openssl verify site2 pem files but I don’t know how to test that in the terminal so I tried verifying site1’s own pem files in every combination (beating it with a stick) and I can see that I ether get

A: unable to get issuer certificate

B: unable to get local issuer certificate

Btw: I concated the files as advised by mongdb docs:

cat privkey.pem cert.pem > /etc/letsencrypt/live/site1.com/mongod.pem

and

cat lets-encrypt-x3-cross-signed.pem isrgrootx1.pem > /etc/letsencrypt/mongod-letsencrypt.pem

What happened (maybe it’s useful):

[root@panel ~]# openssl verify -verbose -CAfile /etc/letsencrypt/lets-encrypt-x3-cross-signed.pem /etc/letsencrypt/live/site1.com/mongod.pem 
/etc/letsencrypt/live/site1.com/mongod.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
error 2 at 1 depth lookup:unable to get issuer certificate

[root@panel ~]# openssl verify -verbose -CAfile /etc/letsencrypt/mongod-letsencrypt.pem /etc/letsencrypt/live/site1.com/mongod.pem 
/etc/letsencrypt/live/site1.com/mongod.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
error 2 at 1 depth lookup:unable to get issuer certificate

[root@panel ~]# openssl verify -verbose -CAfile /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt /etc/letsencrypt/live/site1.com/mongod.pem 
/etc/letsencrypt/live/site1.com/mongod.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

[root@panel ~]# openssl verify -verbose -CAfile /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt /etc/letsencrypt/live/site1.com/fullchain.pem 
/etc/letsencrypt/live/site1.com/fullchain.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

[root@panel ~]# openssl verify -verbose -CAfile /etc/letsencrypt/live/site1.com/mongod.pem /etc/letsencrypt/live/site1.com/fullchain.pem
/etc/letsencrypt/live/site1.com/fullchain.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

[root@panel ~]# openssl verify -verbose -CAfile /etc/letsencrypt/mongod-letsencrypt.pem /etc/letsencrypt/live/site1.com/mongod.pem 
/etc/letsencrypt/live/site1.com/mongod.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
error 2 at 1 depth lookup:unable to get issuer certificate

#10

I had an idea (I thought logically I would fix it) through combining earlier advice from letsencrypt staff on using fullchain.pem instead of cert.pem but, by concat-ing the file to the privkey.pem as mongodb asks

also following @pfg’s advice of using /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt as -CAfile

cat  /etc/letsencrypt/live/site1.com/privkey.pem /etc/letsencrypt/live/site1.com/fullchain.pem > /etc/letsencrypt/live/site1.com/mongodfull.pem

then test openssl verify again site1’s own pems

[root@panel ~]# openssl verify -verbose -CAfile /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt /etc/letsencrypt/live/site1.com/mongodfull.pem 
/etc/letsencrypt/live/site.com/mongodfull.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

#11

more tries at verifying own pems with the new pem file

openssl verify -verbose -CAfile /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt /etc/letsencrypt/live/site1.com/mongodfull.pem 
/etc/letsencrypt/live/site1.com/mongodfull.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

 openssl verify -verbose -CAfile /etc/letsencrypt/lets-encrypt-x3-cross-signed.pem /etc/letsencrypt/live/site1.com/mongodfull.pem 
/etc/letsencrypt/live/site1.com/mongodfull.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
error 2 at 1 depth lookup:unable to get issuer certificate

openssl verify -verbose -CAfile /etc/letsencrypt/isrgrootx1.pem /etc/letsencrypt/live/site1.com/mongodfull.pem 
/etc/letsencrypt/live/site1.com/mongodfull.pem: CN = site1.com
error 20 at 0 depth lookup:unable to get local issuer certificate

openssl verify -verbose -CAfile /etc/letsencrypt/mongod-letsencrypt.pem /etc/letsencrypt/live/site1.com/mongodfull.pem 
/etc/letsencrypt/live/site1.com/mongodfull.pem: C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
error 2 at 1 depth lookup:unable to get issuer certificate

#12
require('mongodb').MongoClient.connect(
    'mongodb://benz:xxxx@site1.com:27017/db?ssl=true'
    ,	{server:{
	    sslValidate:true
        ,   checkServerIdentity:true
        ,   sslCA:[require('fs').readFileSync('/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt')]
        ,   sslKey:require('fs').readFileSync('/etc/letsencrypt/live/site2.com/privkey.pem')
        ,   sslCert:require('fs').readFileSync('/etc/letsencrypt/live/site2.com/mongodfull.pem')
	    }}
    ,   function(e,db){
            console.log(e,db);
            db.close();
            });

still causes

MongoError: unable to get local issuer certificate

even though mongodfull.pem contains both

/etc/letsencrypt/live/site2.com/privkey.pem 
/etc/letsencrypt/live/site2.com/fullchain.pem

and

chown mongod:mongod /etc/letsencrypt/live/site2.com/mongodfull.pem 
chmod 600 /etc/letsencrypt/live/site2.com/mongodfull.pem

#13

That’s not an existing concept in TLS. A client connects to a server, even if that client might be a server itself.

Clients may use a client certificate as an authentication mechanism, but that is essentially a replacement for password-based authentication and not strictly necessary.

Based on this guide, client certificate authentication needs to be enabled through various steps and the certificate subject for every user needs to be configured as well.

My recommendation: Keep it simple - skip client certificates, and try to get things working with regular password-based authentication while using TLS. This means: The MongoDB server gets a certificate and private key, and your client gets, at most, a CA file (which might as well be ca-bundle.trust.crt) - i.e., no sslKey or sslCert anywhere in your client code.

Once that’s working, and you decide you still want to use client certificates as an authentication method (instead of passwords), you should be able to follow that guide.


#14

That guide is incomplete as it doesn’t show how to integrate the auth code into the connect code (below)

benz:xxxx has nothing to do with ssl. It’s after the ssl to do with read/write permissions on the database once connected

require('mongodb').MongoClient.connect(
    'mongodb://benz:xxxx@site1.com:27017/db?ssl=true'
    ,	{server:{
	    sslValidate:true
        ,   checkServerIdentity:true
        ,   sslCA:[require('fs').readFileSync('/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt')]
	    }}
    ,   function(e,db){
            console.log(e,db);
            db.close();
            });

still causes

MongoError: unable to get local issuer certificate

how come I can’t succeed with any openssl verify comands?


#15

Can you provide the commands you used to generate the .pem file you’re using on the server as --sslPEMKeyFile?


#16

I have now got no user

require('mongodb').MongoClient.connect(
    'mongodb://site1.com:27017/db?ssl=true'
    ,   {server:{
            sslValidate:true
        ,   checkServerIdentity:true
        ,   sslCA:[require('fs').readFileSync('/etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt')]
        ,   sslKey:require('fs').readFileSync('/etc/letsencrypt/live/site2.com/privkey.pem')
        ,   sslCert:require('fs').readFileSync('/etc/letsencrypt/live/site2.com/mongodfull.pem')
            }}
    ,   function(e,db){
            console.log(e,db);
            db.close();
            });

But even without the user it still causes

MongoError: unable to get local issuer certificate

#17
cat /etc/letsencrypt/lets-encrypt-x3-cross-signed.pem /etc/letsencrypt/isrgrootx1.pem > /etc/letsencrypt/mongod-letsencrypt.pem

reference https://gist.github.com/leommoore/1e773a7d230ca4bbe1c2#preparing-the-letsencrypt-cert-for-use-with-mongodb


#18

That’s the chain/CA file.

PEMKeyFile should probably be cat privkey.pem cert.pem (original files from the client).
CAFile should be either just https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt (try this first), or alternatively:

(Longer explanation: That guide was originally written for the X1 intermediate certificate, which lead back to the ISRG root certificate. The current intermediate certificate (X3) doesn’t lead back to the ISRG root, so you have to use the IdenTrust (DST X3) root.)

Once you’ve configured your server, you can use some openssl code to verify that the server is sending the intermediate certificate like this:

openssl s_client -showcerts -connect site1.com:mongoport

And then verify that the output contains those lines:

1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3

#19

Confirmed!

1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3

and I also see

Acceptable client certificate CA names
/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
/O=Digital Signature Trust Co./CN=DST Root CA X3

#20

Do I have to add https://www.identrust.com/certificates/trustid/root-download-x3.html to /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt? (cause the code still does not connect)

MongoError: unable to get local issuer certificate