将Heroku App连接到Atlas MongoDB Cloud服务

时间:2017-02-10 12:16:11

标签: node.js mongodb ssl heroku mongoose

要解决这个问题:我是否需要在Heroku上获得 SSL 支持才能在 Heroku Atlas MongoDB Cloud 之间建立连接使用SSL? (TSL / SSL连接是访问Atlas MongoDB Cloud服务的requirement)。


我正在尝试将以node.js编写的Heroku应用程序连接到Atlas MongoDB Cloud托管的群集。

我当前的数据库托管在mLab(作为Heroku附加组件),用于通过mongoose访问集群的MongoDB URI是(使用 xxx 来省略机密信息):

MONGODB_URI="mongodb://xxx:xxx@xxx-a0.mlab.com:23266,xxx-a1.mlab.com:xxx/xxx?replicaSet=rs-xxx"

现在我已将我的数据从mLab迁移到Atlas MongoDB Cloud,我目前正在使用URI访问集群:

MONGODB_URI="mongodb://xxx:xxx@cluster0-shard-xxx.mongodb.net:xxx,cluster0-shard-xxx.mongodb.net:xxx,cluster0-shard-xxx.mongodb.net:xxx/xxx?replicaSet=xxx&ssl=true&authSource=admin"

在我的机器本地运行我的Heroku App时,我可以毫无问题地访问数据库。我也可以使用mongo shell连接到集群。

但是,在Heroku中运行App时,无法建立连接。在Browser JS控制台中,我收到503服务不可用消息。在heroku中,我收到错误:

no primary found in replica set

我知道Atlas MongoDB Cloud需要SSL连接,与mLab不同。在我的本地计算机中,我认为正在使用自签名证书成功连接到群集。

我的问题是:我是否需要在Heroku中获得SSL支持才能访问在Heroku和MongoDB Atlas之间建立安全连接?或者Heroku中的SSL支持仅需要客户端/ Heroku安全连接?

7 个答案:

答案 0 :(得分:11)

我认为可能会解决您的问题

免责声明:我既没使用Heroku也没使用MongoDB Atlas,但我正在调查它们。

根据我发现[1]的Github问题,如果您没有将MongoDB Atlas中的服务器IP地址列入白名单,您将收到该错误消息。

阅读MongoDB Atlas文档[2],我认为与Heroku dynos结合使用的唯一方法是将0.0.0.0/0(即所有地址)添加到MongoDB Atlas白名单中。

尝试一下,请报告您是否可以实例化连接。

在SSL

尝试回复SSL问题,我认为你不需要根据我读的内容在Heroku上启用它,虽然我不完全确定。

如果MongoDB服务器执行了证书验证,则用于连接它的Node.js代码必须如下所示(取自Node.js驱动程序文档[3]):

var MongoClient = require('mongodb').MongoClient,
  f = require('util').format,
  fs = require('fs');

// Read the certificates
var ca = [fs.readFileSync(__dirname + "/ssl/ca.pem")];
var cert = fs.readFileSync(__dirname + "/ssl/client.pem");
var key = fs.readFileSync(__dirname + "/ssl/client.pem");

// Connect validating the returned certificates from the server
MongoClient.connect("mongodb://localhost:27017/test?ssl=true", {
  server: {
      sslValidate:true
    , sslCA:ca
    , sslKey:key
    , sslCert:cert
    , sslPass:'10gen'
  }
}, function(err, db) {
  db.close();
});

如果MongoDB服务器没有检查任何SSL证书,您可以简单地使用如下代码(也来自Node.js驱动程序文档[3]):

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://localhost:27017/test?ssl=true", function(err, db) {
  db.close();
});

鉴于Atlas文档[4]包含以下用于从Node.js连接到它的示例代码,我认为您必须在Heroku上启用SSL:

var MongoClient = require('mongodb').MongoClient;

var uri = "mongodb://kay:myRealPassword@mycluster0-shard-00-00-wpeiv.mongodb.net:27017,mycluster0-shard-00-01-wpeiv.mongodb.net:27017,mycluster0-shard-00-02-wpeiv.mongodb.net:27017/admin?ssl=true&replicaSet=Mycluster0-shard-0&authSource=admin";
MongoClient.connect(uri, function(err, db) {
  db.close();
});
[1] https://github.com/meteor/meteor/issues/7492#issuecomment-236562860
[2] https://docs.atlas.mongodb.com/security-whitelist/
[3] https://mongodb.github.io/node-mongodb-native/2.2/tutorials/connect/ssl/
[4] https://docs.atlas.mongodb.com/driver-connection/#node-js-driver-example

答案 1 :(得分:4)

还必须向Mongo IP白名单中添加0.0.0.0/0,然后在Heroku上重新部署我的应用程序才能使其正常工作(在更改IP之前,抛出了CORS错误)。

答案 2 :(得分:3)

非常简单的解决方案!只需将地址“ 0.0.0.0/0”添加到mongo地图集的白名单IP中即可。

它将向全世界开放mongo地图集.....因此它不是用于生产,而是用于小型测试

答案 3 :(得分:2)

您可以使用以下命令找到Heroku的所有IP范围:

HEROKU_REGION=eu; sudo apt -qqy install curl jq 2>/dev/null 1>/dev/null; heroku regions --json 2>/dev/null | jq ".[] | select(.name==\"$HEROKU_REGION\") | .provider.region" | (REGION=$(cat); curl -s https://ip-ranges.amazonaws.com/ip-ranges.json |  jq ".prefixes[] | select(.region==$REGION) | .ip_prefix")

答案 4 :(得分:1)

我通过为数据库请求和其他TCP连接安装静态IP地址的插件(我使用Fixie Socks)解决了这个问题。 更多选项:https://elements.heroku.com/addons#network

答案 5 :(得分:0)

由于允许从任何地方访问都不安全并且IP范围可能会改变,因此我最终安装了附件QuotaGuard Static IP's(它为IP白名单提供了2个IP地址),所以SOCKS5 Proxy can be used with QGTunnel

QGTunnel应该下载并包含在代码库中

curl https://s3.amazonaws.com/quotaguard/qgtunnel-latest.tar.gz | tar xz

Procfile应该更新

web: bin/qgtunnel npm start

假设您要使用QGTunnel访问复制的MongoDB集群,该集群具有位于主机rs01.mongodb.net:52115rs02.mongodb.net:52115rs1.mongodb.net:52115上的3个副本。对于此配置,您将需要为transparent mode中端口52115上的每个主机创建3个单独的隧道。完成此操作后,QGTunnel将更改DNS解析过程,以将这些主机名解析为适当的回送地址,并自动执行复制群集的自动发现。

答案 6 :(得分:0)

登录云 MongoDB 站点并进入网络访问,点击添加 IP 地址,然后点击允许从任何地方访问即可

enter image description here