MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Connessione a MongoDB su SSL con Node.js

Passaggio 1:ottieni MongoDB 3.0

La prima cosa che devi sapere è che SSL è supportato immediatamente solo da MongoDB 3.0 e versioni successive. Ubuntu non ha 3.0 nei repository predefiniti, quindi ecco come lo ottieni:

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

La 3.0.7 è l'ultima versione stabile al momento, ma sentiti libero di sostituire la 3.0.7 con la tua versione preferita.

Fase 2:ottieni la chiave privata, il certificato e i file PEM

Il PEM contiene un certificato di chiave pubblica e la chiave privata associata. Questi file possono essere ottenuti con dollari IRL da un'autorità di certificazione o generati con OpenSSL in questo modo:

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 verrà utilizzato come file PEM, mongodb-cert.key è il file della chiave privata e mongodb-cert.crt è il file del certificato che può essere utilizzato anche come file CA. AVRAI BISOGNO DI TUTTI E TRE QUESTI.

Fase 3:configura MongoD

Assumiamo che tu abbia copiato questi file nella tua cartella /etc/ssl/ a cui appartengono. Ora apriamo il nostro file di configurazione MongoDB:

sudo vi /etc/mongod.conf

e modifica la sezione "# interfacce di rete" in questo modo:

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

SI PREGA DI NOTARE :stiamo commentando bindIp . QUESTO PERMETTE A CONNESSIONI ESTERNE di accedere al tuo database Mongo. Partiamo dal presupposto che questo sia il tuo obiettivo finale (Perché dovresti crittografare il traffico su localhost? ), ma dovresti farlo solo DOPO AVER IMPOSTATO LE REGOLE DI AUTORIZZAZIONE per il tuo server MongoDB.

Anche il CAFile è commentato in quanto facoltativo. Spiegherò come impostare l'attendibilità dell'autorità di certificazione alla fine di questo post.

Come sempre, è necessario riavviare MongoDB prima che le modifiche al file di configurazione abbiano effetto:

sudo service mongod restart

IL TUO SERVER NON SI AVVIENE? Sei da solo, ma probabilmente c'è un problema con i file del certificato. Puoi controllare gli errori di avvio eseguendo mongod manualmente:

sudo mongod --config /etc/mongod.conf

Fase 4:verifica le impostazioni del server

Prima di andare a pasticciare con le configurazioni di Node, assicuriamoci che la configurazione del tuo server funzioni correttamente collegandoti con mongo client della riga di comando:

mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates

A meno che il nome di dominio sul tuo certificato non sia 127.0.0.1 o localhost , il --sslAllowInvalidHostnames la bandiera è necessaria. Senza di esso, probabilmente otterrai questo errore:

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

Passaggio 5:Configura Node.JS / Mongoose

Se stai usando il node-mongodb-native pacchetto nella tua applicazione Node, fermati immediatamente e inizia a usare Mongoose. Non è così difficile. Detto questo, mongoose.connect() ha praticamente la stessa API di mongodb.connect() , quindi sostituisci in modo appropriato.

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

Passaggio 6:[facoltativamente] verifica i tuoi certificati tramite un'autorità di certificazione

Per convalidare i tuoi certificati SSL, devi ottenere una CA (o bundle ) dalla tua autorità di certificazione. Questo assomiglierà molto al tuo file di certificato, ma spesso conterrà più certificati (che forma una catena di fiducia per verificare che un certificato sia valido ). Se stai utilizzando un certificato autofirmato, puoi utilizzare il tuo mongodb-cert.crt come un file CA.

Dovrai anche assicurarti che il nome host del tuo server MongoDB corrisponda a quello utilizzato per creare il certificato.

Passaggio 6.3:aggiorna il tuo mongod configurazione

sudo vi /etc/mongod.conf

e modifica la sezione "# interfacce di rete" in questo modo:

# 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

Passaggio 6.4:verifica le impostazioni del server

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

I client Mongo possono anche passare il file CA per verificare che stiano parlando con il server corretto. Questo viene fatto con il --sslCAFile parametro

I server Mongo configurati con un CAFile richiedono che i client possiedano un certificato valido AND la chiave privata per il server. Nel client mongo shell, questo viene fatto passando il --sslPEMKeyFile parametro.

Senza un file PEM (che contiene il certificato del server ), potresti visualizzare questo errore:

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

Il server può essere configurato per accettare richieste dai client senza un file PEM abilitando net.ssl.weakCertificateValidation , ma indebolirai la tua sicurezza senza alcun reale vantaggio.

Passaggio 6.5:Configura Node.JS / Mongoose

Ci sono un paio di trucchi qui, quindi abbi pazienza.

Innanzitutto, DEVI avere node-mongodb-native 2.0 o più tardi. Se stai usando Mongoose, allora HAI BISOGNO di Mongoose 4.0 o più tardi. Le versioni precedenti di Mongoose utilizzano node-mongodb-native 1.* che non supporta la convalida del certificato in alcun modo.

In secondo luogo, non ci sono sslAllowInvalidHostnames o un'opzione simile disponibile in node-mongodb-native. Questo non è qualcosa che node-mongodb-native gli sviluppatori possono risolvere (avrei già fatto ) perché la libreria TLS nativa disponibile nel nodo 0.10.* non offre alcuna opzione per questo. Nei nodi 4.* e 5.* è presente un checkServerIdentity opzione che offre speranza, ma il passaggio dal ramo Node originale al ramo dopo l'unione io.js può causare un po' di mal di testa al momento attuale.

Quindi proviamo questo:

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

Se ricevi errori di mancata corrispondenza nome host/IP, correggi il certificato o annulla tutto questo duro lavoro disabilitando 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')
      }
    }
  ;

Fonte