mirror of https://github.com/mongodb/mongo
SERVER-94769 Expand testing of certificate selectors (#27942)
GitOrigin-RevId: edd87e3868164bdab0e9f8eded09539f88b74ecd
This commit is contained in:
parent
a304082e75
commit
0080b6e41c
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Tests various failure cases when using certificate selectors on Windows.
|
||||
*/
|
||||
import {
|
||||
requireSSLProvider,
|
||||
TRUSTED_SERVER_CERT,
|
||||
} from "jstests/ssl/libs/ssl_helpers.js";
|
||||
|
||||
const notFoundError = "failed to find cert";
|
||||
const badValueError = "Invalid certificate selector value";
|
||||
const startupFailureTestCases = [
|
||||
{selector: `thumbprint=DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF`, error: notFoundError},
|
||||
{selector: `subject=Unknown Test Client`, error: notFoundError},
|
||||
{selector: `thumbprint=LOL`, error: badValueError},
|
||||
{
|
||||
keyFile: TRUSTED_SERVER_CERT,
|
||||
clusterSelector: `thumbprint=DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF`,
|
||||
error: notFoundError
|
||||
},
|
||||
{
|
||||
keyFile: TRUSTED_SERVER_CERT,
|
||||
clusterSelector: `subject=Unknown Test Client`,
|
||||
error: notFoundError
|
||||
},
|
||||
{keyFile: TRUSTED_SERVER_CERT, clusterSelector: `thumbprint=LOL`, error: badValueError},
|
||||
];
|
||||
|
||||
function testStartupFails(testCase) {
|
||||
jsTestLog(`Running testStartupFails with test case: ${tojson(testCase)}`);
|
||||
const opts = {
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCertificateKeyFile: testCase.keyFile,
|
||||
tlsCertificateSelector: testCase.selector,
|
||||
tlsClusterCertificateSelector: testCase.clusterSelector,
|
||||
tlsAllowInvalidHostnames: "",
|
||||
setParameter: {tlsUseSystemCA: true},
|
||||
waitForConnect: true,
|
||||
};
|
||||
clearRawMongoProgramOutput();
|
||||
assert.throws(() => {
|
||||
MongoRunner.runMongod(opts);
|
||||
});
|
||||
assert(rawMongoProgramOutput().includes(testCase.error));
|
||||
}
|
||||
|
||||
requireSSLProvider('windows', function() {
|
||||
startupFailureTestCases.forEach(test => testStartupFails(test));
|
||||
});
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
// Test invalid SSL keyfile settings.
|
||||
|
||||
import {requireSSLProvider} from "jstests/ssl/libs/ssl_helpers.js";
|
||||
|
||||
function runTest(name, config, expect) {
|
||||
jsTest.log('Running test: ' + name);
|
||||
clearRawMongoProgramOutput();
|
||||
|
|
@ -38,3 +40,49 @@ runTest('expired', expired, validityMessage);
|
|||
// Test that startup fails with no certificate at all.
|
||||
const needKeyFile = 'need tlsCertificateKeyFile or certificateSelector when TLS is enabled';
|
||||
runTest('no-key-file', {tlsMode: 'requireTLS', tlsCAFile: 'jstests/libs/ca.pem'}, needKeyFile);
|
||||
|
||||
// Test that startup also fails if only tlsClusterFile is provided
|
||||
runTest('cluster-file-only',
|
||||
{
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCAFile: 'jstests/libs/ca.pem',
|
||||
tlsClusterFile: 'jstests/libs/client.pem'
|
||||
},
|
||||
needKeyFile);
|
||||
|
||||
requireSSLProvider(['windows', 'apple'], function() {
|
||||
const selector = "subject=Trusted Kernel Test Server";
|
||||
|
||||
// Test that startup also fails if only tlsClusterSelector is provided
|
||||
runTest('cluster-selector-only',
|
||||
{
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCAFile: 'jstests/libs/ca.pem',
|
||||
tlsClusterCertificateSelector: selector,
|
||||
},
|
||||
needKeyFile);
|
||||
|
||||
// Test that startup fails if both key file and cert selector are provided
|
||||
const keyFileAndSelector = {
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCAFile: 'jstests/libs/ca.pem',
|
||||
tlsCertificateKeyFile: 'jstests/libs/client.pem',
|
||||
tlsCertificateSelector: selector,
|
||||
};
|
||||
runTest(
|
||||
'keyfile-and-selector',
|
||||
keyFileAndSelector,
|
||||
"net.tls.certificateKeyFile is not allowed when net.tls.certificateSelector is specified");
|
||||
|
||||
// Test that startup fails if both cluster file and cluster cert selector are provided
|
||||
const clusterFileAndSelector = {
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCAFile: 'jstests/libs/ca.pem',
|
||||
tlsClusterFile: 'jstests/libs/client.pem',
|
||||
tlsClusterCertificateSelector: selector,
|
||||
};
|
||||
runTest(
|
||||
'cluster-keyfile-and-selector',
|
||||
clusterFileAndSelector,
|
||||
"net.tls.clusterFile is not allowed when net.tls.clusterCertificateSelector is specified");
|
||||
});
|
||||
|
|
@ -1,15 +1,130 @@
|
|||
/**
|
||||
* Validate that the shell can load certificates from the certificate store and connect to the
|
||||
* server.
|
||||
* Tests that the server can load its keys and certificates from the certificate store
|
||||
* through a selector, and that the correct keys are used for ingress/egress connections.
|
||||
*/
|
||||
|
||||
import {getPython3Binary} from "jstests/libs/python.js";
|
||||
import {ReplSetTest} from "jstests/libs/replsettest.js";
|
||||
import {
|
||||
requireSSLProvider,
|
||||
TRUSTED_CA_CERT,
|
||||
TRUSTED_SERVER_CERT
|
||||
TRUSTED_CLIENT_CERT,
|
||||
TRUSTED_SERVER_CERT,
|
||||
} from "jstests/ssl/libs/ssl_helpers.js";
|
||||
|
||||
const clientThumbprint = cat('jstests/libs/trusted-client.pem.digest.sha1');
|
||||
const serverThumbprint = cat('jstests/libs/trusted-server.pem.digest.sha1');
|
||||
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 testCases = [
|
||||
{
|
||||
selector: `thumbprint=${serverThumbprint}`,
|
||||
expectIngressKeyUsed: SERVER,
|
||||
expectEgressKeyUsed: SERVER
|
||||
},
|
||||
{
|
||||
selector: `thumbprint=${serverThumbprint}`,
|
||||
clusterSelector: `thumbprint=${clientThumbprint}`,
|
||||
expectIngressKeyUsed: SERVER,
|
||||
expectEgressKeyUsed: CLIENT,
|
||||
},
|
||||
{
|
||||
keyFile: TRUSTED_SERVER_CERT,
|
||||
clusterSelector: `thumbprint=${clientThumbprint}`,
|
||||
expectIngressKeyUsed: SERVER,
|
||||
expectEgressKeyUsed: CLIENT,
|
||||
},
|
||||
// TODO: SERVER-95653 uncomment this test case once bug is fixed
|
||||
/*{
|
||||
selector: `thumbprint=${serverThumbprint}`,
|
||||
clusterFile: TRUSTED_CLIENT_CERT,
|
||||
expectIngressKeyUsed: SERVER,
|
||||
expectEgressKeyUsed: CLIENT,
|
||||
},*/
|
||||
{
|
||||
selector: 'subject=Trusted Kernel Test Server',
|
||||
clusterSelector: 'subject=Trusted Kernel Test Client',
|
||||
expectIngressKeyUsed: SERVER,
|
||||
expectEgressKeyUsed: CLIENT,
|
||||
},
|
||||
];
|
||||
|
||||
function testServerSelectorKeyUsage(testCase) {
|
||||
jsTestLog(`Running testServerSelectorKeyUsage with test case: ${tojson(testCase)}`);
|
||||
|
||||
// Start a replica set with one mongod configured with the test case key file parameters
|
||||
// and a system CA store containing trusted-ca.pem.
|
||||
const rst = new ReplSetTest({nodes: 1});
|
||||
rst.startSet({
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCertificateKeyFile: testCase.keyFile,
|
||||
tlsCertificateSelector: testCase.selector,
|
||||
tlsClusterFile: testCase.clusterFile,
|
||||
tlsClusterCertificateSelector: testCase.clusterSelector,
|
||||
tlsAllowInvalidHostnames: "",
|
||||
tlsAllowConnectionsWithoutCertificates: "",
|
||||
waitForConnect: true,
|
||||
setParameter: {tlsUseSystemCA: true},
|
||||
});
|
||||
rst.initiate();
|
||||
rst.awaitReplication();
|
||||
let conn = rst.getPrimary();
|
||||
|
||||
jsTestLog("Testing server uses correct key on ingress");
|
||||
assert.soon(function() {
|
||||
return runMongoProgram('mongo',
|
||||
'--tls',
|
||||
'--tlsAllowInvalidHostnames',
|
||||
'--tlsCAFile',
|
||||
TRUSTED_CA_CERT,
|
||||
'--tlsCertificateKeyFile',
|
||||
TRUSTED_CLIENT_CERT,
|
||||
'--port',
|
||||
conn.port,
|
||||
'--eval',
|
||||
'quit()') === 0;
|
||||
}, "mongo did not initialize properly");
|
||||
|
||||
assert.soon(
|
||||
() => {
|
||||
const log = rawMongoProgramOutput();
|
||||
return log.search(testCase.expectIngressKeyUsed) !== -1;
|
||||
},
|
||||
`logfile did not contain expected peer certificate info: ${
|
||||
testCase.expectIngressKeyUsed}.\n` +
|
||||
"Log File Contents\n==============================\n" + rawMongoProgramOutput() +
|
||||
"\n==============================\n");
|
||||
|
||||
jsTestLog("Testing server uses correct key on egress");
|
||||
|
||||
// Add new node to test the other node's egress key
|
||||
let otherNode = rst.add({
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCertificateKeyFile: TRUSTED_SERVER_CERT,
|
||||
tlsCAFile: TRUSTED_CA_CERT,
|
||||
tlsAllowInvalidHostnames: "",
|
||||
setParameter: {tlsWithholdClientCertificate: true},
|
||||
waitForConnect: true,
|
||||
});
|
||||
|
||||
jsTestLog("Reinitiating replica set with one additional node");
|
||||
rst.reInitiate();
|
||||
rst.awaitSecondaryNodes();
|
||||
|
||||
assert.commandWorked(otherNode.adminCommand({clearLog: 'global'}));
|
||||
|
||||
// Verify node 1 can now connect to node 2
|
||||
jsTestLog("Forcing egress connection with replSetTestEgress...");
|
||||
assert.commandWorked(conn.adminCommand({replSetTestEgress: 1}));
|
||||
|
||||
checkLog.containsRelaxedJson(
|
||||
otherNode, 6723802, {peerSubjectName: testCase.expectEgressKeyUsed});
|
||||
|
||||
jsTestLog("Stopping the replica set...");
|
||||
rst.stopSet();
|
||||
}
|
||||
|
||||
requireSSLProvider('windows', function() {
|
||||
if (_isWindows()) {
|
||||
assert.eq(0,
|
||||
|
|
@ -19,43 +134,15 @@ requireSSLProvider('windows', function() {
|
|||
runProgram("certutil.exe", "-addstore", "-f", "Root", TRUSTED_CA_CERT);
|
||||
// Import a pfx file since it contains both a cert and private key and is easy to import
|
||||
// via command line.
|
||||
runProgram("certutil.exe",
|
||||
"-importpfx",
|
||||
"-f",
|
||||
"-p",
|
||||
"qwerty",
|
||||
"jstests\\libs\\trusted-client.pfx");
|
||||
const importPfx = function(pfxFile) {
|
||||
return runProgram("certutil.exe", "-importpfx", "-f", "-p", "qwerty", pfxFile);
|
||||
};
|
||||
assert.eq(0, importPfx("jstests\\libs\\trusted-client.pfx"));
|
||||
assert.eq(0, importPfx("jstests\\libs\\trusted-server.pfx"));
|
||||
}
|
||||
|
||||
try {
|
||||
const mongod = MongoRunner.runMongod({
|
||||
tlsMode: 'requireTLS',
|
||||
tlsCertificateKeyFile: TRUSTED_SERVER_CERT,
|
||||
setParameter: {tlsUseSystemCA: true},
|
||||
useHostname: false,
|
||||
});
|
||||
|
||||
const testWithCert = function(certSelector) {
|
||||
jsTest.log(`Testing with SSL cert ${certSelector}`);
|
||||
const conn = new Mongo(mongod.host, undefined, {
|
||||
tls: {
|
||||
certificateSelector: certSelector,
|
||||
}
|
||||
});
|
||||
assert.commandWorked(conn.getDB('admin').runCommand({buildinfo: 1}));
|
||||
};
|
||||
|
||||
const trusted_client_thumbprint = cat('jstests/libs/trusted-client.pem.digest.sha1');
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
testWithCert("thumbprint=" + trusted_client_thumbprint);
|
||||
});
|
||||
|
||||
assert.doesNotThrow(function() {
|
||||
testWithCert("subject=Trusted Kernel Test Client");
|
||||
});
|
||||
|
||||
MongoRunner.stopMongod(mongod);
|
||||
testCases.forEach(test => testServerSelectorKeyUsage(test));
|
||||
} finally {
|
||||
if (_isWindows()) {
|
||||
const trusted_ca_thumbprint = cat('jstests/libs/trusted-ca.pem.digest.sha1');
|
||||
|
|
|
|||
Loading…
Reference in New Issue