This is an old question, however I was facing the same issues and it took me a lot of time to get it working. Some items are rather essential but quite hidden in the documentation.
I try to give an overview without doing simple copy/paste from the MongoDB documentation.
In general a x.509 certificate in MongoDB provides these functions:
- Generate keys to encrypt the connection
- Ensure the connection is established from correct host (i.e. the declared hostname matches the actual hostname)
- Authenticate a client (instead of using username + password or keyfile)
As starting point, one should have a look at these tutorials:
TLS/SSL settings are defined in this configuration file section:
net:
tls:
certificateKeyFile: server.pem
CAFile: server-ca.crt
clusterFile: member.pem
clusterCAFile: cluster-ca.crt
They correspond to command line options
--tlsCertificateKeyFile server.pem
--tlsCAFile server-ca.crt
--tlsClusterFile member.pem
--tlsClusterCAFile cluster-ca.crt
All other TLS/SSL related parameters are well documented and usually they should not cause any confusion or misunderstanding.
Step 1
When a client tries to establish a TLS/SSL enabled connection, then the mongod/mongos
server presents a server certificate. The client verifies this certificate with a CA.
A client can be a normal client (e.g. the Mongo shell mongosh
) or an internal Replica Set / Sharded Cluster member
The server certificate is always the same, mongod/mongos
does not distinct the client types
The server certificate is defined by parameter
net.tls.certificateKeyFile
or --tlsCertificateKeyFile
A normal client can verify the server certificate for example with these:
Option --tls --tlsCAFile server-ca.cer
Option --tls --tlsUseSystemCA
Connection string parameter tls=true&tlsCAFile=server-ca.cer
--tlsUseSystemCA
exists only as option, you cannot define it in connection string. Would be like this:
mongosh --tlsUseSystemCA "mongodb://localhost/?tls=true"
An internal Replica Set / Sharded Cluster member verifies the server certificate by parameter
net.tls.CAFile
or --tlsCAFile
If net.tls.CAFile
or --tlsCAFile
is not specified and you are not using x.509 authentication, the system-wide CA certificate store will be used. If you use x.509 authentication, then net.tls.CAFile
or --tlsCAFile
is required.
Step 2
The client presents a client certificate to the mongod/mongos
server. The client certificate can be used to authenticate the user. In this case, you don't have to provide a password/keyfile.
- For normal client, x.509 authentication is enabled by user creation, e.g.
db.getSiblingDB("$external").runCommand({createUser: "CN=myName,OU=myOrgUnit,O=myOrg,..."})
- For Replica Set / Sharded Cluster member, x.509 authentication is enabled by parameter
security.clusterAuthMode: x509
A normal client (e.g. mongosh
) provides client certificate for example by these parameters:
mongosh --tls --tlsCertificateKeyFile client.pem
(no x.509 authentication)
mongosh --tls --authenticationDatabase $external --authenticationMechanism MONGODB-X509 --tlsCertificateKeyFile client.pem
(with x.509 authentication)
mongosh "mongodb://username:secret@localhost/?tls=true&authSource=admin&tlsCertificateKeyFile=client.pem"
(no x.509 authentication)
mongosh "mongodb://localhost/?tls=true&authSource=$exernal&tlsCertificateKeyFile=client.pem&authMechanism=MONGODB-X509"
(with x.509 authentication)
An internal Replica Set / Sharded Cluster member provides member certificate by parameter net.tls.clusterFile
or --tlsClusterFile
- The
monogd/mongos
sever verifies the client/member certificate with Root-CA defined by parameter net.tls.clusterCAFile
or --tlsClusterCAFile
- The client can be a normal client (e.g. the Mongo shell
mongosh
) or an internal Replica Set / Sharded Cluster member
- The Root-CA is always the same,
mongos/mongod
does not distinct between client certificate and member certificate
- If
net.tls.clusterCAFile
or --tlsClusterCAFile
is not defined, then net.tls.CAFile/--tlsCAFile
is used for verification.
Pitfalls:
Some MongoDB documentations just use the term "certificate" without a clear statement whether it applies to client certificates or server certificates or both. And often MongoDB documentation just use the term "client certificate" without a clear statement whether it applies to normal user client certificates or internal membership client certificates in a Replica Set / Sharded Cluster deployment.
In this answer I use terms "server certificate", "client certificate" and "member certificate" for better understanding.
Server certificates and Member certificates must have the same O
, OU
, and DC
in their subject name.
Starting in MongoDB version 7.0 you can change this behavior by setting net.tls.clusterAuthX509.attributes
, however so far I did not test it.
Client certificates and Member certificates must have different O
, OU
, and DC
in their subject name
Parameter pairs certificateKeyFile/CAFile
and clusterFile/clusterCAFile
are not used to separate connections from normal clients and connections from Replica Set / Sharded Cluster members. They are used to separate client and server certificates, i.e. incoming and outgoing connections. In my opinion, these names are totally miss-leading.
You can use a common Root-CA, defined by net.tls.CAFile
You can also use the same certificate for client, member and server. This common certificate can be even used for x.509 authentication of Replica Set / Sharded Cluster members. This certificate only provides encrypted connection and x.509 member authentication. Of course, you cannot use it for x.509 authentication of normal clients.
Option tlsAllowInvalidCertificates
has no effect on x509 authentication. For x509 authentication the certificate must be valid. Invalid certificates are only used to encrypt the connection.
Test cases:
openssl verify -CAfile server-ca.crt server.pem
openssl verify -CAfile cluster-ca.crt member.pem
openssl verify -CAfile cluster-ca.crt client.pem
# Verify server certificate:
openssl s_server -cert server.pem
# open another terminal
openssl s_client -CAfile server-ca.crt -quiet -no_ign_eof -status <<< Q
# Verify server and client certificate:
openssl s_server -cert server.pem -CAfile cluster-ca.crt -Verify 0
# open another terminal
openssl s_client -cert member.pem -CAfile server-ca.crt -quiet -no_ign_eof -status <<< Q
openssl s_client -cert client.pem -CAfile server-ca.crt -quiet -no_ign_eof -status <<< Q
Visualization
Or if you use only one CA certificate common-ca.crt
: