TLS/SSL 接続

Mongoose は、TLS/SSL 接続を必要とする MongoDB クラスタへの接続をサポートしています。 mongoose.connect() または接続文字列で tls オプションを true に設定するだけで、TLS/SSL を使用して MongoDB クラスタに接続できます。

mongoose.connect('mongodb://127.0.0.1:27017/test', { tls: true });

// Equivalent:
mongoose.connect('mongodb://127.0.0.1:27017/test?tls=true');

mongodb:// で始まる接続文字列の場合、tls オプションはデフォルトで false です。ただし、mongodb+srv:// で始まる接続文字列の場合、tls オプションはデフォルトで true です。そのため、srv 接続文字列を使用して MongoDB Atlas に接続する場合、TLS/SSL はデフォルトで有効になっています。

tls/ssl オプションを有効にせずに TLS/SSL 接続が必要な MongoDB クラスタに接続しようとすると、mongoose.connect() は以下のエラーで失敗します。

MongooseServerSelectionError: 接続127.0.0.1:27017 への接続が閉じられました NativeConnection.Connection.openUri (/node_modules/mongoose/lib/connection.js:800:32) ...

TLS/SSL 検証

デフォルトでは、Mongoose は 認証局 に対して TLS/SSL 証明書を検証し、TLS/SSL 証明書が有効であることを確認します。この検証を無効にするには、tlsAllowInvalidCertificates (または tlsInsecure) オプションを true に設定します。

mongoose.connect('mongodb://127.0.0.1:27017/test', {
  tls: true,
  tlsAllowInvalidCertificates: true,
});

ほとんどの場合、本番環境では TLS/SSL 検証を無効にするべきではありません。ただし、tlsAllowInvalidCertificates: true は、SSL 接続の問題をデバッグする際に役立つことがよくあります。 tlsAllowInvalidCertificates: true で MongoDB に接続できるが、tlsAllowInvalidCertificates: false では接続できない場合、Mongoose がサーバーに接続でき、サーバーが TLS/SSL を正しく使用するように構成されていることは確認できますが、証明書に何らかの問題があることがわかります。

たとえば、よくある問題は、以下のエラーメッセージです。

MongooseServerSelectionError: 最初の証明書を検証できません

このエラーは、多くの場合、自己署名 MongoDB 証明書 または MongoDB サーバーから送信された証明書が確立された認証局に登録されていないその他の状況が原因です。解決策は、tlsCAFile オプションを設定することです。これは、本質的に許可された SSL 証明書のリストを設定します。

await mongoose.connect('mongodb://127.0.0.1:27017/test', {
  tls: true,
  // For example, see https://medium.com/@rajanmaharjan/secure-your-mongodb-connections-ssl-tls-92e2addb3c89
  // for where the `rootCA.pem` file comes from.
  tlsCAFile: `${__dirname}/rootCA.pem`,
});

もう 1 つのよくある問題は、以下のエラーメッセージです。

MongooseServerSelectionError: ホスト名/IP が証明書の代替名と一致しません: ホスト: hostname1. は証明書の CN: hostname2 ではありません

SSL 証明書の 共通名 は、接続文字列のホスト名と一致する必要があります。 SSL 証明書が hostname2.mydomain.com の場合、接続文字列は hostname2.mydomain.com に接続する必要があり、hostname2.mydomain.com と同等の他のホスト名または IP アドレスには接続できません。レプリカセットの場合、これは SSL 証明書の共通名が マシンの hostname と一致する必要があることも意味します。この検証を無効にするには、tlsAllowInvalidHostnames オプションを true に設定します。

X.509 認証

X.509 認証 を使用している場合は、connect() オプションではなく、接続文字列にユーザー名を設定する必要があります。

// Do this:
const username = 'myusername';
await mongoose.connect(`mongodb://${encodeURIComponent(username)}@127.0.0.1:27017/test`, {
  tls: true,
  tlsCAFile: `${__dirname}/rootCA.pem`,
  authMechanism: 'MONGODB-X509',
});

// Not this:
await mongoose.connect('mongodb://127.0.0.1:27017/test', {
  tls: true,
  tlsCAFile: `${__dirname}/rootCA.pem`,
  authMechanism: 'MONGODB-X509',
  auth: { username },
});

MongoDB Atlas での X.509 認証

MongoDB Atlas では、X.509 証明書はルート CA 証明書ではなく、自己署名証明書のように tlsCAFile パラメータでは機能しません。 tlsCAFile パラメータを使用すると、次のようなエラーが発生します。

MongoServerSelectionError: ローカル発行者証明書を取得できません

X.509 認証を使用して MongoDB Atlas クラスタに接続するには、設定する正しいオプションは tlsCertificateKeyFile です。接続文字列はすでに authSourceauthMechanism を指定していますが、完全を期すために以下に connect() オプションとして含めています。

const url = 'mongodb+srv://xyz.mongodb.net/test?authSource=%24external&authMechanism=MONGODB-X509';
await mongoose.connect(url, {
  tls: true,
  // location of a local .pem file that contains both the client's certificate and key
  tlsCertificateKeyFile: '/path/to/certificate.pem',
  authMechanism: 'MONGODB-X509',
  authSource: '$external',
});

接続文字列オプションは、URL エスケープを正しく行う必要があります。