Skip to content

Commit 0160156

Browse files
committed
fix(supervisor): scrape apiserver /metrics over https so TLS verifies against the cluster CA
1 parent a3e578b commit 0160156

1 file changed

Lines changed: 34 additions & 7 deletions

File tree

apps/supervisor/src/clients/kubernetes.ts

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as https from "node:https";
12
import * as k8s from "@kubernetes/client-node";
23
import { Informer } from "@kubernetes/client-node";
34
import { ListPromise } from "@kubernetes/client-node";
@@ -67,12 +68,38 @@ export function createApiserverMetricsFetcher(): () => Promise<string> {
6768
if (!cluster) {
6869
throw new Error("no current cluster in kubeconfig");
6970
}
70-
const requestInit = await kubeConfig.applyToFetchOptions({ method: "GET" });
71-
// node-fetch vs DOM RequestInit: structurally compatible, declaration-only mismatch
72-
const response = await fetch(`${cluster.server}/metrics`, requestInit as unknown as RequestInit);
73-
if (!response.ok) {
74-
throw new Error(`apiserver /metrics scrape failed: ${response.status}`);
75-
}
76-
return response.text();
71+
const url = new URL(`${cluster.server}/metrics`);
72+
const opts: https.RequestOptions = {
73+
method: "GET",
74+
protocol: url.protocol,
75+
hostname: url.hostname,
76+
port: url.port,
77+
path: url.pathname,
78+
};
79+
// applyToHTTPSOptions sets the cluster CA, client cert/key, and auth headers
80+
// (incl. exec plugins) on the request - so TLS verifies against the cluster
81+
// CA, not the system store. The fetch-options path attaches the CA as an
82+
// https.Agent, which global fetch (undici) ignores.
83+
await kubeConfig.applyToHTTPSOptions(opts);
84+
85+
return new Promise<string>((resolve, reject) => {
86+
const req = https.request(opts, (res) => {
87+
const status = res.statusCode ?? 0;
88+
let body = "";
89+
res.setEncoding("utf8");
90+
res.on("data", (chunk) => {
91+
body += chunk;
92+
});
93+
res.on("end", () => {
94+
if (status >= 200 && status < 300) {
95+
resolve(body);
96+
} else {
97+
reject(new Error(`apiserver /metrics scrape failed: ${status}`));
98+
}
99+
});
100+
});
101+
req.on("error", reject);
102+
req.end();
103+
});
77104
};
78105
}

0 commit comments

Comments
 (0)