要解决这个问题:我是否需要在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安全连接?
答案 0 :(得分:11)
免责声明:我既没使用Heroku也没使用MongoDB Atlas,但我正在调查它们。
根据我发现[1]的Github问题,如果您没有将MongoDB Atlas中的服务器IP地址列入白名单,您将收到该错误消息。
阅读MongoDB Atlas文档[2],我认为与Heroku dynos结合使用的唯一方法是将0.0.0.0/0
(即所有地址)添加到MongoDB Atlas白名单中。
尝试一下,请报告您是否可以实例化连接。
尝试回复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:52115
,rs02.mongodb.net:52115
和rs1.mongodb.net:52115
上的3个副本。对于此配置,您将需要为transparent mode中端口52115上的每个主机创建3个单独的隧道。完成此操作后,QGTunnel将更改DNS解析过程,以将这些主机名解析为适当的回送地址,并自动执行复制群集的自动发现。
答案 6 :(得分:0)