feat: secure frontend and provider ingress

This commit is contained in:
Codex
2026-05-04 11:40:56 +00:00
parent caa80ee5e7
commit 8726611b6f
25 changed files with 1491 additions and 450 deletions
+38 -8
View File
@@ -1,4 +1,5 @@
import { type UniDeskConfig } from "./config";
import { runCommand } from "./command";
import { type UniDeskConfig, repoRoot } from "./config";
async function readJson(url: string, init?: RequestInit): Promise<unknown> {
const controller = new AbortController();
@@ -7,24 +8,53 @@ async function readJson(url: string, init?: RequestInit): Promise<unknown> {
const res = await fetch(url, { ...init, signal: controller.signal });
const text = await res.text();
return { ok: res.ok, status: res.status, body: text.length > 0 ? JSON.parse(text) : null };
} catch (error) {
return { ok: false, error: error instanceof Error ? error.message : String(error) };
} finally {
clearTimeout(timer);
}
}
function coreInternalFetch(path: string, init?: { method?: string; body?: unknown }): unknown {
const code = `
const res = await fetch(${JSON.stringify(`http://127.0.0.1:8080${path}`)}, ${JSON.stringify({
method: init?.method ?? "GET",
headers: init?.body === undefined ? undefined : { "content-type": "application/json" },
body: init?.body === undefined ? undefined : JSON.stringify(init.body),
})});
const text = await res.text();
let body = null;
try { body = text ? JSON.parse(text) : null; } catch { body = { text }; }
console.log(JSON.stringify({ ok: res.ok, status: res.status, body }));
`;
const result = runCommand(["docker", "exec", "unidesk-backend-core", "bun", "-e", code], repoRoot);
if (result.exitCode !== 0) {
return { ok: false, exitCode: result.exitCode, stdoutTail: result.stdout.slice(-1200), stderrTail: result.stderr.slice(-1200) };
}
try {
return JSON.parse(result.stdout.trim()) as unknown;
} catch {
return { ok: true, stdoutTail: result.stdout.slice(-1200), stderrTail: result.stderr.slice(-1200) };
}
}
export async function debugHealth(config: UniDeskConfig): Promise<unknown> {
return {
core: await readJson(`http://127.0.0.1:${config.network.core.port}/health`),
overview: await readJson(`http://127.0.0.1:${config.network.core.port}/api/overview`),
nodes: await readJson(`http://127.0.0.1:${config.network.core.port}/api/nodes`),
frontend: await readJson(`http://127.0.0.1:${config.network.frontend.port}/health`),
coreInternal: await coreInternalFetch("/health"),
overviewInternal: await coreInternalFetch("/api/overview"),
nodesInternal: await coreInternalFetch("/api/nodes"),
frontendPublic: await readJson(`http://127.0.0.1:${config.network.frontend.port}/health`),
providerIngressPublic: await readJson(`http://127.0.0.1:${config.network.providerIngress.port}/health`),
publicExposureBoundary: {
coreHostPort: { port: config.network.core.port, expected: "not-exposed" },
databaseHostPort: { port: config.network.database.port, expected: "not-exposed" },
},
};
}
export async function debugDispatch(config: UniDeskConfig, providerId: string, command: "docker.ps" | "echo"): Promise<unknown> {
return readJson(`http://127.0.0.1:${config.network.core.port}/api/dispatch`, {
return coreInternalFetch("/api/dispatch", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ providerId, command, payload: { source: "cli-debug" } }),
body: { providerId, command, payload: { source: "cli-debug" } },
});
}