mongodbssh-tunnelaws-documentdbaws-documentdb-mongoapi

How do I connect via Node.js to a DocDB cluster from local test computer?


I'm trying to migrate from MongoDB to DocumentDB just for keeping everything under one roof, and I want to test my code on a sample DocDB cluster. I'm using Node.js + Express.js for my backend. However, it's been proving quite difficult with the mental jumps and hoops I'm going through.

The instructions provided by the AWS DocumentDB documentation for connecting from outside the VPC have been extraordinarily unhelpful.

In fact, they may even be considered dangerous:

To connect to your Amazon DocumentDB cluster from outside the Amazon VPC, use the following command.

mongo --sslAllowInvalidHostnames --ssl --sslCAFile global-bundle.pem --username <yourUsername> --password <yourPassword> 

I can imagine using this for the MongoDB shell command line. However, I'm trying to connect programmatically. (Or is there a way to do this through the mongosh CLI?)

sslAllowInvalidHostnames seems like it's used for preventing localhost from being rejected due to not match the IP hosts, as seen below when it's forcibly disabled:

MongoServerSelectionError: Hostname/IP does not match certificate's altnames: Host: localhost. is not in the cert's altnames: DNS:sldkfjl.ksdjlfksdjlf.us-east-2.docdb.amazonaws.com, DNS:sldkfjl.cluster-sldkfjlsdk.us-east-2.docdb.amazonaws.com, DNS:sldkfjl.cluster-ro-sldkfjlsdk.us-east-2.docdb.amazonaws.com

This is what I'm stuck on. I am also using the package connect-mongo to have a session manager for the login component of my backend, but it would not allow me to have the tslAllowInvalidHostnames option enabled. If I do, I get the following error:

MongoServerError: Authorization failure

Connecting to the DocDB was not a problem--if I didn't use the package and attempted to upload something, it was fine. Is there a way to test DocDB with the package enabled in any other way? The port forwarding system works as planned.

Essentially, the testing system looks like this:

localhost-frontend --- localhost-backend --- EC2 --- DocDB

The reason why I need connect-mongo is that I wish to use an login session tracker for express.js. I have used connect-mongo in the following fashion to set things up (or rather, not set things up as this results in an error):

const MongoStore = require('connect-mongo');
var store;
 store = MongoStore.create({
    mongoUrl: uri,
    dbName: 'server',
    collectionName: 'sessions',
    secret: ss,
    stringify: false,
    ttl: fifteen_min,
    mongoOptions: { 
      tlsCAFile: process.env.TLSCAFILE,
      directConnection: true, 
      tls: true,
    }
  });

Are there any alternatives that wouldn't cause such problems?

Notes:

  1. I have been indeed able to actually connect with the settings above, independent of the problematic package. For example, the connect command below works perfectly fine. I plan to remove the tslAllowInvalidHostnames option in the production build, and I hope that it will be okay once I do.
const client = new MongoClient(uri, {
  tlsCAFile: process.env.TLSCAFILE, //Specify the DocDB; cert
  tlsAllowInvalidCertificates: mode !== "prod",
  tlsAllowInvalidHostnames: mode !== "prod",
  directConnection: true,
  auth: {
      username: user,
      password: pass
  }
});

client.connect().then((_) => console.log('Connection successful.'));

Solution

  • It turns out that the authorization error does not involve tslAllowInvalidHostnames at all. I just forgot the user and password in the auth field. Once I did that, the problem seems like it's fixed.

    Conducting the following changes below fixed my issue. The package does not inhibit which mongoOptions you can use after all.

    const MongoStore = require('connect-mongo');
    var store;
     store = MongoStore.create({
        mongoUrl: uri,
        dbName: 'server',
        collectionName: 'sessions',
        secret: ss,
        stringify: false,
        ttl: fifteen_min,
        mongoOptions: { 
          tlsCAFile: process.env.TLSCAFILE,
          directConnection: true, 
          tls: true,
          tlsAllowInvalidCertificates: mode !== "prod",
          tlsAllowInvalidHostnames: mode !== "prod",
          auth: {
              username: user,
              password: pass
          }
        }
      });