fix: harden proxied client installation
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s

This commit is contained in:
2026-08-18 16:01:06 +00:00
parent 40c5021c85
commit a08a2c1a96
15 changed files with 513 additions and 87 deletions
+52 -8
View File
@@ -34,6 +34,36 @@ test("POSIX bootstrap installs a private Node and falls back after a network fai
}
});
test("POSIX bootstrap scopes the Node environment proxy flag to the networked installer", {
skip: process.platform === "win32",
}, () => {
const fixture = createPosixFixture();
try {
const result = runPosixFixture(fixture, "proxy");
assert.equal(result.status, 0, result.stderr);
const invocations = readFileSync(fixture.nodeArgsLog, "utf8").trim().split(/\r?\n/);
assert.ok(invocations.some((value) => value.startsWith("--use-env-proxy ") && value.includes("installer.mjs install")));
} finally {
rmSync(fixture.root, { recursive: true, force: true });
}
});
test("POSIX bootstrap falls back for the signed installer and public key downloads", {
skip: process.platform === "win32",
}, () => {
const fixture = createPosixFixture();
try {
const result = runPosixFixture(fixture, "release-fallback");
assert.equal(result.status, 0, result.stderr);
const calls = readFileSync(fixture.callLog, "utf8").trim().split(/\r?\n/);
assert.ok(calls.includes("https://release.example.test/installer.mjs"));
assert.ok(calls.includes("https://release-mirror.example.test/installer.mjs"));
assert.ok(calls.includes("https://release-mirror.example.test/release-signing-public.pem"));
} finally {
rmSync(fixture.root, { recursive: true, force: true });
}
});
test("POSIX bootstrap stops immediately when a downloaded runtime has the wrong hash", {
skip: process.platform === "win32",
}, () => {
@@ -94,6 +124,7 @@ interface PosixFixture {
archive: string;
installer: string;
publicKey: string;
nodeArgsLog: string;
}
function createPosixFixture(): PosixFixture {
@@ -105,6 +136,7 @@ function createPosixFixture(): PosixFixture {
const archive = join(root, RUNTIME_ARCHIVE);
const installer = join(root, "installer.mjs");
const publicKey = join(root, "release-signing-public.pem");
const nodeArgsLog = join(root, "node-args.log");
const script = join(root, "bootstrap.sh");
mkdirSync(join(archiveRoot, "bin"), { recursive: true });
mkdirSync(join(archiveRoot, "lib", "node_modules", "npm", "bin"), { recursive: true });
@@ -114,6 +146,7 @@ function createPosixFixture(): PosixFixture {
const privateNode = join(archiveRoot, "bin", "node");
writeFileSync(privateNode, [
"#!/bin/sh",
"if [ -n \"${DING_TEST_NODE_ARGS_LOG:-}\" ]; then printf '%s\\n' \"$*\" >> \"$DING_TEST_NODE_ARGS_LOG\"; fi",
"if [ \"${1:-}\" = '-e' ]; then exit 0; fi",
"printf '%s\\n' '{\"ok\":true,\"status\":\"installed\",\"managedNode\":true}'",
"",
@@ -125,6 +158,7 @@ function createPosixFixture(): PosixFixture {
writeFileSync(installer, "// fixture installer\n");
writeFileSync(publicKey, "fixture public key\n");
writeFileSync(callLog, "");
writeFileSync(nodeArgsLog, "");
const curl = join(fakeBin, "curl");
writeFileSync(curl, `#!/bin/sh
@@ -145,8 +179,14 @@ case "$ding_url" in
printf '000'; exit 7 ;;
https://mirror.example.test/node/*) /bin/cp "$DING_TEST_ARCHIVE" "$ding_target"; printf '200' ;;
https://official.example.test/node/*) /bin/cp "$DING_TEST_ARCHIVE" "$ding_target"; printf '200' ;;
https://release.example.test/installer.mjs) /bin/cp "$DING_TEST_INSTALLER" "$ding_target"; printf '200' ;;
https://release.example.test/release-signing-public.pem) /bin/cp "$DING_TEST_PUBLIC_KEY" "$ding_target"; printf '200' ;;
https://release.example.test/installer.mjs)
if [ "$DING_TEST_MODE" = 'release-fallback' ]; then printf '000'; exit 7; fi
/bin/cp "$DING_TEST_INSTALLER" "$ding_target"; printf '200' ;;
https://release.example.test/release-signing-public.pem)
if [ "$DING_TEST_MODE" = 'release-fallback' ]; then printf '000'; exit 7; fi
/bin/cp "$DING_TEST_PUBLIC_KEY" "$ding_target"; printf '200' ;;
https://release-mirror.example.test/installer.mjs) /bin/cp "$DING_TEST_INSTALLER" "$ding_target"; printf '200' ;;
https://release-mirror.example.test/release-signing-public.pem) /bin/cp "$DING_TEST_PUBLIC_KEY" "$ding_target"; printf '200' ;;
*) printf '404'; exit 22 ;;
esac
`);
@@ -158,11 +198,12 @@ esac
let body = readFileSync("distribution/bootstrap-posix.template.sh", "utf8");
const replacements: Record<string, string> = {
"{{NODE_SOURCE_BASES_POSIX}}": "https://primary.example.test/node/ https://mirror.example.test/node/ https://official.example.test/node/",
"{{INSTALLER_URL}}": "https://release.example.test/installer.mjs",
"{{INSTALLER_URLS_POSIX}}": "https://release.example.test/installer.mjs https://release-mirror.example.test/installer.mjs",
"{{INSTALLER_SHA256}}": digest(installer),
"{{PUBLIC_KEY_URL}}": "https://release.example.test/release-signing-public.pem",
"{{PUBLIC_KEY_URLS_POSIX}}": "https://release.example.test/release-signing-public.pem https://release-mirror.example.test/release-signing-public.pem",
"{{PUBLIC_KEY_SHA256}}": digest(publicKey),
"{{MANIFEST_URL}}": "https://release.example.test/manifest.json",
"{{MANIFEST_MIRROR_URLS_POSIX}}": "https://release-mirror.example.test/manifest.json",
};
for (const platform of ["LINUX_X64", "LINUX_ARM64", "DARWIN_X64", "DARWIN_ARM64"]) {
replacements[`{{NODE_${platform}_FILE}}`] = RUNTIME_ARCHIVE;
@@ -172,10 +213,10 @@ esac
assert.doesNotMatch(body, /\{\{/);
writeFileSync(script, body);
chmodSync(script, 0o700);
return { root, clientRoot, callLog, script, fakeBin, archive, installer, publicKey };
return { root, clientRoot, callLog, script, fakeBin, archive, installer, publicKey, nodeArgsLog };
}
function runPosixFixture(fixture: PosixFixture, mode: "fallback" | "corrupt" | "server-error") {
function runPosixFixture(fixture: PosixFixture, mode: "fallback" | "corrupt" | "server-error" | "proxy" | "release-fallback") {
return spawnSync("/bin/sh", [fixture.script], {
encoding: "utf8",
env: {
@@ -187,6 +228,8 @@ function runPosixFixture(fixture: PosixFixture, mode: "fallback" | "corrupt" | "
DING_TEST_ARCHIVE: fixture.archive,
DING_TEST_INSTALLER: fixture.installer,
DING_TEST_PUBLIC_KEY: fixture.publicKey,
DING_TEST_NODE_ARGS_LOG: fixture.nodeArgsLog,
...(mode === "proxy" ? { HTTPS_PROXY: "http://proxy.example.test:8080" } : {}),
},
});
}
@@ -195,11 +238,12 @@ function renderWindowsBootstrap(): string {
let body = readFileSync("distribution/bootstrap-windows.template.ps1", "utf8");
const replacements: Record<string, string> = {
"{{NODE_SOURCE_BASES_POWERSHELL}}": '"https://primary.example.test/node/", "https://official.example.test/node/"',
"{{INSTALLER_URL}}": "https://release.example.test/installer.mjs",
"{{INSTALLER_URLS_POWERSHELL}}": '"https://release.example.test/installer.mjs", "https://release-mirror.example.test/installer.mjs"',
"{{INSTALLER_SHA256}}": "a".repeat(64),
"{{PUBLIC_KEY_URL}}": "https://release.example.test/release-signing-public.pem",
"{{PUBLIC_KEY_URLS_POWERSHELL}}": '"https://release.example.test/release-signing-public.pem", "https://release-mirror.example.test/release-signing-public.pem"',
"{{PUBLIC_KEY_SHA256}}": "b".repeat(64),
"{{MANIFEST_URL}}": "https://release.example.test/manifest.json",
"{{MANIFEST_MIRROR_URLS_POWERSHELL}}": '"https://release-mirror.example.test/manifest.json"',
};
for (const platform of ["WIN32_X64", "WIN32_ARM64"]) {
replacements[`{{NODE_${platform}_FILE}}`] = `node-v${NODE_VERSION}-win-x64.zip`;