mongo/jstests/ssl/ssl_cert_selector_apple.js

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);
});
});
});