// Verify certificates and CAs between intra-cluster // and client->server communication using different CAs. import {ReplSetTest} from "jstests/libs/replsettest.js"; function testRS(opts, succeed) { const origSkipCheck = TestData.skipCheckDBHashes; const rsOpts = { // Use localhost so that SAN matches. useHostName: false, nodes: {node0: opts, node1: opts}, }; const rs = new ReplSetTest(rsOpts); rs.startSet(); if (succeed) { rs.initiate(); assert.commandWorked(rs.getPrimary().getDB('admin').runCommand({hello: 1})); } else { // By default, rs.initiate takes a very long time to timeout. We should shorten this // period, because we expect it to fail. ReplSetTest has both a static and local copy // of kDefaultTimeOutMS, so we must override both. const oldTimeout = ReplSetTest.kDefaultTimeoutMS; const shortTimeout = 2 * 60 * 1000; ReplSetTest.kDefaultTimeoutMS = shortTimeout; rs.timeoutMS = shortTimeout; // The rs.initiate will fail in an assert.soon, which would ordinarily trigger the hang // analyzer. We don't want that to happen, so we disable it here. MongoRunner.runHangAnalyzer.disable(); try { assert.throws(function() { rs.initiate(); }); } finally { ReplSetTest.kDefaultTimeoutMS = oldTimeout; MongoRunner.runHangAnalyzer.enable(); } TestData.skipCheckDBHashes = true; } rs.stopSet(); TestData.skipCheckDBHashes = origSkipCheck; } // The name "trusted" in these certificates is misleading. // They're just a separate trust chain from the ones without the name. // ca.pem signed client.pem and server.pem // trusted-ca.pem signed trusted-client.pem and trusted-server.pem const valid_options = { tlsMode: 'requireTLS', // Servers present trusted-server.pem to clients and each other for inbound connections. // Peers validate trusted-server.pem using trusted-ca.pem when making those connections. tlsCertificateKeyFile: 'jstests/libs/trusted-server.pem', tlsCAFile: 'jstests/libs/trusted-ca.pem', // Servers making outbound connections to other servers present server.pem to their peers // which their peers validate using ca.pem. tlsClusterFile: 'jstests/libs/server.pem', tlsClusterCAFile: 'jstests/libs/ca.pem', // SERVER-36895: IP based hostname validation with SubjectAlternateName tlsAllowInvalidHostnames: '', }; testRS(valid_options, true); const wrong_cluster_file = Object.assign({}, valid_options, {tlsClusterFile: valid_options.tlsCertificateKeyFile}); testRS(wrong_cluster_file, false); const wrong_key_file = Object.assign({}, valid_options, {tlsCertificateKeyFile: valid_options.tlsClusterFile}); testRS(wrong_key_file, false); const mongod = MongoRunner.runMongod(valid_options); assert(mongod, "Failed starting standalone mongod with alternate CA"); function testConnect(cert, succeed) { const mongo = runMongoProgram("mongo", "--host", "localhost", "--port", mongod.port, "--tls", "--tlsCAFile", valid_options.tlsCAFile, "--tlsCertificateKeyFile", cert, "--eval", ";"); // runMongoProgram returns 0 on success assert.eq(mongo === 0, succeed); } testConnect('jstests/libs/client.pem', true); testConnect('jstests/libs/trusted-client.pem', false); MongoRunner.stopMongod(mongod);