Saltar al contenido

Conexión a MongoDB a través de SSL con Node.js

Nuestro team redactor ha estado largas horas investigando respuestas a tus interrogantes, te brindamos la resolución así que nuestro objetivo es resultarte de gran ayuda.

Solución:

Paso 1: Obtenga MongoDB 3.0

Lo primero que debe saber es que SSL solo es compatible con MongoDB 3.0 y versiones posteriores. Ubuntu no tiene 3.0 en los repositorios predeterminados, así que así es como lo obtienes:

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 es la última versión estable a partir de ahora, pero no dude en sustituir la 3.0.7 por su versión favorita.

Paso 2: Obtenga archivos de clave privada, certificado y PEM

El PEM contiene un certificado de clave pública y su clave privada asociada. Estos archivos pueden obtenerse con dólares IRL de un certificado de autenticación o generarse con OpenSSL así:

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 se utilizará como archivo PEM, mongodb-cert.key es el archivo de clave privada y mongodb-cert.crt es el archivo de certificado que también se puede utilizar como archivo CA. USTED NECESITARÁ LOS TRES DE ESTOS.

Paso 3: configurar MongoD

Vamos a suponer que copió estos archivos en su carpeta / etc / ssl / donde pertenecen. Ahora abrimos nuestro archivo de configuración MongoDB:

sudo vi /etc/mongod.conf

y modifique la sección “# interfaces de red” así:

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

TENGA EN CUENTA: estamos comentando bindIp. ESTO PERMITE CONEXIONES EXTERNAS para acceder a su base de datos de Mongo. Suponemos que este es su objetivo final (¿Por qué cifraría su tráfico en localhost?), pero solo debe hacer esto DESPUÉS DE CONFIGURAR LAS REGLAS DE AUTORIZACIÓN para su servidor MongoDB.

El CAFile también está comentado ya que es opcional. Explicaré cómo configurar la confianza de la autoridad de certificación al final de esta publicación.

Como siempre, debe reiniciar MongoDB antes de que los cambios en el archivo de configuración surtan efecto:

sudo service mongod restart

¿FALLÓ SU SERVIDOR AL INICIAR? Está solo, pero probablemente haya un problema con sus archivos de certificado. Puede comprobar los errores de inicio ejecutando mongod a mano:

sudo mongod --config /etc/mongod.conf

Paso 4: prueba la configuración de tu servidor

Antes de empezar a jugar con las configuraciones de nodo, asegurémonos de que la configuración de su servidor esté funcionando correctamente conectándose con el mongo cliente de línea de comandos:

mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates

A menos que el nombre de dominio en su certificado sea 127.0.0.1 o localhost, los --sslAllowInvalidHostnames bandera es necesaria. Sin él, probablemente obtendrá este 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

Paso 5: Configurar Node.JS / Mongoose

Si está utilizando el node-mongodb-native paquete en su aplicación Node, deténgase inmediatamente y comience a usar Mongoose. No es tan dificil. Dicho eso mongoose.connect() tiene prácticamente la misma API que mongodb.connect(), así que sustitúyalo apropiadamente.

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

Paso 6: [Optionally] verificar sus Certificados a través de una Autoridad de Certificación

Para validar sus certificados SSL, debe obtener una CA (o paquete) archivo de su autoridad de certificación. Esto se parecerá mucho a su archivo de certificado, pero a menudo contendrá varios certificados (que forma una cadena de confianza para verificar que un certificado es válido). Si está utilizando un certificado autofirmado, puede utilizar su mongodb-cert.crt como un archivo CA.

También deberá asegurarse de que el nombre de host de su servidor MongoDB coincida con el que se usó para crear el certificado.

Paso 6.3: actualice su mongod configuración

sudo vi /etc/mongod.conf

y modifique la sección “# interfaces de red” así:

# 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

Paso 6.4: Pruebe la configuración de su servidor

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

Los clientes de Mongo también pueden pasar el archivo CA para verificar que están hablando con el servidor correcto. Esto se hace con el --sslCAFile parámetro

Los servidores Mongo configurados con un CAFile requieren que los clientes posean un certificado válido Y la clave privada del servidor. En el cliente de shell mongo, esto se hace pasando el --sslPEMKeyFile parámetro.

Sin un archivo PEM (que contiene el certificado del servidor), es posible que vea este 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

El servidor se puede configurar para aceptar solicitudes de clientes sin un archivo PEM habilitando net.ssl.weakCertificateValidation, pero debilitará su seguridad sin una ganancia real.

Paso 6.5: Configurar Node.JS / Mongoose

Hay un par de trampas aquí, así que tengan paciencia conmigo.

Primero, NECESITAS tener node-mongodb-native2.0 o después. Si está usando Mongoose, entonces NECESITA Mongoose 4.0 o después. Las versiones anteriores de Mongoose utilizan node-mongodb-native1.* que no admite la validación de certificados de ninguna manera.

En segundo lugar, no hay sslAllowInvalidHostnames o una opción similar disponible en node-mongodb-native. Esto no es algo que node-mongodb-native los desarrolladores pueden arreglar (Ya lo habría hecho) porque la biblioteca TLS nativa disponible en el nodo 0.10. * no ofrece ninguna opción para esto. En el nodo 4. * y 5. *, hay un checkServerIdentity opción que ofrece esperanza, pero cambiar de la rama de Nodo original a la rama después de la fusión de io.js puede causar un poco de dolor de cabeza en este momento.

Así que intentemos esto:

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

Si recibe errores de no coincidencia de nombre de host / IP, corrija su certificado o niegue todo este trabajo deshabilitando 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')
      
    
  ;

Fuente

Como se sugiere en los comentarios, el node-mongodb-native tiene todo lo necesario.

Lo puse en funcionamiento usando lo siguiente:

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

Editar

También puedes hacer ssl desde mongoose:

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

Si desea autenticarse mediante un certificado, utilice 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();
);

Reseñas y valoraciones del artículo

Agradecemos que quieras sostener nuestro análisis ejecutando un comentario o dejando una valoración te damos la bienvenida.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *