Files
diegosouzapw--omniroute/tests/unit/agent-bridge-cert-install-fallback-4546.test.ts
2026-07-13 13:39:12 +08:00

65 lines
3.3 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
// #4546 — In containers/headless, the system trust store can't be written
// (no sudo / read-only store / no interactive auth), so the cert install
// throws and used to abort the whole Agent Bridge start. These tests pin the
// graceful-fallback contract: a structured result that distinguishes a
// user-canceled auth from an environment failure, plus a platform-specific
// manual-install guide so the operator can trust the MITM root CA themselves.
const { classifyCertInstallError, buildCertManualGuide, installCertResult } = await import(
"../../src/mitm/cert/install.ts"
);
const DOWNLOAD_URL = "/api/tools/agent-bridge/cert/download";
test("classifyCertInstallError → 'canceled' only when the message says canceled", () => {
assert.equal(classifyCertInstallError("User canceled authorization"), "canceled");
assert.equal(classifyCertInstallError("Operation was canceled by the user"), "canceled");
});
test("classifyCertInstallError → 'environment' for trust-store / sudo failures", () => {
assert.equal(classifyCertInstallError("Certificate install failed"), "environment");
assert.equal(classifyCertInstallError("sudo: no tty present and no askpass program specified"), "environment");
assert.equal(classifyCertInstallError("Certificate file not found: /x/server.crt"), "environment");
});
test("buildCertManualGuide(linux) → update-ca-certificates steps + download url + cert path", () => {
const guide = buildCertManualGuide("/data/mitm/server.crt", "linux");
assert.equal(guide.platform, "linux");
assert.equal(guide.certPath, "/data/mitm/server.crt");
assert.equal(guide.downloadUrl, DOWNLOAD_URL);
assert.ok(Array.isArray(guide.steps) && guide.steps.length > 0);
const joined = guide.steps.join("\n");
assert.ok(joined.includes("update-ca-"), "should mention the distro CA refresh command");
assert.ok(joined.includes("/data/mitm/server.crt"), "should reference the cert path");
});
test("buildCertManualGuide(darwin) → security add-trusted-cert", () => {
const guide = buildCertManualGuide("/d/server.crt", "darwin");
assert.equal(guide.platform, "darwin");
assert.ok(guide.steps.join("\n").includes("add-trusted-cert"));
});
test("buildCertManualGuide(win32) → certutil -addstore Root", () => {
const guide = buildCertManualGuide("C:/d/server.crt", "win32");
assert.equal(guide.platform, "win32");
assert.ok(guide.steps.join("\n").toLowerCase().includes("certutil"));
});
test("installCertResult → environment skip (not a throw) when install is impossible", async () => {
// A non-existent cert path makes installCert() throw before any privileged
// command runs — deterministic, no sudo. The wrapper must convert that into a
// structured skippable result with a manual guide, never a thrown error.
const result = await installCertResult("", "/nonexistent/omniroute-4546-server.crt");
assert.equal(result.installed, false);
assert.equal(result.skipped, true);
assert.equal(result.reason, "environment");
assert.ok(result.manualGuide, "environment skip must carry a manual guide");
assert.equal(result.manualGuide?.downloadUrl, DOWNLOAD_URL);
// The message must be a safe string (no stack trace leaked).
assert.equal(typeof result.message, "string");
assert.ok(!String(result.message).includes("\n at "), "must not leak a stack trace");
});