Подключение к MongoDB через SSL с узлом.Яш

Как подключиться к MongoDB-серверу через SSL с помощью узла.Яш?

Я прочитал источники нескольких драйверов (mongojs, mongodb-родной) и я уже давно гуглю, но, похоже, не могу найти никаких правильных учебников, руководств или документов.

3 ответов


Шаг 1: Получить MongoDB 3.0

первое, что вам нужно знать, это то, что SSL поддерживается только из коробки MongoDB 3.0 и более поздних версий. Ubuntu не имеет 3.0 в репозиториях по умолчанию, поэтому вот как вы его получите:

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-последняя стабильная версия на данный момент, но не стесняйтесь заменять 3.0.7 своим любимым выпуском.

Шаг 2: Получите закрытый ключ, сертификат и PEM-файлы

PEM содержит Сертификат открытого ключа и связанный с ним закрытый ключ. Эти файлы могут быть получены с IRL долларов из сертификата Authroity или генерируется с OpenSSL, как так:

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 будет использоваться как файл PEM, mongodb-cert.ключ-это файл закрытого ключа и mongodb-cert.crt - это файл сертификата, который также может использоваться в качестве файла CA. ВАМ ПОНАДОБЯТСЯ ВСЕ ТРИ.

Шаг 3: Настройка MongoD

мы будем считать, что вы скопировали эти файлы в папку/etc/ ssl/, где они принадлежат. Теперь мы открываем наш файл конфигурации MongoDB:

sudo vi /etc/mongod.conf

и измените раздел "# Сетевые интерфейсы " следующим образом:

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

обратите внимание: мы комментируем bindIp. Это позволяет внешним соединениям получить доступ к базе данных Mongo. Мы предполагаем, что это твоя конечная цель (зачем шифровать трафик на localhost?), но вы должны сделать это только после настройки правил авторизации для вашего MongoDB сервер.

CAFile также прокомментирован, поскольку он является необязательным. Я объясню, как настроить доверие центра сертификации в конце этого поста.

как всегда, вы должны перезапустить MongoDB, прежде чем изменения файла конфигурации вступят в силу:

sudo service mongod restart

НЕ УДАЛОСЬ ЗАПУСТИТЬ СЕРВЕР? Вы сами по себе, но, вероятно, есть проблема с файлами сертификатов. Вы можете проверить ошибки запуска, запустив mongod вручную:

sudo mongod --config /etc/mongod.conf

Шаг 4: Проверьте настройки сервера

прежде чем мы начнем возиться с конфигурациями узлов, давайте убедимся, что ваша настройка сервера работает правильно, подключившись к клиенту командной строки mongo:

mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates

если имя домена в сертификате не 127.0.0.1 или localhost, флаг --sslAllowInvalidHostnames необходим. Без него вы, вероятно, получите эту ошибку:

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

Шаг 5) Настройка Узла.JS / Мангуст

если вы используете пакет node-mongodb-native в приложении Node немедленно прекратите и начните использовать Мангуста. Это не так уж сложно. Тем не менее, Мангуст.connect () имеет практически тот же API, что и mongodb.connect (), поэтому замените соответствующим образом.

    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')
          }
        }
      ;

mongoose.connect(mongoUri, mongoOpt);

Шаг 6) [необязательно] Проверьте свои сертификаты через центр сертификации

для проверки сертификатов SSL необходимо получить файл CA(или пакет) из Центра сертификации. Это будет выглядеть очень похоже ваш файл сертификата, но часто будет содержать несколько сертификатов (которые образуют цепочки доверия, чтобы убедиться, что сертификат действителен). Если вы используете самозаверяющий сертификат, вы можете использовать mongodb-cert.crt как файл CA.

Вам также необходимо убедиться, что имя хоста вашего сервера MongoDB совпадает с именем, используемым для создания сертификата.

шаг 6.3) обновите конфигурацию mongod

sudo vi /etc/mongod.conf

и измените раздел " Сетевые интерфейсы#" вот так:

# 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

шаг 6.4) проверьте настройки сервера

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

клиенты Mongo могут передать файл CA, а также проверить, что они разговаривают с правильным сервером. Это делается с параметром --sslCAFile

серверы Mongo, настроенные с CAFile, требуют, чтобы клиенты имели действительный сертификат и закрытый ключ для сервера. В клиенте оболочки mongo это делается путем передачи в --sslPEMKeyFile параметр.

без файла PEM (который содержит сертификат сервера) вы можете увидеть эту ошибку:

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

сервер можно настроить для приема запросов от клиентов без PEM-файла, включив net.использование SSL.weakCertificateValidation, но вы будете ослабление безопасности никакой реальной выгоды.

Шаг 6.5) Настройка Узла.JS / Мангуст

здесь есть пара gotchas, так что потерпите со мной.

во-первых, вам нужно имейте node-mongodb-native 2.0 или более поздней версии. Если вы используете Мангуст, то вам нужен Мангуст 4.0 или более поздней версии. В предыдущих версиях Mongoose используется node-mongodb-native 1.* который не поддерживает проверку сертификатов в любом качестве.

во-вторых, в node-mongodb-native нет sslAllowInvalidHostnames или аналогичной опции. Это не то, что могут исправить разработчики node-mongodb-native (я бы уже), потому что собственная библиотека TLS доступна в узле 0.10.* не предлагает выбора для этого. В Узле 4.* и 5.* , есть опция checkServerIdentity, которая предлагает надежду, но переключение с исходной ветви узла на ветвь после ввода-вывода.слияние js может вызвать немного головной боли в настоящее время.

так давайте попробуем это:

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')
      }
    }
  ;

если вы получаете ошибки несоответствия имени хоста / IP, либо исправьте свой сертификат, либо отмените всю эту тяжелую работу, отключив 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')
      }
    }
  ;

источник: http://www.bainweb.com/2015/11/connecting-to-mongodb-over-tlsssl-with.html


как предложено в комментариях,node-mongodb-native есть все необходимое.

я получил его и работает, используя следующие:

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()
    });
  });
});

редактировать

вы также можете сделать ssl из мангуста:

mongoose.createConnection(connString, { server: { ssl: true }})

Если вы хотите аутентифицировать с помощью сертификата, используя node-mongodb-native:

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