Skip to content

Commit 4b02eb0

Browse files
DRIVERS-3434 Fix auth-ssl config for standalone (#761)
Co-authored-by: Jeffrey 'Alex' Clark <aclark@aclark.net>
1 parent 7dd3643 commit 4b02eb0

4 files changed

Lines changed: 110 additions & 11 deletions

File tree

.evergreen/orchestration/configs/servers/auth-ssl.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"id" : "standalonessl",
3+
"auth_key": "secret",
34
"name": "mongod",
45
"login": "bob",
56
"password": "pwd123",

.evergreen/orchestration/mongodb_runner.py

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,48 @@ def _normalize_path(path: Union[Path, str]) -> str:
6161
return re.sub("/cygdrive/(.*?)(/)", r"\1://", path, count=1)
6262

6363

64+
_MR_VERSION = "6.7.1"
65+
66+
67+
def _install_mongodb_runner() -> Path:
68+
"""Install mongodb-runner via npm with overrides to pin @mongodb-js/oidc-mock-provider.
69+
70+
npx does not support npm overrides, so we manage the install manually.
71+
@mongodb-js/oidc-mock-provider 0.13.8+ switched to yargs@18 (ESM-only), which
72+
cannot be require()'d on Node 16. Pinning to 0.13.7 keeps it on yargs@17.
73+
"""
74+
install_dir = TMPDIR / f"mongodb-runner-{_MR_VERSION}"
75+
ext = ".cmd" if PLATFORM == "win32" else ""
76+
runner_bin = install_dir / "node_modules" / ".bin" / f"mongodb-runner{ext}"
77+
if not runner_bin.exists():
78+
pkg = {
79+
"name": "mongodb-runner-wrapper",
80+
"version": "1.0.0",
81+
"dependencies": {"mongodb-runner": _MR_VERSION},
82+
"overrides": {"@mongodb-js/oidc-mock-provider": "0.13.7"},
83+
}
84+
install_dir.mkdir(parents=True, exist_ok=True)
85+
(install_dir / "package.json").write_text(json.dumps(pkg, indent=2))
86+
npm = shutil.which("npm")
87+
if npm is None:
88+
raise RuntimeError(
89+
"npm not found. Source init-node-and-npm-env.sh or install Node before running this script."
90+
)
91+
if PLATFORM == "win32":
92+
# .cmd files require shell=True on Windows; pass as string to avoid quoting issues.
93+
subprocess.run(
94+
f'"{npm}" install --silent',
95+
cwd=str(install_dir),
96+
check=True,
97+
shell=True,
98+
)
99+
else:
100+
subprocess.run(
101+
[npm, "install", "--silent"], cwd=str(install_dir), check=True
102+
)
103+
return runner_bin
104+
105+
64106
def start_mongodb_runner(opts, data):
65107
mo_home = Path(opts.mongo_orchestration_home)
66108
server_log = mo_home / "server.log"
@@ -80,20 +122,39 @@ def start_mongodb_runner(opts, data):
80122
binary = shutil.which("node")
81123
target = HERE / "devtools-shared/packages/mongodb-runner/bin/runner.js"
82124
target = _normalize_path(target)
125+
binary = _normalize_path(binary)
126+
cmd = f"{binary} {target} start --debug --config {config_file}"
83127
else:
84-
binary = shutil.which("npx")
85-
target = "-y mongodb-runner@^6.7.1"
86-
binary = _normalize_path(binary)
87-
cmd = f"{binary} {target} start --debug --config {config_file}"
88-
LOGGER.info(f"Running mongodb-runner using {binary} {target}...")
128+
binary = _normalize_path(_install_mongodb_runner())
129+
cmd = f"{binary} start --debug --config {config_file}"
130+
LOGGER.info(f"Running mongodb-runner using {binary}...")
131+
env = os.environ.copy()
132+
node_bin = shutil.which("node")
133+
if node_bin:
134+
try:
135+
node_ver = subprocess.check_output(
136+
[node_bin, "--version"], encoding="utf-8"
137+
).strip()
138+
node_major = int(node_ver.lstrip("v").split(".")[0])
139+
# Node < 19 doesn't expose WebCrypto as a global; mongodb driver needs it.
140+
# The flag was removed in Node 22, so only add it for Node 16-18.
141+
if node_major < 19:
142+
existing = env.get("NODE_OPTIONS", "")
143+
env["NODE_OPTIONS"] = (
144+
f"{existing} --experimental-global-webcrypto".strip()
145+
)
146+
except (subprocess.CalledProcessError, ValueError):
147+
pass
89148
try:
90149
with server_log.open("w") as fid:
91150
# Capture output while still streaming it to the file
92151
proc = subprocess.Popen(
93-
shlex.split(cmd),
152+
cmd if PLATFORM == "win32" else shlex.split(cmd),
94153
stdout=subprocess.PIPE,
95154
stderr=subprocess.STDOUT,
96155
text=True,
156+
env=env,
157+
shell=(PLATFORM == "win32"),
97158
)
98159
output_lines = []
99160
for line in proc.stdout:
@@ -109,7 +170,7 @@ def start_mongodb_runner(opts, data):
109170
LOGGER.error("server.log: %s", server_log.read_text())
110171
LOGGER.error(str(e))
111172
raise e
112-
LOGGER.info(f"Running mongodb-runner using {binary} {target}... done.")
173+
LOGGER.info(f"Running mongodb-runner using {binary}... done.")
113174
cluster_file = Path(config["runnerDir"]) / f"m-{config['id']}.json"
114175
server_info = json.loads(cluster_file.read_text())
115176
cluster_file.unlink()

.evergreen/tests/test-install-binaries.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,19 @@ SCRIPT_DIR=$(dirname ${BASH_SOURCE[0]})
77
pushd $SCRIPT_DIR/..
88

99
./install-node.sh
10-
npx -y mongodb-runner --help
10+
. ./init-node-and-npm-env.sh
11+
MR_INSTALL_DIR=$(mktemp -d)
12+
case "$(uname -s)" in
13+
CYGWIN*) MR_INSTALL_DIR=$(cygpath -m "$MR_INSTALL_DIR") ;;
14+
esac
15+
trap 'rm -rf "$MR_INSTALL_DIR"' EXIT
16+
printf '{"name":"t","version":"1.0.0","dependencies":{"mongodb-runner":"6.7.1"},"overrides":{"@mongodb-js/oidc-mock-provider":"0.13.7"}}' > "$MR_INSTALL_DIR/package.json"
17+
# Use a subshell + cd so npm install uses process.cwd() instead of --prefix,
18+
# which avoids MSYS2/Cygwin path translation issues on Windows.
19+
(cd "$MR_INSTALL_DIR" && npm install --silent)
20+
# Invoke node directly to bypass the .bin/ POSIX shim, which can fail on
21+
# Windows (CRLF shebang line or missing interpreter).
22+
node "$MR_INSTALL_DIR/node_modules/mongodb-runner/bin/runner.js" --help
1123

