mirror of https://github.com/mongodb/mongo
125 lines
5.7 KiB
JavaScript
125 lines
5.7 KiB
JavaScript
/**
|
|
* Validate that the server can load certificates from the
|
|
* Secure Transport certificate store.
|
|
*
|
|
* Don't actually try to connect via SSL, because without interactivity,
|
|
* we won't be able to click on the "Allow" button that Apple insists on presenting.
|
|
*
|
|
* Just verify that we can startup when we select a valid cert,
|
|
* and fail when we do not.
|
|
*/
|
|
|
|
import {requireSSLProvider} from "jstests/ssl/libs/ssl_helpers.js";
|
|
|
|
// Due to a race condition in shutdown-during-startup, this test sometimes produces core dumps.
|
|
// TODO SERVER-99909 Remove this once shutdown-during-startup issues are fixed.
|
|
TestData.cleanUpCoreDumpsFromExpectedCrash = true;
|
|
|
|
requireSSLProvider("apple", function () {
|
|
const CLIENT = "CN=Trusted Kernel Test Client,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
|
|
const SERVER = "CN=Trusted Kernel Test Server,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
|
|
const INVALID = null;
|
|
|
|
function getCertificateSHA1BySubject(subject) {
|
|
clearRawMongoProgramOutput();
|
|
// security find-certificate prints out info about certificates matching the given search
|
|
// criteria. In this case, we use -c, matching common name, and -Z, which includes SHA-1 and
|
|
// SHA-256 thumbprints in the output.
|
|
assert.eq(0, runNonMongoProgram("security", "find-certificate", "-c", subject, "-Z"));
|
|
const out = rawMongoProgramOutput(".*");
|
|
|
|
const kSearchStr = "SHA-1 hash: ";
|
|
const kHashHexitLen = 40;
|
|
|
|
const searchIdx = out.indexOf(kSearchStr);
|
|
assert.neq(searchIdx, -1, "SHA-1 hash not found in command output!");
|
|
|
|
return out.substr(searchIdx + kSearchStr.length, kHashHexitLen);
|
|
}
|
|
|
|
// Using the thumbprint of the certificate stored in the keychain should always work as a
|
|
// selector. Uppercase everything so we don't fail on unmatching case.
|
|
const trusted_server_thumbprint = getCertificateSHA1BySubject("Trusted Kernel Test Server").toUpperCase();
|
|
const trusted_client_thumbprint = getCertificateSHA1BySubject("Trusted Kernel Test Client").toUpperCase();
|
|
|
|
const expected_server_thumbprint = cat("jstests/libs/trusted-server.pem.digest.sha1").toUpperCase();
|
|
const expected_client_thumbprint = cat("jstests/libs/trusted-client.pem.digest.sha1").toUpperCase();
|
|
|
|
// If we fall into this case, our trusted certificates are not installed on the machine's
|
|
// certificate keychain. This probably means that certificates have just been renewed, but have
|
|
// not been installed in MacOS machines yet.
|
|
if (
|
|
expected_server_thumbprint !== trusted_server_thumbprint ||
|
|
expected_client_thumbprint !== trusted_client_thumbprint
|
|
) {
|
|
jsTest.log.error(
|
|
"macOS host has an unexpected version of the trusted server certificate (jstests/libs/trusted-server.pem) or trusted client certificate (jstests/libs/trusted-client.pem) installed.",
|
|
);
|
|
jsTest.log.error(
|
|
"Expecting server thumbprint: " + expected_server_thumbprint + ", got: " + trusted_server_thumbprint,
|
|
);
|
|
jsTest.log.error(
|
|
"Expecting client thumbprint: " + expected_client_thumbprint + ", got: " + trusted_client_thumbprint,
|
|
);
|
|
}
|
|
|
|
const testCases = [
|
|
{selector: "thumbprint=" + trusted_server_thumbprint, name: SERVER},
|
|
{selector: "subject=Trusted Kernel Test Server", name: SERVER},
|
|
{selector: "thumbprint=" + trusted_client_thumbprint, name: CLIENT},
|
|
{selector: "subject=Trusted Kernel Test Client", name: CLIENT},
|
|
{selector: "thumbprint=DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", name: INVALID},
|
|
{selector: "subject=Unknown Test Client", name: INVALID},
|
|
];
|
|
|
|
function test(cert, cluster) {
|
|
jsTest.log.info(`Testing with:`);
|
|
jsTest.log.info(` Cert Name: ${cert.name}, Selector: ${cert.selector}`);
|
|
jsTest.log.info(` Cluster Name: ${cluster.name}, Selector: ${cluster.selector}`);
|
|
const opts = {
|
|
tlsMode: "requireTLS",
|
|
tlsCertificateSelector: cert.selector,
|
|
tlsClusterCertificateSelector: cluster.selector,
|
|
waitForConnect: false,
|
|
setParameter: {logLevel: "1", tlsUseSystemCA: true},
|
|
};
|
|
clearRawMongoProgramOutput();
|
|
const mongod = MongoRunner.runMongod(opts);
|
|
|
|
assert.soon(
|
|
function () {
|
|
const log = rawMongoProgramOutput(".*");
|
|
if (cert.name === null || cluster.name === null) {
|
|
// Invalid search criteria should fail.
|
|
return log.search("Certificate selector returned no results") >= 0;
|
|
}
|
|
// Valid search criteria should show our Subject Names.
|
|
const certOK = log.search('\"name\":\"' + cert.name) >= 0;
|
|
const clusOK = log.search('\"name\":\"' + cluster.name) >= 0;
|
|
return certOK && clusOK;
|
|
},
|
|
"Starting Mongod with " + tojson(opts),
|
|
60000,
|
|
);
|
|
|
|
try {
|
|
MongoRunner.stopMongod(mongod);
|
|
} catch (e) {
|
|
// Depending on timing, exitCode might be 0, 1, or -9.
|
|
// All that matters is that it dies, resmoke will tell us if that failed.
|
|
// So just let it go, the exit code never bothered us anyway.
|
|
}
|
|
}
|
|
|
|
// Test each possible combination of server/cluster certificate selectors. Make sure we only use
|
|
// the trusted-server certificate as the server certificate, and only use the trusted-client
|
|
// certificate as the cluster certificate.
|
|
testCases.forEach((cert) => {
|
|
if (cert.name === CLIENT) return;
|
|
testCases.forEach((cluster) => {
|
|
if (cluster.name === SERVER) return;
|
|
test(cert, cluster);
|
|
});
|
|
});
|
|
});
|