fix: harden d601 k3s guards
This commit is contained in:
+25
-22
@@ -4,6 +4,11 @@ import { createWriteStream, existsSync, mkdirSync, openSync, readSync, statSync,
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { join, resolve } from "node:path";
|
||||
import { repoRoot, rootPath } from "./config";
|
||||
import {
|
||||
classifyD601DefaultKubectlDiagnostic,
|
||||
classifyD601K3sTarget,
|
||||
d601NativeKubeconfig,
|
||||
} from "./d601-k3s-guard";
|
||||
|
||||
type HwlabCdAction = "status" | "apply";
|
||||
type HwlabCdEnvironment = "dev";
|
||||
@@ -59,7 +64,7 @@ interface CommandView {
|
||||
|
||||
const namespace = "hwlab-dev";
|
||||
const lockName = "hwlab-dev-cd-lock";
|
||||
const nativeKubeconfig = "/etc/rancher/k3s/k3s.yaml";
|
||||
const nativeKubeconfig = d601NativeKubeconfig;
|
||||
const defaultFrontendLiveUrl = "http://74.48.78.17:16666/health/live";
|
||||
const defaultApiLiveUrl = "http://74.48.78.17:16667/health/live";
|
||||
const parseCaptureLimitBytes = 4 * 1024 * 1024;
|
||||
@@ -347,38 +352,36 @@ async function gitSummary(repoPath: string, dumpDir: string, timeoutMs: number):
|
||||
|
||||
async function nativeK3sGuard(kubeconfig: string, dumpDir: string, timeoutMs: number): Promise<Record<string, unknown>> {
|
||||
const env = { ...process.env, KUBECONFIG: kubeconfig };
|
||||
const [context, server, nodes] = await Promise.all([
|
||||
const [context, server, nodes, defaultContext, defaultServer, defaultNodes] = await Promise.all([
|
||||
runCaptured(["kubectl", "config", "current-context"], repoRoot, dumpDir, "k3s-current-context", { env, timeoutMs }),
|
||||
runCaptured(["kubectl", "config", "view", "--minify", "-o", "jsonpath={.clusters[0].cluster.server}"], repoRoot, dumpDir, "k3s-server", { env, timeoutMs }),
|
||||
runCaptured(["kubectl", "get", "nodes", "-o", "jsonpath={range .items[*]}{.metadata.name}{\"\\n\"}{end}"], repoRoot, dumpDir, "k3s-nodes", { env, timeoutMs }),
|
||||
runCaptured(["kubectl", "config", "current-context"], repoRoot, dumpDir, "default-kubectl-current-context", { timeoutMs }),
|
||||
runCaptured(["kubectl", "config", "view", "--minify", "-o", "jsonpath={.clusters[0].cluster.server}"], repoRoot, dumpDir, "default-kubectl-server", { timeoutMs }),
|
||||
runCaptured(["kubectl", "get", "nodes", "-o", "jsonpath={range .items[*]}{.metadata.name}{\"\\n\"}{end}"], repoRoot, dumpDir, "default-kubectl-nodes", { timeoutMs }),
|
||||
]);
|
||||
const contextText = context.stdoutText.trim();
|
||||
const serverText = server.stdoutText.trim();
|
||||
const nodeNames = nodes.stdoutText.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
||||
const combined = `${context.stdoutText}\n${context.stderrText}\n${server.stdoutText}\n${server.stderrText}\n${nodes.stdoutText}\n${nodes.stderrText}`;
|
||||
const refusalSignals = [
|
||||
/docker-desktop/iu.test(combined) ? "docker-desktop" : null,
|
||||
/desktop-control-plane/iu.test(combined) ? "desktop-control-plane" : null,
|
||||
/127\.0\.0\.1:11700/u.test(combined) ? "127.0.0.1:11700" : null,
|
||||
].filter((signal): signal is string => signal !== null);
|
||||
const refusal = refusalSignals.length > 0;
|
||||
const readable = context.ok && server.ok && nodes.ok;
|
||||
return {
|
||||
status: refusal ? "refused" : readable ? "pass" : "blocked",
|
||||
refusal,
|
||||
refusalSignals,
|
||||
const defaultDiagnostic = classifyD601DefaultKubectlDiagnostic({
|
||||
currentContext: defaultContext.stdoutText.trim() || null,
|
||||
apiServer: defaultServer.stdoutText.trim() || null,
|
||||
combinedText: `${defaultContext.stdoutText}\n${defaultContext.stderrText}\n${defaultServer.stdoutText}\n${defaultServer.stderrText}\n${defaultNodes.stdoutText}\n${defaultNodes.stderrText}`,
|
||||
commandsOk: defaultContext.ok && defaultServer.ok && defaultNodes.ok,
|
||||
});
|
||||
const guard = classifyD601K3sTarget({
|
||||
kubeconfig,
|
||||
injectedEnv: { KUBECONFIG: kubeconfig },
|
||||
expectedKubeconfig: nativeKubeconfig,
|
||||
currentContext: contextText || null,
|
||||
apiServer: serverText || null,
|
||||
nodeNames,
|
||||
nodeCount: nodeNames.length,
|
||||
summary: refusal
|
||||
? "Refusing HWLAB CD because kubectl resolved to a Docker Desktop control plane signal."
|
||||
: readable
|
||||
? "D601 native k3s guard passed with explicit KUBECONFIG."
|
||||
: "D601 native k3s guard could not fully read context, server, and nodes.",
|
||||
commands: [context, server, nodes].map(commandView),
|
||||
commandsOk: context.ok && server.ok && nodes.ok,
|
||||
combinedText: `${context.stdoutText}\n${context.stderrText}\n${server.stdoutText}\n${server.stderrText}\n${nodes.stdoutText}\n${nodes.stderrText}`,
|
||||
}, defaultDiagnostic);
|
||||
return {
|
||||
...guard,
|
||||
injectedEnv: { KUBECONFIG: kubeconfig },
|
||||
commands: [context, server, nodes, defaultContext, defaultServer, defaultNodes].map(commandView),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user