skip to Main Content

Issue: Unable to Connect to MongoDB with TLS and Authentication
MongoDB Setup:
I’m running MongoDB on a Docker container, and I’ve enabled TLS/SSL and role-based access control (RBAC) with internal authentication. Here’s an outline of my setup:

MongoDB Version: 6.x (Running in Docker)
mongod.conf Configuration:

net:
  port: 27017
  bindIp: 0.0.0.0
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongo.pem   # Combined certificate and private key
    CAFile: /etc/ssl/ca.pem                  # Certificate Authority file
    allowConnectionsWithoutCertificates: false

security:
  authorization: "enabled"                   # Enabling Role-Based Access Control (RBAC)
  keyFile: /etc/rs_keyfile                   # Path to key file for replica set authentication

systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
  verbosity: 2

Certificates:
mongo.pem: Contains the server certificate and private key.
ca.pem: Contains the CA certificate that signed mongo.pem.
Docker Compose:
MongoDB is running in a Docker container, and I have generated the required PEM files using openssl.

How I Start MongoDB:
I start MongoDB with the above configuration using Docker. Everything seems to start correctly, but when I try to connect to MongoDB using mongosh with TLS, I encounter connection issues.

Error When Connecting:
I attempt to connect using the following command:

mongosh --tls --tlsCAFile /etc/ssl/ca.pem --tlsCertificateKeyFile /etc/ssl/mongo.pem --host 127.0.0.1 --port 27017

However, I get the following error:

MongoServerSelectionError: connection to 127.0.0.1:27017 closed

When using tlsAllowInvalidHostnames, I still can’t establish a successful connection.

Additional Information:

I confirmed the certificates using openssl verify and openssl s_client, and they seem valid.

Error in Log Files:

I noticed the following errors in the MongoDB logs:

User assertion "NotYetInitialized: no replset config has been received"
Unable to retrieve storageStats in $collStats stage :: caused by :: Collection [local.oplog.rs] not found.

Questions: Certificate Setup: Is there any issue with how I’ve generated or configured the certificates for MongoDB?

Hostname Issue: How can I properly resolve the “hostname mismatch” issue for local connections when using TLS?

Replica Set Configuration: Even though I haven’t enabled replication, I still see replica set errors. Could this be related to the issue?

Here is the output of openssl x509 -in /etc/ssl/mongo.pem -noout -text

Certificate: 
Data: 
Version: 3 (0x2) 
Serial Number: 23:e7:a5:54:fa:d1:5f:12:7c:a7:5a:16:7c:63:50:23:16:39:a2:c9 
Signature Algorithm: sha256WithRSAEncryption 
Issuer: C = US, ST = UH, L = GO, O = NFA, OU = NFA, CN = NFA, emailAddress = [email protected] 
Validity Not Before: Sep 14 15:11:18 2024 GMT 
Not After : Sep 14 15:11:18 2025 GMT Subject: CN = mongo1
Subject Public Key Info: 
   Public Key Algorithm: rsaEncryption Public-Key: (2048 bit)
      00:c5:46:e0:4f:f2:3c:14:0e:67:6c:e6:ee:60:37: 
      ...        
   Exponent: 65537 (0x10001) 
X509v3 extensions: 
   X509v3 Key Usage: Key Encipherment, Data Encipherment 
   X509v3 Extended Key Usage: TLS Web Server Authentication 
X509v3 Subject Alternative Name: 
   DNS:mongo1, IP Address:127.0.0.1, IP Address:0.0.0.0 
X509v3 Subject Key Identifier: F1:EC:87:9E:4B:1C:5B:44:EA:91:68:45:2F:F3:20:44:B0:4D:22:69 
X509v3 Authority Key Identifier: 17:40:89:67:A8:59:00:18:A4:E4:33:BD:F2:7A:2D:D0:16:C7:D2:78 
Signature Algorithm: sha256WithRSAEncryption

2

