mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-10-13 17:47:09 +00:00
fix(build): derive the pack-boot CLI token against the smoke's DATA_DIR (#15147)
Some checks failed
Publish to Docker Hub / Resolve Docker release metadata (push) Has been cancelled
Release-Green (continuous) / Validate active release branch (push) Has been cancelled
Release-Green (continuous) / Validate main branch (push) Has been cancelled
Release-Green (continuous) / Bank ratchet shrinks (push) Has been cancelled
Release-Green (continuous) / Baseline headroom (push) Has been cancelled
Lock released branch / lock-branch (push) Has been cancelled
Lock released branch / guard-no-push-after-release (push) Has been cancelled
Release acceptance / Release acceptance (push) Has been cancelled
OpenSSF Scorecard / Scorecard analysis (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/amd64) (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/arm64) (push) Has been cancelled
Publish to Docker Hub / Publish multi-arch manifests (push) Has been cancelled
Some checks failed
Publish to Docker Hub / Resolve Docker release metadata (push) Has been cancelled
Release-Green (continuous) / Validate active release branch (push) Has been cancelled
Release-Green (continuous) / Validate main branch (push) Has been cancelled
Release-Green (continuous) / Bank ratchet shrinks (push) Has been cancelled
Release-Green (continuous) / Baseline headroom (push) Has been cancelled
Lock released branch / lock-branch (push) Has been cancelled
Lock released branch / guard-no-push-after-release (push) Has been cancelled
Release acceptance / Release acceptance (push) Has been cancelled
OpenSSF Scorecard / Scorecard analysis (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/amd64) (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/arm64) (push) Has been cancelled
Publish to Docker Hub / Publish multi-arch manifests (push) Has been cancelled
Release-captain fix (v3.8.51 release PR #11442, Package Artifact / dast-smoke): since #13909 the packaged CLI token salt lives in the instance DATA_DIR, but the pack-boot and install-upgrade smokes derived the token without it, so the server rejected the CLI and served the anonymous health view (no version). The smokes now pass their isolated DATA_DIR. New unit test red→green; end-to-end with the CI next-build artifact: version 3.8.51, whoami 200. No production code changed.
This commit is contained in:
parent
dfb563d5d9
commit
2f42a9ac19
3 changed files with 47 additions and 7 deletions
|
|
@ -76,7 +76,9 @@ const INTERNAL_SERVICE_HEADER = "x-omniroute-internal-service-token";
|
|||
* packaged CLI. Sent alongside the internal-service token so a build that only honours one
|
||||
* of the two still answers with the full payload.
|
||||
*/
|
||||
function derivePackagedCliToken(prefix) {
|
||||
// The CLI token salt lives under <DATA_DIR> (#13679/#13909): derive against the DATA_DIR the
|
||||
// probed server boots on, or the token never matches.
|
||||
function derivePackagedCliToken(prefix, dataDir) {
|
||||
const cliModuleUrl = pathToFileURL(
|
||||
path.join(packageRootFor(prefix), "bin", "cli", "utils", "cliToken.mjs")
|
||||
).href;
|
||||
|
|
@ -89,7 +91,7 @@ function derivePackagedCliToken(prefix) {
|
|||
"import(process.argv[1]).then(async m => process.stdout.write(await m.getCliToken()))",
|
||||
cliModuleUrl,
|
||||
],
|
||||
{ encoding: "utf8", env: { ...process.env } }
|
||||
{ encoding: "utf8", env: { ...process.env, DATA_DIR: dataDir } }
|
||||
).trim();
|
||||
} catch {
|
||||
// A truncated/broken install cannot derive a token. Returning null keeps the boot
|
||||
|
|
@ -176,7 +178,7 @@ async function bootAndProbe({ prefix, dataDir, port, expectVersion, label }) {
|
|||
if (!fs.existsSync(binPath)) {
|
||||
return { ok: false, failures: [`${label}: bin not found at ${binPath}`], tail: [] };
|
||||
}
|
||||
const cliToken = derivePackagedCliToken(prefix);
|
||||
const cliToken = derivePackagedCliToken(prefix, dataDir);
|
||||
const probeHeaders = {
|
||||
[INTERNAL_SERVICE_HEADER]: INTERNAL_SERVICE_TOKEN,
|
||||
...(cliToken ? { "x-omniroute-cli-token": cliToken } : {}),
|
||||
|
|
|
|||
|
|
@ -311,7 +311,13 @@ function spawnServer(binPath, port, dataDir) {
|
|||
return { child, tail };
|
||||
}
|
||||
|
||||
function derivePackagedCliToken(packageRoot) {
|
||||
/**
|
||||
* Derive the loopback machine token exactly as the installed CLI would for this install.
|
||||
* Since #13679/#13909 the token salt is per-install, persisted under <DATA_DIR>, so the
|
||||
* derivation MUST see the same DATA_DIR the server boots on — otherwise the CLI resolves
|
||||
* a different salt, the server rejects the token and health serves the anonymous view.
|
||||
*/
|
||||
export function derivePackagedCliToken(packageRoot, dataDir) {
|
||||
const cliModuleUrl = pathToFileURL(
|
||||
path.join(packageRoot, "bin", "cli", "utils", "cliToken.mjs")
|
||||
).href;
|
||||
|
|
@ -323,7 +329,7 @@ function derivePackagedCliToken(packageRoot) {
|
|||
"import(process.argv[1]).then(async m => process.stdout.write(await m.getCliToken()))",
|
||||
cliModuleUrl,
|
||||
],
|
||||
{ encoding: "utf8", env: { ...process.env } }
|
||||
{ encoding: "utf8", env: { ...process.env, DATA_DIR: dataDir } }
|
||||
).trim();
|
||||
}
|
||||
|
||||
|
|
@ -454,7 +460,7 @@ async function main() {
|
|||
const dataDir = path.join(tmp, "data");
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
const binPath = path.join(prefix, "bin", "omniroute");
|
||||
const packagedCliToken = derivePackagedCliToken(packageRoot);
|
||||
const packagedCliToken = derivePackagedCliToken(packageRoot, dataDir);
|
||||
|
||||
// BOOT #1 — boot, prove the forced sql.js tier, PATCH a setting, then shut down cleanly
|
||||
// so the sql.js adapter's graceful persist actually lands on disk. The in-flow stopChild
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createHmac } from "node:crypto";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import {
|
||||
|
|
@ -15,6 +16,7 @@ import {
|
|||
evaluateMachineTokenAuth,
|
||||
evaluateSqlJsRoundTrip,
|
||||
evaluateRestartPersistence,
|
||||
derivePackagedCliToken,
|
||||
} from "../../scripts/check/check-pack-boot.mjs";
|
||||
|
||||
// WS1.2 (T1, v3.8.49 quality plan) — pure-function guards for the tarball boot-smoke
|
||||
|
|
@ -244,3 +246,33 @@ test("source guard: final shutdown only deletes the workspace after a CONFIRMED
|
|||
"stopChild/waitForHealthy must read authoritative exit state, not a stale boolean"
|
||||
);
|
||||
});
|
||||
|
||||
// #13679/#13909 made the CLI token salt per-install, persisted under <DATA_DIR>. The
|
||||
// smoke boots the server on an isolated DATA_DIR, so the token it sends must be derived
|
||||
// against that SAME DATA_DIR — derived without it, the CLI resolves a different salt,
|
||||
// the server rejects the token, and /api/monitoring/health answers the anonymous view
|
||||
// ("version undefined", release PR #11442 Package Artifact).
|
||||
test("derivePackagedCliToken derives the token against the server's DATA_DIR salt", () => {
|
||||
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
||||
const dataDir = mkdtempSync(path.join(os.tmpdir(), "pack-boot-cli-token-"));
|
||||
const otherDataDir = mkdtempSync(path.join(os.tmpdir(), "pack-boot-cli-token-other-"));
|
||||
const savedCliSalt = process.env.OMNIROUTE_CLI_SALT;
|
||||
delete process.env.OMNIROUTE_CLI_SALT;
|
||||
try {
|
||||
const token = derivePackagedCliToken(repoRoot, dataDir);
|
||||
assert.match(token, /^[0-9a-f]{64}$/);
|
||||
assert.equal(
|
||||
existsSync(path.join(dataDir, "cli-token-salt.json")),
|
||||
true,
|
||||
"the salt must be established inside the smoke's DATA_DIR"
|
||||
);
|
||||
// Stable for the same DATA_DIR, different for another install's DATA_DIR.
|
||||
assert.equal(derivePackagedCliToken(repoRoot, dataDir), token);
|
||||
assert.notEqual(derivePackagedCliToken(repoRoot, otherDataDir), token);
|
||||
} finally {
|
||||
if (savedCliSalt === undefined) delete process.env.OMNIROUTE_CLI_SALT;
|
||||
else process.env.OMNIROUTE_CLI_SALT = savedCliSalt;
|
||||
rmSync(dataDir, { recursive: true, force: true });
|
||||
rmSync(otherDataDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue