diff --git a/src/main/context-handler/context-handler.ts b/src/main/context-handler/context-handler.ts index 04d3bb8eec..1e5b209236 100644 --- a/src/main/context-handler/context-handler.ts +++ b/src/main/context-handler/context-handler.ts @@ -14,6 +14,7 @@ import logger from "../logger"; import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy"; import path from "path"; import { readFile } from "fs/promises"; +import type { CreateKubeAuthProxy } from "../kube-auth-proxy/create-kube-auth-proxy.injectable"; export interface PrometheusDetails { prometheusPath: string; @@ -28,7 +29,7 @@ interface PrometheusServicePreferences { } interface Dependencies { - createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; + createKubeAuthProxy: CreateKubeAuthProxy; certPath: string; } @@ -121,7 +122,11 @@ export class ContextHandler { await this.ensureServer(); const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : ""; - return `http://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix}${path}`; + return `https://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix}${path}`; + } + + async resolveAuthProxyCa() { + return readFile(path.join(this.dependencies.certPath, "proxy.crt")); } async getApiTarget(isLongRunningRequest = false): Promise { @@ -137,7 +142,9 @@ export class ContextHandler { protected async newApiTarget(timeout: number): Promise { await this.ensureServer(); - const ca = (await readFile(path.join(this.dependencies.certPath, "proxy.crt"))).toString(); + const caFileContents = await this.resolveAuthProxyCa(); + const clusterPath = this.clusterUrl.path !== "/" ? this.clusterUrl.path : ""; + const apiPrefix = `${this.kubeAuthProxy.apiPrefix}${clusterPath}`; return { //target: await this.resolveAuthProxyUrl(), @@ -145,7 +152,8 @@ export class ContextHandler { protocol: "https:", host: "127.0.0.1", port: this.kubeAuthProxy.port, - ca, + path: apiPrefix, + ca: caFileContents.toString(), }, changeOrigin: true, timeout, diff --git a/src/main/index.ts b/src/main/index.ts index 984d3facd5..d60d0ea4e6 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -39,7 +39,7 @@ import { WeblinkStore } from "../common/weblink-store"; import { SentryInit } from "../common/sentry"; import { ensureDir } from "fs-extra"; import { initMenu } from "./menu/menu"; -import { kubeApiRequest } from "./proxy-functions"; +import { kubeApiUpgradeRequest } from "./proxy-functions"; import { initTray } from "./tray/tray"; import { ShellSession } from "./shell-session/shell-session"; import { getDi } from "./getDi"; @@ -231,7 +231,7 @@ app.on("ready", async () => { const lensProxy = LensProxy.createInstance(router, httpProxy.createProxy(), { getClusterForRequest: (req) => ClusterManager.getInstance().getClusterForRequest(req), - kubeApiRequest, + kubeApiUpgradeRequest, shellApiRequest, }); diff --git a/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts b/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts index 845ae92912..275f05ead7 100644 --- a/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts +++ b/src/main/kube-auth-proxy/create-kube-auth-proxy.injectable.ts @@ -11,10 +11,12 @@ import { getBinaryName } from "../../common/vars"; import directoryForBundledBinariesInjectable from "../../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable"; import getKubeAuthProxyCertDirInjectable from "./kube-auth-proxy-cert.injectable"; +export type CreateKubeAuthProxy = (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy; + const createKubeAuthProxyInjectable = getInjectable({ id: "create-kube-auth-proxy", - instantiate: (di) => { + instantiate: (di): CreateKubeAuthProxy => { const binaryName = getBinaryName("lens-k8s-proxy"); const dependencies: KubeAuthProxyDependencies = { proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), binaryName), diff --git a/src/main/kube-auth-proxy/kube-auth-proxy.ts b/src/main/kube-auth-proxy/kube-auth-proxy.ts index 62e75ee15c..3d28eaa95a 100644 --- a/src/main/kube-auth-proxy/kube-auth-proxy.ts +++ b/src/main/kube-auth-proxy/kube-auth-proxy.ts @@ -44,7 +44,7 @@ export class KubeAuthProxy { } const proxyBin = this.dependencies.proxyBinPath; - const certPath = await this.dependencies.proxyCertPath; + const certPath = this.dependencies.proxyCertPath; this.proxyProcess = this.dependencies.spawn(proxyBin, [], { env: { diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index 31d593d627..3a4bdea723 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -22,7 +22,7 @@ type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | null; export interface LensProxyFunctions { getClusterForRequest: GetClusterForRequest; shellApiRequest: (args: ProxyApiRequestArgs) => void | Promise; - kubeApiRequest: (args: ProxyApiRequestArgs) => void | Promise; + kubeApiUpgradeRequest: (args: ProxyApiRequestArgs) => void | Promise; } const watchParam = "watch"; @@ -61,7 +61,7 @@ export class LensProxy extends Singleton { public port: number; - constructor(protected router: Router, protected proxy: httpProxy, { shellApiRequest, kubeApiRequest, getClusterForRequest }: LensProxyFunctions) { + constructor(protected router: Router, protected proxy: httpProxy, { shellApiRequest, kubeApiUpgradeRequest, getClusterForRequest }: LensProxyFunctions) { super(); this.configureProxy(proxy); @@ -88,7 +88,7 @@ export class LensProxy extends Singleton { return socket.destroy(); } - const reqHandler = isInternal ? shellApiRequest : kubeApiRequest; + const reqHandler = isInternal ? shellApiRequest : kubeApiUpgradeRequest; (async () => reqHandler({ req, socket, head, cluster }))() .catch(error => logger.error("[LENS-PROXY]: failed to handle proxy upgrade", error)); diff --git a/src/main/proxy-functions/index.ts b/src/main/proxy-functions/index.ts index 490e3c4a74..5d374825ee 100644 --- a/src/main/proxy-functions/index.ts +++ b/src/main/proxy-functions/index.ts @@ -2,5 +2,5 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -export * from "./kube-api-request"; +export * from "./kube-api-upgrade-request"; export * from "./types"; diff --git a/src/main/proxy-functions/kube-api-request.ts b/src/main/proxy-functions/kube-api-upgrade-request.ts similarity index 81% rename from src/main/proxy-functions/kube-api-request.ts rename to src/main/proxy-functions/kube-api-upgrade-request.ts index 8995d965e5..899d22164e 100644 --- a/src/main/proxy-functions/kube-api-request.ts +++ b/src/main/proxy-functions/kube-api-upgrade-request.ts @@ -4,21 +4,25 @@ */ import { chunk } from "lodash"; -import net from "net"; +import tls from "tls"; import url from "url"; import { apiKubePrefix } from "../../common/vars"; import type { ProxyApiRequestArgs } from "./types"; const skipRawHeaders = new Set(["Host", "Authorization"]); -export async function kubeApiRequest({ req, socket, head, cluster }: ProxyApiRequestArgs) { +export async function kubeApiUpgradeRequest({ req, socket, head, cluster }: ProxyApiRequestArgs) { const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, ""); + const proxyCa = await cluster.contextHandler.resolveAuthProxyCa(); const apiUrl = url.parse(cluster.apiUrl); const pUrl = url.parse(proxyUrl); - const connectOpts = { port: parseInt(pUrl.port), host: pUrl.hostname }; - const proxySocket = new net.Socket(); + const connectOpts = { + port: parseInt(pUrl.port), + host: pUrl.hostname, + ca: proxyCa, + }; - proxySocket.connect(connectOpts, () => { + const proxySocket = tls.connect(connectOpts, () => { proxySocket.write(`${req.method} ${pUrl.path} HTTP/1.1\r\n`); proxySocket.write(`Host: ${apiUrl.host}\r\n`);