MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Conectando-se ao MongoDB por SSL com Node.js

Etapa 1:obter o MongoDB 3.0


A primeira coisa que você precisa saber é que esse SSL só é compatível com o MongoDB 3.0 e posterior. O Ubuntu não tem 3.0 nos repositórios padrão, então aqui está como você o obtém:
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 é a versão estável mais recente a partir de agora, mas sinta-se à vontade para substituir a 3.0.7 pela sua versão favorita.

Etapa 2:obter a chave privada, o certificado e os arquivos PEM


O PEM contém um Certificado de Chave Pública e sua Chave Privada associada. Esses arquivos podem ser obtidos com dólares IRL de uma Autoridade de Certificação ou gerados com OpenSSL da seguinte forma:
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 será usado como arquivo PEM, mongodb-cert.key é o arquivo de chave privada e mongodb-cert.crt é arquivo de certificado que também pode ser usado como arquivo CA. VOCÊ VAI PRECISAR DE TODOS OS TRÊS.

Etapa 3:configurar o MongoD


Vamos supor que você copiou esses arquivos para sua pasta /etc/ssl/ onde eles pertencem. Agora abrimos nosso arquivo de configuração do MongoDB:
sudo vi /etc/mongod.conf

e modifique a seção "# interfaces de rede" assim:
# network interfaces
net:
  port: 27017
  #bindIp: 127.0.0.1
  ssl:
    mode: allowSSL
    PEMKeyFile: /etc/ssl/mongodb.pem
    #CAFile: /etc/ssl/mongodb-cert.crt

ATENÇÃO :estamos comentando bindIp . ISSO PERMITE CONEXÕES EXTERNAS para acessar seu banco de dados Mongo. Assumimos que este é seu objetivo final (Por que seu tráfego criptografado no localhost? ), mas você só deve fazer isso APÓS CONFIGURAR AS REGRAS DE AUTORIZAÇÃO para seu servidor MongoDB.

O CAFile também é comentado, pois é opcional. Explicarei como configurar a confiança da Autoridade de Certificação no final deste post.

Como sempre, você deve reiniciar o MongoDB antes que as alterações no arquivo de configuração entrem em vigor:
sudo service mongod restart

SEU SERVIDOR NÃO INICIOU? Você está sozinho, mas provavelmente há um problema com seus arquivos de certificado. Você pode verificar erros de inicialização executando mongod manualmente:
sudo mongod --config /etc/mongod.conf

Etapa 4:teste as configurações do seu servidor


Antes de mexer nas configurações do Node, vamos nos certificar de que a configuração do seu servidor está funcionando corretamente conectando-se com o mongo cliente de linha de comando:
mongo --ssl --sslAllowInvalidHostnames --sslAllowInvalidCertificates

A menos que o nome de domínio em seu certificado seja 127.0.0.1 ou localhost , o --sslAllowInvalidHostnames bandeira é necessária. Sem ele, você provavelmente receberá este erro:
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

Etapa 5:configurar o Node.JS/Mongoose


Se você estiver usando o node-mongodb-native pacote em seu aplicativo Node, pare imediatamente e comece a usar o Mongoose. Não é tão difícil. Dito isso, mongoose.connect() tem praticamente a mesma API que mongodb.connect() , então substitua adequadamente.
    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);

Etapa 6:[Opcionalmente] verifique seus certificados por meio de uma autoridade de certificação


Para validar seus Certificados SSL, você precisa obter uma CA (ou pacote ) da sua Autoridade de Certificação. Isso será muito parecido com o seu arquivo de certificado, mas geralmente conterá vários certificados (que forma uma cadeia de confiança para verificar se um certificado é válido ). Se você estiver usando um certificado autoassinado, poderá usar seu mongodb-cert.crt como um arquivo CA.

Você também precisará garantir que o nome de host do servidor MongoDB corresponda ao usado para criar o certificado.

Etapa 6.3:atualize seu mongod configuração

sudo vi /etc/mongod.conf

e modifique a seção "# interfaces de rede" assim:
# 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

Etapa 6.4:teste as configurações do seu servidor

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

Os clientes do Mongo também podem passar o arquivo CA para verificar se estão se comunicando com o servidor correto. Isso é feito com o --sslCAFile parâmetro

Os servidores Mongo configurados com um CAFile exigem que os clientes possuam um certificado válido E a chave privada para o servidor. No cliente shell do mongo, isso é feito passando o --sslPEMKeyFile parâmetro.

Sem um arquivo PEM (que contém o Certificado do servidor ), você pode ver este erro:
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

O servidor pode ser configurado para aceitar solicitações de clientes sem um arquivo PEM ativando net.ssl.weakCertificateValidation , mas você estará enfraquecendo sua segurança sem nenhum ganho real.

Etapa 6.5:configurar o Node.JS / Mongoose


Há algumas pegadinhas aqui, então tenha paciência comigo.

Primeiro, você PRECISA ter node-mongodb-native 2.0 ou mais tarde. Se você estiver usando o Mongoose, você PRECISA do Mongoose 4.0 ou mais tarde. Versões anteriores do Mongoose usam node-mongodb-native 1.* que não suporta a validação do Certificado em qualquer capacidade.

Em segundo lugar, não há sslAllowInvalidHostnames ou opção semelhante disponível em node-mongodb-native. Isso não é algo que node-mongodb-native os desenvolvedores podem corrigir (eu já teria ) porque a biblioteca TLS nativa disponível no Node 0.10.* não oferece nenhuma opção para isso. No nó 4.* e 5.*, há um checkServerIdentity opção que oferece esperança, mas mudar da ramificação Node original para a ramificação após a mesclagem do io.js pode causar um pouco de dor de cabeça no momento atual.

Então vamos tentar isso:
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 você estiver recebendo erros de incompatibilidade de nome de host/IP, corrija seu certificado ou negue todo esse trabalho árduo desativando 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