Answers


  1. Chosen as BEST ANSWER

    I’m now able to connect using TLS with the admin user, but when I try to initialize the replica set, I encounter the following error:

    MongoServerError[NodeNotFound]: replSetInitiate quorum check failed because not all proposed set members responded affirmatively: localhost:27018 failed with Error connecting to localhost:27018 (127.0.0.1:27018) :: caused by :: onInvoke :: caused by :: Connection refused, localhost:27019 failed with Error connecting to localhost:27019 (127.0.0.1:27019) :: caused by :: onInvoke :: caused by :: Connection refused I want to make sure I’m following all the necessary steps, especially around generating certificates.

    Here’s my process:

    openssl.cnf:

    [ req ]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
    x509_extensions = v3_req
    req_extensions = v3_req
    
    [ dn ]
    C = US
    ST = Massachusetts
    L = Bedford
    O = Personal
    OU = Personal
    emailAddress = [email protected]
    CN = localhost
    
    [ v3_req ]
    subjectAltName = @alt_names
    
    [ alt_names ]
    DNS.1 = localhost
    DNS.2 = mongo1
    DNS.3 = mongo2
    DNS.4 = mongo3
    

    Steps for certificate generation:

    1. Generate the CA certificate:

      openssl req -newkey rsa:2048 -new -x509 -days 3650 -nodes -config openssl.cnf -out ca.crt -keyout ca.key

    2.Combine the CA key and certificate

    cat ca.key ca.crt > ca.pem
    

    3.Generate a member certificate:

    openssl req -newkey rsa:2048 -new -x509 -days 3650 -nodes -config openssl.cnf -out member.crt -keyout member.key
    

    4.Combine the member key and certificate:

    cat member.key member.crt > member.pem
    

    Next, I generate the replica set keyfile:

    openssl rand -base64 756 > ${PWD}/rs_keyfile
    chmod 0400 ${PWD}/rs_keyfile
    chown 999:999 ${PWD}/rs_keyfile
    

    Then in mongod.conf:

    # Network Interface
    net:
      port: 27017
      bindIp: 0.0.0.0
      tls:
        mode: requireTLS
        certificateKeyFile: /etc/ssl/ca.pem        # Combined server private key and certificate
        CAFile: /etc/ssl/ca.crt                    
        allowConnectionsWithoutCertificates: false # Require client certificates for all connections
        clusterFile: /etc/ssl/member.pem           
        allowInvalidHostnames: false 
    
    # Replica Set Configuration
    replication:
      replSetName: "nfa_rs"                       # Name of the replica set
    
    # Security Settings
    security:
      authorization: "enabled"                    # Enables role-based access control (RBAC)
      clusterAuthMode: x509                       # Use x509 certificates for inter-member communication
      keyFile: /etc/rs_keyfile
    

    I tried to initiate the rs with machine ip (also added to openssl) / localhost / mongo network. What might I be doing wrong?


  2. Mit comment was a bit misleading. Of course, you can "use" a MongoDB without initiated the Replica Set. But as long as you did not initiate the Replica Set, it acts as a stand-alone MongoDB.

    I am not familiar with Docker, I don’t know how it initiate the replia set. But you should find several answers here on SO with search function.

    Let’s focus on your certificate issue:

    As said, I have no clue about Docker, certainly

    X509v3 Subject Alternative Name: 
       DNS:mongo1, IP Address:127.0.0.1, IP Address:0.0.0.0 
    

    is (at least) a security risk. IP Address:127.0.0.1, IP Address:0.0.0.0 makes the certificate valid for any host.

    First part:

    You created a server certificate:

    X509v3 extensions: 
       X509v3 Extended Key Usage: TLS Web Server Authentication 
    

    Client certificates are not used (where I don’t see any issue, because client certificates add only negligible security, unless they are used for x.509 authentication)

    Thus your config should be

    net:
      port: 27017
      bindIp: 0.0.0.0
      tls:
        mode: requireTLS
        certificateKeyFile: /etc/ssl/mongo.pem   # Combined certificate and private key
        allowConnectionsWithoutCertificates: true
    

    And connection is done like this:

    mongosh --tls --tlsCAFile /etc/ssl/ca.pem --host 127.0.0.1 --port 27017
    

    Maybe, due to Docker and certificate you have to use real hostname instead of --host 127.0.0.1 or use option --allowInvalidHostnames.

    It works like this: The mongod server provides the server certificate /etc/ssl/mongo.pem and the mongosh client verifies this certificate with /etc/ssl/ca.pem. The server does not receive any client certificate, thus net.tls.CAFile is not needed.

    Second part:

    From your question, it is not clear whether you like to use client certificates or not. If yes, then first you need to create the client certificate (assuming /etc/ssl/client.pem), i.e. certificate option must be

    X509v3 extensions: 
       X509v3 Extended Key Usage: TLS Web Client Authentication 
    

    Most likely it will be also issued by certificate /etc/ssl/ca.pem. In this case configuration and connection would be like this:

    net:
      port: 27017
      bindIp: 0.0.0.0
      tls:
        mode: requireTLS
        certificateKeyFile: /etc/ssl/mongo.pem   # Combined certificate and private key
        CAFile: /etc/ssl/ca.pem                  # Certificate Authority file
        clusterFile: /etc/ssl/client.pem         # Client certificate used to connect to other replica set members
        allowInvalidHostnames: true              # depending how you set "X509v3 Subject Alternative Name"
        allowConnectionsWithoutCertificates: false
    
    
    mongosh --tls --tlsCAFile /etc/ssl/ca.pem --tlsCertificateKeyFile /etc/ssl/client.pem --host 127.0.0.1 --port 27017
    

    Some notes:

    • X509v3 Subject Alternative Name is not relevant in client certificate, it is not used.

    • You could create a single certificate with both options, TLS Web Client Authentication and TLS Web Server Authentication. But I in my opinion, this is rather pointless, because you don’t gain anything for the client certificate part. Unless you use the client certificate for x.509 authentication it is also accepted when invalid. Hostnames in client certificate are not verified at all.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search