Connecting to MongoDB over SSL with Node.js

前端 未结 3 1804
一整个雨季
一整个雨季 2020-12-14 23:11

How do I connect to a MongoDB-server over SSL using Node.js?

I\'ve read the sources of a few drivers (mongojs, mongodb-native) and I\'ve been googling a while now, b

相关标签:
3条回答
  • 2020-12-14 23:15

    As suggested in the comments, the node-mongodb-native has everything needed.

    I got it up and running using the following:

    var mongo = require('mongodb');
    
    var server = new mongo.Server('HOSTNAME', 27017, { ssl: true });
    var db = new mongo.Db('NAME_OF_MY_DB', server, { w: 1 });
    var auth = { user: 'USERNAME', pass: 'PASSWORD' };
    
    db.open(function(err, db) {
      if (err) return console.log("error opening", err);
    
      db.authenticate(auth.user, auth.pass, function(err, result) {
        if (err) return console.log("error authenticating", err);
    
        console.log("authed?", result);
    
        db.collection('whatever').count(function(err, count) {
          if (err) return console.log("error counting", err);
    
          console.log("count", count);
          db.close()
        });
      });
    });
    

    Edit

    You can also do ssl from mongoose:

    mongoose.createConnection(connString, { server: { ssl: true }})
    
    0 讨论(0)
  • 2020-12-14 23:26

    If you want to authenticate using a certificate, using node-mongodb-native:

    var buffer = require('fs').readFileSync("mongodb.pem");
    var MongoClient = require('mongodb').MongoClient;
    MongoClient.connect("mongodb://hostname:27017/test?ssl=true", {
        sslKey: buffer,
        sslCert: buffer,
        sslValidate: false //in case of self-generated certificate
    }, function(err, db) {
        console.log(err);
        console.log(db);
        db.close();
    });
    
    0 讨论(0)
  • 2020-12-14 23:39

    Step 1: Obtain MongoDB 3.0

    The first thing you need to know is that that SSL is only supported out-of-the-box by MongoDB 3.0 and later. Ubuntu does not have 3.0 in the default repositories, so here's how you get it:

    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
    echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
    sudo apt-get update
    sudo apt-get install -y mongodb-org=3.0.7 mongodb-org-server=3.0.7 mongodb-org-shell=3.0.7 mongodb-org-mongos=3.0.7 mongodb-org-tools=3.0.7
    

    3.0.7 is the latest stable version as of now, but feel free to substitute 3.0.7 with your favorite release.

    Step 2: Obtain Private Key, Certificate, and PEM files

    The PEM contains a Public Key Certificate and its associated Private Key. These files can either be obtained with IRL dollars from a Certificate Authroity or generated with OpenSSL like so:

    openssl req -newkey rsa:2048 -new -x509 -days 3650 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key
    cat mongodb-cert.key mongodb-cert.crt > mongodb.pem
    

    mongodb.pem will be used as the PEM file, mongodb-cert.key is the Private Key file, and mongodb-cert.crt is Certificate file which can also be used as the CA file. YOU WILL NEED ALL THREE OF THESE.

    Step 3: Configure MongoD

    We're going to assume that you copied these files to your /etc/ssl/ folder where they belong. Now we open up our MongoDB config file:

    sudo vi /etc/mongod.conf
    

    and modify the "# network interfaces" section like so:

    # network interfaces
    net:
      port: 27017
      #bindIp: 127.0.0.1
      ssl:
        mode: allowSSL
        PEMKeyFile: /etc/ssl/mongodb.pem
        #CAFile: /etc/ssl/mongodb-cert.crt
    

    PLEASE NOTE: we are commenting out bindIp. THIS ALLOWS EXTERNAL CONNECTIONS to access your Mongo database. We assume that this is your end goal (Why would your encrypt traffic on localhost?), but you should only do this AFTER SETTING UP AUTHORIZATION RULES for your MongoDB server.

    The CAFile is also commented out as it is optional. I will explain how to set up Certificate Authority trust at the end of this post.

    As always, you must restart MongoDB before config file changes will take effect:

    sudo service mongod restart
    

    DID YOUR SERVER FAIL TO START? You are on your own, but there is probably an issue with your certificate files. You can check start-up errors by running mongod manually:

    sudo mongod --config /etc/mongod.conf
    

    Step 4: Test your server settings

    Before we go messing with Node configurations, let's make sure that your server setup is working properly by connecting with the mongo command line client:

    mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates
    

    Unless the domain name on your certificate is 127.0.0.1 or localhost, the --sslAllowInvalidHostnames flag is necessary. Without it, you will probably get this error:

    E NETWORK  The server certificate does not match the host name 127.0.0.1
    E QUERY    Error: socket exception [CONNECT_ERROR] for 
        at connect (src/mongo/shell/mongo.js:179:14)
        at (connect):1:6 at src/mongo/shell/mongo.js:179
    exception: connect failed
    

    Step 5: Configure Node.JS / Mongoose

    If you are using the node-mongodb-native package in your Node application, stop immediately and start using Mongoose. It's not that hard. That said, mongoose.connect() has virtually the same API as mongodb.connect(), so substitute appropriately.

        var fs = require('fs')
          , mongoose = require('mongoose')
          , mongoUri = "mongodb://127.0.0.1:27017?ssl=true"
          , mongoOpt = {
              "sslValidate": false,
              "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'),
              "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt')
            }
          ;
    
    mongoose.connect(mongoUri, mongoOpt);
    

    Step 6: [Optionally] verify your Certificates via a Certificate Authority

    In order to validate your SSL Certificates, you need to obtain a CA (or bundle) file from your Certificate Authority. This will look a lot like your Certificate file, but will often contain multiple Certificates (which forms a chain of trust to verify that a certificate is valid). If you are using a self-signed certificate, you can use your mongodb-cert.crt as a CA file.

    You will also need to ensure that your MongoDB server's hostname matches the one used to create the certificate.

    Step 6.3: Update your mongod configuration

    sudo vi /etc/mongod.conf
    

    and modify the "# network interfaces" section like so:

    # network interfaces net:   port: 27017   #bindIp: 127.0.0.1   ssl:
        mode: allowSSL
        PEMKeyFile: /etc/ssl/mongodb.pem
        CAFile: /etc/ssl/mongodb-ca.crt
    
    sudo service mongod restart
    

    Step 6.4: Test your server settings

    mongo --ssl --sslAllowInvalidHostnames --sslCAFile /etc/ssl/mongodb-ca.crt --sslPEMKeyFile /etc/ssl/mongodb.pem
    

    Mongo Clients can pass in the CA file as well to verify that they are talking to the correct server. This is done with the --sslCAFile parameter

    Mongo Servers configured with a CAFile require that clients possess a valid Certificate AND the Private Key for the server. In the mongo shell client, this is done by passing in the --sslPEMKeyFile parameter.

    Without a PEM file (which contains the server's Certificate), you may see this error:

    I NETWORK  DBClientCursor::init call() failed
    E QUERY    Error: DBClientBase::findN: transport error: 127.0.0.1:27017 ns: admin.$cmd query: { whatsmyuri: 1 }
        at connect (src/mongo/shell/mongo.js:179:14)
        at (connect):1:6 at src/mongo/shell/mongo.js:179
    exception: connect failed
    

    The server can be configured to accept requests from clients without a PEM file by enabling net.ssl.weakCertificateValidation, but you will be weakening your security for no real gain.

    Step 6.5: Configure Node.JS / Mongoose

    There are a couple of gotchas here, so bear with me.

    First, you NEED to have node-mongodb-native 2.0 or later. If you are using Mongoose, then you NEED Mongoose 4.0 or later. Previous Mongoose versions use node-mongodb-native 1.* which does not support Certificate validation in any capacity whatsoever.

    Secondly, there is no sslAllowInvalidHostnames or similar option available in node-mongodb-native. This is not something that node-mongodb-native developers can fix (I would have by now) because the native TLS library available in Node 0.10.* offers no option for this. In Node 4.* and 5.*, there is a checkServerIdentity option which offers hope, but switching from the original Node branch to the branch after the io.js merge can cause a bit of headache at the current time.

    So let's try this:

    var fs = require('fs')
      , mongoose = require('mongoose')
      , mongoUri = "mongodb://127.0.0.1:27017?ssl=true"
      , mongoOpt = {
          "server": { 
            "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'),
            "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt'),
            "sslCa": fs.readFileSync('/etc/ssl/mongodb-ca.crt')
          }
        }
      ;
    

    If you are getting hostname/IP mismatch errors, either fix your certificate, or negate all this hard work by disabling sslValidate:

    var fs = require('fs')
      , mongoose = require('mongoose')
      , mongoUri = "mongodb://127.0.0.1:27017?ssl=true"
      , mongoOpt = {
          "server": {
            "sslValidate": false,
            "sslKey": fs.readFileSync('/etc/ssl/mongodb.pem'),
            "sslCert": fs.readFileSync('/etc/ssl/mongodb-cert.crt'),
            "sslCa": fs.readFileSync('/etc/ssl/mongodb-ca.crt')
          }
        }
      ;
    

    Source

    0 讨论(0)
提交回复
热议问题