1224
source ./install-rust.sh
1325
rustup install stable

.evergreen/tests/test-mongodb-runner.sh

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,64 @@ pushd $SCRIPT_DIR/.. > /dev/null
1515
# shellcheck disable=SC2120
1616
function connect_mongodb() {
1717
local use_tls=false
18+
local use_auth=false
19+
local eval_cmd='db.runCommand({"ping":1})'
1820

1921
# Parse flags
2022
while [[ $# -gt 0 ]]; do
2123
case "$1" in
2224
--ssl) use_tls=true; shift ;;
25+
--auth) use_auth=true; shift ;;
26+
--eval-cmd)
27+
if [[ -z "${2:-}" ]]; then
28+
echo "Missing value for --eval-cmd"
29+
return 1
30+
fi
31+
eval_cmd="$2"
32+
shift 2
33+
;;
2334
*) echo "Unknown option: $1"; return 1 ;;
2435
esac
2536
done
2637

2738
URI="mongodb://localhost:27017/?directConnection=true&serverSelectionTimeoutMS=10000"
39+
if [[ "$use_auth" == "true" ]]; then
40+
URI="mongodb://bob:pwd123@localhost:27017/?directConnection=true&serverSelectionTimeoutMS=10000&authSource=admin"
41+
fi
2842
local TLS_OPTS=()
2943
if [[ "$use_tls" == "true" ]]; then
3044
TLS_OPTS+=("--tls" "--tlsCertificateKeyFile" "${DRIVERS_TOOLS}/.evergreen/x509gen/server.pem")
3145
TLS_OPTS+=("--tlsCAFile" "${DRIVERS_TOOLS}/.evergreen/x509gen/ca.pem")
3246
fi
47+
local result=0
3348
echo "Connecting to server..."
3449
# shellcheck disable=SC2068
35-
$MONGODB_BINARIES/mongosh "$URI" ${TLS_OPTS[@]:-} --eval "db.runCommand({\"ping\":1})"
50+
$MONGODB_BINARIES/mongosh "$URI" ${TLS_OPTS[@]:-} --eval "$eval_cmd" || result=$?
3651
echo "Connecting to server... done."
52+
return $result
3753
}
3854

3955
# Test for default, then test cli options.
4056
bash ./run-mongodb.sh start
4157
connect_mongodb
4258

4359
bash ./run-mongodb.sh start --topology standalone --auth
44-
connect_mongodb
60+
connect_mongodb --auth
4561

4662
bash ./run-mongodb.sh start --version 7.0 --topology replica_set --ssl
4763
connect_mongodb --ssl
4864

4965
bash ./run-mongodb.sh start --version latest --topology sharded_cluster --auth --ssl
50-
connect_mongodb --ssl
66+
connect_mongodb --ssl --auth
67+
68+
# Verify that auth is enforced when starting with AUTH=auth SSL=yes.
69+
# An unauthenticated connection must be rejected, and an authenticated one must succeed.
70+
AUTH=auth SSL=yes bash ./run-mongodb.sh start
71+
if connect_mongodb --ssl --eval-cmd 'db.adminCommand({listDatabases:1})' 2>/dev/null; then
72+
echo "ERROR: unauthenticated connection should have been rejected on an auth+ssl server"
73+
exit 1
74+
fi
75+
connect_mongodb --ssl --auth
5176

5277
# Ensure that we can use a downloaded mongodb directory.
5378
DOWNLOAD_DIR=mongodl_test

0 commit comments

Comments
 (0)