sql >> Base de Datos >  >> NoSQL >> MongoDB

Conexión a MongoDB sobre SSL con Node.js

Paso 1:Obtenga MongoDB 3.0

Lo primero que debe saber es que MongoDB 3.0 y versiones posteriores solo admiten SSL listo para usar. Ubuntu no tiene 3.0 en los repositorios predeterminados, así es como se obtiene:

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 3.0.7 con su versión favorita.

Paso 2:obtener la clave privada, el certificado y los archivos PEM

El PEM contiene un Certificado de Clave Pública y su Clave Privada asociada. Estos archivos se pueden obtener con dólares reales de una autoridad de certificación o se pueden generar con OpenSSL de la siguiente manera:

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 usará 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 usar como archivo CA. NECESITARÁS LOS TRES.

Paso 3:Configurar MongoD

Vamos a suponer que copió estos archivos a su carpeta /etc/ssl/ donde pertenecen. Ahora abrimos nuestro archivo de configuración de 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 Mongo. Asumimos que este es su objetivo final (¿Por qué encriptarí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

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

sudo mongod --config /etc/mongod.conf

Paso 4:Pruebe la configuración de su servidor

Antes de jugar con las configuraciones de Node, asegurémonos de que la configuración de su servidor funcione correctamente conectándonos con mongo cliente de línea de comando:

mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates

A menos que el nombre de dominio en su certificado sea 127.0.0.1 o localhost , el --sslAllowInvalidHostnames la 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 node-mongodb-native paquete en su aplicación Node, deténgase inmediatamente y comience a usar Mongoose. No es tan dificil. Dicho esto, 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:[Opcionalmente] verifique 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. Se parecerá mucho a su archivo de Certificado, pero a menudo contendrá varios Certificados (que forman una cadena de confianza para verificar que un certificado es válido ). Si está usando un certificado autofirmado, puede usar 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 utilizado 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 --sslCAFile parámetro

Los servidores Mongo configurados con un CAFile requieren que los clientes posean un certificado válido Y la clave privada para el servidor. En el cliente de shell mongo, esto se hace pasando --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 estarás debilitando tu seguridad sin ningún beneficio real.

Paso 6.5:Configurar Node.JS/Mongoose

Aquí hay un par de trampas, así que tengan paciencia conmigo.

Primero, NECESITA tener node-mongodb-native 2.0 o después. Si está utilizando Mongoose, entonces NECESITA Mongoose 4.0 o después. Las versiones anteriores de Mongoose usan node-mongodb-native 1.* que no admite la validación de certificados en ninguna capacidad.

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 Node 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 probemos 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 obtiene errores de discrepancia de nombre de host/IP, corrija su certificado o anule todo este arduo 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