SERVER-118615 Use generated macos certificates in system CA tests (#47717)

GitOrigin-RevId: f9363dc6360e7e081ee62899d95001d173a7b9de
This commit is contained in:
Gabriel Marks 2026-02-10 11:08:19 -05:00 committed by MongoDB Bot
parent 4128fb8d53
commit aa38851a3d
12 changed files with 155 additions and 88 deletions

View File

@ -219,3 +219,6 @@ filters:
- "*get_exec_deferred_engine_choice*":
approvers:
- 10gen/query-execution
- "ssl*.yml":
approvers:
- 10gen/server-security

View File

@ -0,0 +1,23 @@
test_kind: js_test
# Runs the `ssl_linear` suite but uses the certificates generated at MacOS provision time,
# which are in the system certificate store. Only runs on MacOS.
selector:
roots:
- jstests/ssl_linear/*.js
# ssl tests start their own mongod's.
executor:
config:
shell_options:
nodb: ""
ssl: ""
sslAllowInvalidCertificates: ""
sslCAFile: /opt/x509/macos-trusted-ca.pem
sslPEMKeyFile: /opt/x509/macos-trusted-ca.pem
global_vars:
TestData:
setParameters:
logComponentVerbosity: "{network:2}"
setParametersMongos:
logComponentVerbosity: "{network:2}"

View File

@ -174,4 +174,5 @@ rules:
"selinux_rhel8_org",
"selinux_rhel9_org",
"selinux_rhel8_enterprise",
"ssl_linear_macos",
]

View File

@ -1118,6 +1118,7 @@ tasks:
"encrypt",
"ssl",
"patch_build",
"incompatible_mac",
]
commands:
- func: "do setup"
@ -1126,6 +1127,16 @@ tasks:
suite: ssl_linear
resmoke_jobs_max: 1
- <<: *task_template
name: ssl_linear_macos
tags: ["assigned_to_jira_team_server_security", "experimental"]
commands:
- func: "do setup"
- func: "run tests"
vars:
suite: ssl_linear_macos
resmoke_jobs_max: 1
- <<: *task_template
name: ssl_x509
tags:

View File

@ -31,6 +31,7 @@ buildvariants:
- name: run_unit_tests_8_way_split_TG
- name: .development_critical !.incompatible_community !.incompatible_mac
- name: .release_critical !.incompatible_community !.incompatible_mac !publish_packages
- name: ssl_linear_macos
- name: enterprise-macos-arm64
display_name: Enterprise macOS arm64
@ -58,6 +59,7 @@ buildvariants:
- name: run_unit_tests_8_way_split_TG
- name: .development_critical !.incompatible_mac
- name: .release_critical !.incompatible_mac !publish_packages
- name: ssl_linear_macos
- name: macos
display_name: macOS
@ -85,6 +87,7 @@ buildvariants:
- name: run_unit_tests_8_way_split_TG
- name: .development_critical !.incompatible_community !.incompatible_mac
- name: .release_critical !.incompatible_community !.incompatible_mac !publish_packages
- name: ssl_linear_macos
- name: enterprise-macos
display_name: Enterprise macOS
@ -112,3 +115,4 @@ buildvariants:
- name: run_unit_tests_8_way_split_TG
- name: .development_critical !.incompatible_mac
- name: .release_critical !.incompatible_mac !publish_packages
- name: ssl_linear_macos

View File

@ -1 +0,0 @@
{"certs":[{"Issuer":"self","Subject":{"CN":"Trusted MacOS Kernel Test CA"},"description":"CA for trusted MacOS client/server certificate chain.","extensions":{"basicConstraints":{"CA":true},"subjectAltName":{"DNS":"localhost","IP":"127.0.0.1"}},"keyfile":"macos_ca_key.pem","name":"macos-trusted-ca.pem"},{"Issuer":"macos-trusted-ca.pem","Subject":{"CN":"Trusted MacOS Kernel Test Client"},"description":"Client certificate for trusted MacOS chain.","extensions":{"extendedKeyUsage":["clientAuth"],"subjectAltName":{"DNS":"localhost","IP":"127.0.0.1"}},"name":"macos-trusted-client.pem","pkcs12":{"name":"macos-trusted-client.pfx","passphrase":"qwerty"}},{"Issuer":"macos-trusted-ca.pem","Subject":{"CN":"Trusted MacOS Kernel Test Server"},"description":"Server certificate for trusted MacOS chain.","extensions":{"extendedKeyUsage":["serverAuth"],"subjectAltName":{"DNS":"localhost","IP":"127.0.0.1"}},"name":"macos-trusted-server.pem","pkcs12":{"name":"macos-trusted-server.pfx","passphrase":"qwerty"}}],"global":{"Subject":{"C":"US","L":"New York City","O":"MongoDB","OU":"Kernel","ST":"New York"},"keyfile":"macos_key.pem"}}

View File

@ -1,8 +1,7 @@
/**
* Test that mkcert.py generates certificates deterministically, and that pkcs12 certificates, while
* not deterministic, can be generated. Uses the libs/x509/apple_certs.json and main_certs.json
* files, which are static copies of the JSON files generated by the x509:generate_main_certificates
* and x509:generate_apple_certificates bazel targets.
* not deterministic, can be generated. Uses the libs/x509/main_certs.json file, which is a static
* copy of the JSON file generated by the x509:generate_main_certificates bazel target.
*/
import {getPython3Binary} from "jstests/libs/python.js";
@ -22,7 +21,7 @@ assert.eq(runNonMongoProgram("openssl", "version"), 0);
jsTest.log.info(rawMongoProgramOutput(".*"));
const main_cert_json_file = "jstests/noPassthrough/libs/x509/main_certs.json";
const apple_cert_json_file = "jstests/noPassthrough/libs/x509/apple_certs.json";
const apple_cert_json_file = "x509/apple_certs.json";
const basedir = MongoRunner.dataPath + "certs/";
const genpath = basedir + "generated/";
mkdir(genpath);

View File

@ -1,9 +1,14 @@
// On OSX this test assumes that trusted-ca.pem has been added as a trusted
// certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildslave-cookbooks/commit/af7cabe5b6e0885902ebd4902f7f974b64cc8961
// On MacOS this test assumes that certificates exist at
// /opt/x509/macos-trusted-[ca|server|client].pem, and that /opt/x509/macos-trusted-ca.pem has
// been added as a trusted certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildhost-configuration/blob/1c1fcb51924cd4f1bc9eaf5db23f6e4365d6ba17/roles/macos/tasks/keychains.yml#L58-L87
// for details.
// To install trusted-ca.pem for local testing on OSX, invoke the following at a console:
// security add-trusted-cert -d bazel-bin/install-devcore/bin/x509/trusted-ca.pem
// To install certificates for local testing on OSX, invoke the following at a console:
// mkdir /opt/x509
// python x509/mkcert.py x509/apple_certs.json -o /opt/x509
// security add-trusted-cert -d /opt/x509/macos-trusted-ca.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-server.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-client.pem
import {getPython3Binary} from "jstests/libs/python.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
@ -11,29 +16,36 @@ import {ReplSetTest} from "jstests/libs/replsettest.js";
const HOST_TYPE = getBuildInfo().buildEnvironment.target_os;
jsTest.log("HOST_TYPE = " + HOST_TYPE);
let trustedCA = getX509Path("trusted-ca.pem");
let trustedServer = getX509Path("trusted-server.pem");
let trustedClient = getX509Path("trusted-client.pem");
if (HOST_TYPE == "macOS") {
// Ensure trusted-ca.pem is properly installed on MacOS hosts.
trustedCA = "/opt/x509/macos-trusted-ca.pem";
trustedServer = "/opt/x509/macos-trusted-server.pem";
trustedClient = "/opt/x509/macos-trusted-client.pem";
// Ensure trustedCA is properly installed on MacOS hosts.
// (MacOS is the only OS where it is installed outside of this test)
let exitCode = runProgram("security", "verify-cert", "-c", getX509Path("trusted-client.pem"));
let exitCode = runProgram("security", "verify-cert", "-c", trustedClient);
assert.eq(0, exitCode, "Check for proper installation of Trusted CA on MacOS host");
}
if (HOST_TYPE == "windows") {
assert.eq(0, runProgram(getPython3Binary(), "jstests/ssl_linear/windows_castore_cleanup.py"));
// OpenSSL backed imports Root CA and intermediate CA
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", trustedCA);
// SChannel backed follows Windows rules and only trusts the Root store in Local Machine and
// Current User.
runProgram("certutil.exe", "-addstore", "-f", "Root", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-f", "Root", trustedCA);
}
try {
const x509Options = {
tlsMode: "requireTLS",
tlsCertificateKeyFile: getX509Path("trusted-server.pem"),
tlsCAFile: getX509Path("trusted-ca.pem"),
tlsClusterFile: getX509Path("trusted-client.pem"),
tlsCertificateKeyFile: trustedServer,
tlsCAFile: trustedCA,
tlsClusterFile: trustedClient,
tlsAllowInvalidCertificates: "",
tlsWeakCertificateValidation: "",
};
@ -84,7 +96,7 @@ try {
const subShellArgs = ["mongo", "--nodb", "--eval", subShellCommandFormatter(rst)];
const retVal = runWithEnv(subShellArgs, {"SSL_CERT_FILE": getX509Path("trusted-ca.pem")});
const retVal = runWithEnv(subShellArgs, {"SSL_CERT_FILE": trustedCA});
assert.eq(retVal, 0, "mongo shell did not succeed with exit code 0");
rst.stopSet();

View File

@ -1,9 +1,14 @@
// On OSX this test assumes that trusted-ca.pem has been added as a trusted
// certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildslave-cookbooks/commit/af7cabe5b6e0885902ebd4902f7f974b64cc8961
// On MacOS this test assumes that certificates exist at
// /opt/x509/macos-trusted-[ca|server|client].pem, and that /opt/x509/macos-trusted-ca.pem has
// been added as a trusted certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildhost-configuration/blob/1c1fcb51924cd4f1bc9eaf5db23f6e4365d6ba17/roles/macos/tasks/keychains.yml#L58-L87
// for details.
// To install trusted-ca.pem for local testing on OSX, invoke the following at a console:
// security add-trusted-cert -d bazel-bin/install-devcore/bin/x509/trusted-ca.pem
// To install certificates for local testing on OSX, invoke the following at a console:
// mkdir /opt/x509
// python x509/mkcert.py x509/apple_certs.json -o /opt/x509
// security add-trusted-cert -d /opt/x509/macos-trusted-ca.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-server.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-client.pem
import {getPython3Binary} from "jstests/libs/python.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
@ -11,21 +16,28 @@ import {ReplSetTest} from "jstests/libs/replsettest.js";
const HOST_TYPE = getBuildInfo().buildEnvironment.target_os;
jsTest.log("HOST_TYPE = " + HOST_TYPE);
let trustedCA = getX509Path("trusted-ca.pem");
let trustedServer = getX509Path("trusted-server.pem");
let trustedClient = getX509Path("trusted-client.pem");
if (HOST_TYPE == "macOS") {
// Ensure trusted-ca.pem is properly installed on MacOS hosts.
trustedCA = "/opt/x509/macos-trusted-ca.pem";
trustedServer = "/opt/x509/macos-trusted-server.pem";
trustedClient = "/opt/x509/macos-trusted-client.pem";
// Ensure trustedCA is properly installed on MacOS hosts.
// (MacOS is the only OS where it is installed outside of this test)
let exitCode = runProgram("security", "verify-cert", "-c", getX509Path("trusted-client.pem"));
let exitCode = runProgram("security", "verify-cert", "-c", trustedClient);
assert.eq(0, exitCode, "Check for proper installation of Trusted CA on MacOS host");
}
if (HOST_TYPE == "windows") {
assert.eq(0, runProgram(getPython3Binary(), "jstests/ssl_linear/windows_castore_cleanup.py"));
// OpenSSL backed imports Root CA and intermediate CA
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", trustedCA);
// SChannel backed follows Windows rules and only trusts the Root store in Local Machine and
// Current User.
runProgram("certutil.exe", "-addstore", "-f", "Root", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-f", "Root", trustedCA);
}
try {
@ -34,7 +46,7 @@ try {
nodes: 1,
nodeOptions: {
tlsMode: "requireTLS",
tlsCertificateKeyFile: getX509Path("trusted-server.pem"),
tlsCertificateKeyFile: trustedServer,
setParameter: {tlsUseSystemCA: true},
},
host: "localhost",
@ -43,7 +55,7 @@ try {
replTest.startSet({
env: {
SSL_CERT_FILE: getX509Path("trusted-ca.pem"),
SSL_CERT_FILE: trustedCA,
},
});
@ -57,13 +69,13 @@ try {
let argv = ["mongo", url, "--eval", "db.runCommand({replSetGetStatus: 1})"];
if (url.endsWith("&ssl=true")) {
argv.push("--tls", "--tlsCertificateKeyFile", getX509Path("trusted-client.pem"));
argv.push("--tls", "--tlsCertificateKeyFile", trustedClient);
}
if (!_isWindows()) {
// On Linux we override the default path to the system CA store to point to our
// system CA. On Windows, this CA will have been added to the user's trusted CA list
argv.unshift("env", "SSL_CERT_FILE=" + getX509Path("trusted-ca.pem"));
argv.unshift("env", "SSL_CERT_FILE=" + trustedCA);
}
let ret = runMongoProgram(...argv);
return ret;

View File

@ -1,9 +1,14 @@
// On OSX this test assumes that trusted-ca.pem has been added as a trusted
// certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildhost-configuration/blob/f60ba13f506ef035d14e46fb5935f26ba3ca6bed/roles/macos/tasks/keychains.yml#L39-L100
// On MacOS this test assumes that certificates exist at
// /opt/x509/macos-trusted-[ca|server|client].pem, and that /opt/x509/macos-trusted-ca.pem has
// been added as a trusted certificate to the login keychain of the evergreen user. See,
// https://github.com/10gen/buildhost-configuration/blob/1c1fcb51924cd4f1bc9eaf5db23f6e4365d6ba17/roles/macos/tasks/keychains.yml#L58-L87
// for details.
// To install trusted-ca.pem for local testing on OSX, invoke the following at a console:
// security add-trusted-cert -d bazel-bin/install-devcore/bin/x509/trusted-ca.pem
// To install certificates for local testing on OSX, invoke the following at a console:
// mkdir /opt/x509
// python x509/mkcert.py x509/apple_certs.json -o /opt/x509
// security add-trusted-cert -d /opt/x509/macos-trusted-ca.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-server.pem
// security add-trusted-cert -d -r trustAsRoot /opt/x509/macos-trusted-client.pem
import {getPython3Binary} from "jstests/libs/python.js";
import {ReplSetTest} from "jstests/libs/replsettest.js";
@ -12,43 +17,50 @@ import {copyCertificateFile} from "jstests/ssl/libs/ssl_helpers.js";
const HOST_TYPE = getBuildInfo().buildEnvironment.target_os;
jsTest.log("HOST_TYPE = " + HOST_TYPE);
let trustedCA = getX509Path("trusted-ca.pem");
let trustedServer = getX509Path("trusted-server.pem");
let trustedClient = getX509Path("trusted-client.pem");
if (HOST_TYPE == "macOS") {
// Ensure trusted-ca.pem is properly installed on MacOS hosts.
trustedCA = "/opt/x509/macos-trusted-ca.pem";
trustedServer = "/opt/x509/macos-trusted-server.pem";
trustedClient = "/opt/x509/macos-trusted-client.pem";
// Ensure trustedCA is properly installed on MacOS hosts.
// (MacOS is the only OS where it is installed outside of this test)
let exitCode = runProgram("security", "verify-cert", "-c", getX509Path("trusted-client.pem"));
let exitCode = runProgram("security", "verify-cert", "-c", trustedClient);
assert.eq(0, exitCode, "Check for proper installation of Trusted CA on MacOS host");
}
if (HOST_TYPE == "windows") {
assert.eq(0, runProgram(getPython3Binary(), "jstests/ssl_linear/windows_castore_cleanup.py"));
// OpenSSL backed imports Root CA and intermediate CA
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-user", "-f", "CA", trustedCA);
// SChannel backed follows Windows rules and only trusts the Root store in Local Machine and
// Current User.
runProgram("certutil.exe", "-addstore", "-f", "Root", getX509Path("trusted-ca.pem"));
runProgram("certutil.exe", "-addstore", "-f", "Root", trustedCA);
}
const certDir = MongoRunner.toRealDir("$dataDir/ssl_with_system_ca_test/");
if (HOST_TYPE == "linux") {
mkdir(certDir);
clearRawMongoProgramOutput();
assert.eq(0, runProgram("openssl", "x509", "-hash", "-noout", "-in", getX509Path("trusted-ca.pem")));
assert.eq(0, runProgram("openssl", "x509", "-hash", "-noout", "-in", trustedCA));
let hash = rawMongoProgramOutput(".*");
jsTestLog(hash); // has form: "|sh<pid> <hash>\n"
hash = hash.trim().split(" ")[1];
copyCertificateFile(getX509Path("trusted-ca.pem"), `${certDir}/${hash}.0`);
copyCertificateFile(trustedCA, `${certDir}/${hash}.0`);
}
// Tests server ingress validation works if the server is configured to use system CA.
function testServerIngress() {
jsTestLog("Running testServerIngress");
// Start a mongod configured with sslPEMKeyFile = trusted-server.pem,
// and a system CA store containing trusted-ca.pem.
// Start a mongod configured with sslPEMKeyFile = trustedServer,
// and a system CA store containing trustedCA.
const serverOpts = {
tlsMode: "preferTLS",
tlsCertificateKeyFile: getX509Path("trusted-server.pem"),
tlsCertificateKeyFile: trustedServer,
tlsAllowInvalidHostnames: "",
waitForConnect: true,
setParameter: {tlsUseSystemCA: true},
@ -60,8 +72,8 @@ function testServerIngress() {
jsTestLog("Testing server ingress validates trusted client certificate");
let clientOpts = {
tls: {
certificateKeyFile: getX509Path("trusted-client.pem"),
CAFile: getX509Path("trusted-ca.pem"),
certificateKeyFile: trustedClient,
CAFile: trustedCA,
allowInvalidHostnames: true,
},
};
@ -89,13 +101,13 @@ function testServerIngress() {
function testServerEgress() {
jsTest.log("Running testServerEgress");
// Start a replica set with one mongod configured with sslPEMKeyFile = trusted-server.pem,
// and a system CA store containing trusted-ca.pem.
// Start a replica set with one mongod configured with sslPEMKeyFile = trustedServer,
// and a system CA store containing trustedCA.
const rst = new ReplSetTest({nodes: 1});
rst.startSet({
tlsMode: "preferTLS",
tlsCertificateKeyFile: getX509Path("trusted-server.pem"), // used on ingress
tlsClusterFile: getX509Path("trusted-client.pem"), // used on egress to node2
tlsCertificateKeyFile: trustedServer, // used on ingress
tlsClusterFile: trustedClient, // used on egress to node2
tlsAllowInvalidHostnames: "",
waitForConnect: true,
setParameter: {tlsUseSystemCA: true},
@ -109,8 +121,8 @@ function testServerEgress() {
let badNode = rst.add({
tlsMode: "preferTLS",
tlsCertificateKeyFile: getX509Path("server.pem"), // used on ingress, untrusted
tlsClusterFile: getX509Path("trusted-client.pem"), // used on egress to node1
tlsCAFile: getX509Path("trusted-ca.pem"),
tlsClusterFile: trustedClient, // used on egress to node1
tlsCAFile: trustedCA,
tlsAllowInvalidHostnames: "",
waitForConnect: true,
});
@ -127,9 +139,9 @@ function testServerEgress() {
// Add new node that uses a key trusted by the first node.
let goodNode = rst.add({
tlsMode: "preferTLS",
tlsCertificateKeyFile: getX509Path("trusted-server.pem"), // used on ingress, trusted
tlsClusterFile: getX509Path("trusted-client.pem"), // used on egress to node1
tlsCAFile: getX509Path("trusted-ca.pem"),
tlsCertificateKeyFile: trustedServer, // used on ingress, trusted
tlsClusterFile: trustedClient, // used on egress to node1
tlsCAFile: trustedCA,
tlsAllowInvalidHostnames: "",
waitForConnect: true,
});

View File

@ -1,6 +1,5 @@
load(":generate_certificates.bzl", "generate_certificates")
load(":main_certs_def.bzl", main_certs_def = "certs_def")
load(":apple_certs_def.bzl", apple_certs_def = "certs_def")
package(default_visibility = ["//visibility:public"])
@ -9,9 +8,3 @@ generate_certificates(
certs_def = main_certs_def,
static_inputs = glob(["static/**"]),
)
generate_certificates(
name = "generate_apple_certificates",
certs_def = apple_certs_def,
static_inputs = glob(["static/**"]),
)

View File

@ -1,76 +1,74 @@
# Definitions for certificates for MacOS-only certificate generation (the
# generate_apple_certificates target).
certs_def = json.encode({
{
"global": {
"Subject": {
"C": "US",
"ST": "New York",
"L": "New York City",
"O": "MongoDB",
"OU": "Kernel",
"OU": "Kernel"
},
"keyfile": "macos_key.pem",
"keyfile": "macos_key.pem"
},
"certs": [
{
"name": "macos-trusted-ca.pem",
"description": "CA for trusted MacOS client/server certificate chain.",
"Subject": {
"CN": "Trusted MacOS Kernel Test CA",
"CN": "Trusted MacOS Kernel Test CA"
},
"Issuer": "self",
"keyfile": "macos_ca_key.pem",
"extensions": {
"basicConstraints": {
"CA": True,
"CA": true
},
"subjectAltName": {
"DNS": "localhost",
"IP": "127.0.0.1",
},
},
"IP": "127.0.0.1"
}
}
},
{
"name": "macos-trusted-client.pem",
"description": "Client certificate for trusted MacOS chain.",
"Subject": {
"CN": "Trusted MacOS Kernel Test Client",
"CN": "Trusted MacOS Kernel Test Client"
},
"Issuer": "macos-trusted-ca.pem",
"pkcs12": {
"passphrase": "qwerty",
"name": "macos-trusted-client.pfx",
"name": "macos-trusted-client.pfx"
},
"extensions": {
"extendedKeyUsage": [
"clientAuth",
"clientAuth"
],
"subjectAltName": {
"DNS": "localhost",
"IP": "127.0.0.1",
},
},
"IP": "127.0.0.1"
}
}
},
{
"name": "macos-trusted-server.pem",
"description": "Server certificate for trusted MacOS chain.",
"Subject": {
"CN": "Trusted MacOS Kernel Test Server",
"CN": "Trusted MacOS Kernel Test Server"
},
"Issuer": "macos-trusted-ca.pem",
"pkcs12": {
"passphrase": "qwerty",
"name": "macos-trusted-server.pfx",
"name": "macos-trusted-server.pfx"
},
"extensions": {
"extendedKeyUsage": [
"serverAuth",
"serverAuth"
],
"subjectAltName": {
"DNS": "localhost",
"IP": "127.0.0.1",
},
},
},
],
})
"IP": "127.0.0.1"
}
}
}
]
}