Meteor.js 使用 X509 证书身份验证连接到 Mongo

Meteor.js connection to Mongo using X509 certificate auth

我正在尝试在 Meteor.js 应用程序和 Mongo 服务器之间设置无密码身份验证。

为此,我需要向连接提供 pem 和 crt 文件。 MONGO_URL 连接字符串只需要 parameters about how to perform auth, but no references to files with certs. I assume, I need to pass in the cert file to connection as a parameter. Similar as described in here

如何在Meteor.js中完成?

基本上我想达到的效果相当于:

mongo mongo.example.com/example -ssl -sslPEMKeyFile client.pem --sslCAFile server.crt

然后按照描述 here

db.getSiblingDB("$external").auth(
  {
    mechanism: "MONGODB-X509",
    user: "CN=myName,OU=myOrgUnit,O=myOrg,L=myLocality,ST=myState,C=myCountry"
  }
)

这在使用 mogo 客户端时工作正常,但在 Meteor 中我到目前为止只了解我很可能需要使用下面的连接字符串(或类似的东西)

MONGO_URL=mongodb://mongo.example.com:27017/example?ssl=true&authSource=$external&authMechanism=MONGODB-X509

但问题仍然存在 - 如何将证书传递给连接?

更新:有 answer 使用本机 noddejs mongo 驱动程序处理问题。问题是 - 如何将其移植到 Meteor。

2015-12-31 更新:我接受了指向在定义集合时使用不同的连接对象的答案。分别为每个集合做这件事很麻烦,但这似乎是目前唯一可行的方法。此外,如果需要,可能可以创建一些 MySslCollection,其他人可以使用它来继承连接详细信息。这还没有经过测试。

更新的答案(1.4 版及更高版本)

正如另一个答案所指出的,从 1.4 版开始,此处的选项已更改,您现在可以调用

Mongo.setConnectionOptions({ ... });

详情请见the documentation

旧答案(1.4 版之前)

这是一个有趣的兔子洞...我想我已经找到一个 solution/workaround 来解决您的问题(可能还有其他问题)。

我的解决方法的快速描述是在创建集合时指定 mongodb 服务器选项。这必须在服务器代码上完成,只是为了避免分发您的 ssl key/cert。像这样:

new Mongo.Collection("collection_name", {
    connection: DDP.connect("mongodb://mongo.example.com:27017/example?ssl=true&authSource=$external&authMechanism=MONGODB-X509", {
        server: {
            sslCert:[CERT_CONTENTS],
            sslKey:[KEY_CONTENTS],
            sslValidate:false
        }
    })
});

骇人听闻的方法

既然您询问是否有一种方法可以在不向创建的每个集合添加选项的情况下执行此操作,我决定再看看。我没有测试过这些方法,但它们看起来很可靠,虽然很老套。

1) 在重新连接方法中使用未记录的选项参数 passthru 在连接状态上设置函数 运行。 https://github.com/meteor/meteor/blob/master/packages/ddp-client/livedata_connection.js#L996

Tracker.autorun(function () {
  var status = Meteor.status();
  if(status == 'failed')
    Meteor.reconnect({
      server: {
        sslCert:[CERT_CONTENTS],
        sslKey:[KEY_CONTENTS],
        sslValidate:false
      }
    });
});

2) Monkey 修补了默认的连接代码(这个我不太确定工作因为我没有花时间去理解 mongo 内部代码因为这实际上是首先设置的)。 https://github.com/meteor/meteor/blob/dc3cd6eb92f2bdd1bb44000cdd6abd1e5d0285b1/packages/mongo/remote_collection_driver.js

MongoInternals.defaultRemoteCollectionDriver = _.once(function () {
  var connectionOptions = {
    server: {
      sslCert:[CERT_CONTENTS],
      sslKey:[KEY_CONTENTS],
      sslValidate:false
    }
  };

  var mongoUrl = process.env.MONGO_URL;

  if (process.env.MONGO_OPLOG_URL) {
    connectionOptions.oplogUrl = process.env.MONGO_OPLOG_URL;
  }

  if (! mongoUrl)
    throw new Error("MONGO_URL must be set in environment");

  return new MongoInternals.RemoteCollectionDriver(mongoUrl, connectionOptions);
});

这些答案的旅程:

从您链接的答案开始,我找到了 Meteor 创建其 MongoDB 连接的位置:https://github.com/meteor/meteor/blob/dc3cd6eb92f2bdd1bb44000cdd6abd1e5d0285b1/packages/mongo/mongo_driver.js#L173

然后我找到了调用的地方:https://github.com/meteor/meteor/blob/3d2282d9ad0b570b913a70d215cd968019d912df/packages/mongo/remote_collection_driver.js#L4

追踪调用的位置使我了解到 Collections 实例化连接的事实:https://github.com/meteor/meteor/blob/15cdbca24888bfdff3ad43c1891a1719c09b3dc5/packages/mongo/collection.js#L102

我可以从那里看到一些选项可以覆盖没有指定选项的默认 Mongo 连接的使用。查看 Meteor 文档中的集合 http://docs.meteor.com/#/full/mongo_collection 显示:

Options

connection Object

The server connection that will manage this collection. Uses the default connection if not specified. Pass the return value of calling DDP.connect to specify a different server. Pass null to specify no connection. Unmanaged (name is null) collections cannot specify a connection.

所以查看 DDP.connect http://docs.meteor.com/#/full/ddp_connect we reach a dead end since it only takes a url... but wait... after searching through the code on github I can see that DDP.connect does take an options param: https://github.com/meteor/meteor/blob/master/packages/ddp-client/livedata_connection.js#L1641

的文档

我们的探索就此结束。

从 Meteor 1.4 开始,Mongo 可以通过调用配置连接选项:

Mongo.setConnectionOptions({ ... });

该函数必须在初始化期间尽早调用。一种方法是创建一个在其他包之前加载的本地 Meteor 包。有关详细信息,请参阅 https://forums.meteor.com/t/meteor-with-the-new-mongodb-3-2-1-compose-io/17763/10 和 Meteor GitHub 问题 #7455。

Meteor 1.4 发行说明:https://github.com/meteor/meteor/blob/devel/History.md#v14-2016-07-25

前面的两个答案都是正确的(, ),但是我想补充:

  1. 我在 Atmosphere (danwild:set-connection-options) 上放了一个非常简单的包来简化这个过程(或者至少提供一个具体的例子 howwhere Mongo.setConnectionOptions 可能实际使用,因为可用的文档很少)。
  2. 只是重申,如果您在项目中使用任何访问 Mongo 的包(例如 accounts-base),您必须确保在加载它们之前调用 Mongo.setConnectionOptions
    • 如何做到这一点?好问题。
    • 据我所知,没有官方方法可以确保您的包先于另一个加载(当然也支持另一种方式)。
    • 我见过的最简单的方法是编辑 .meteor/packages 中的包顺序,即将 danwild:set-connection-options 放在文件顶部。