mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
wip: enable tls on lens-k8s-proxy
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
c04a3b8d33
commit
ad1776d101
@ -267,6 +267,7 @@
|
|||||||
"request": "^2.88.2",
|
"request": "^2.88.2",
|
||||||
"request-promise-native": "^1.0.9",
|
"request-promise-native": "^1.0.9",
|
||||||
"rfc6902": "^4.0.2",
|
"rfc6902": "^4.0.2",
|
||||||
|
"selfsigned": "^2.0.0",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"shell-env": "^3.0.1",
|
"shell-env": "^3.0.1",
|
||||||
"spdy": "^4.0.2",
|
"spdy": "^4.0.2",
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import url, { UrlWithStringQuery } from "url";
|
|||||||
import { CoreV1Api } from "@kubernetes/client-node";
|
import { CoreV1Api } from "@kubernetes/client-node";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
|
import type { KubeAuthProxy } from "../kube-auth-proxy/kube-auth-proxy";
|
||||||
|
import path from "path";
|
||||||
|
import { readFile } from "fs/promises";
|
||||||
|
|
||||||
export interface PrometheusDetails {
|
export interface PrometheusDetails {
|
||||||
prometheusPath: string;
|
prometheusPath: string;
|
||||||
@ -27,6 +29,7 @@ interface PrometheusServicePreferences {
|
|||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
createKubeAuthProxy: (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) => KubeAuthProxy;
|
||||||
|
certPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ContextHandler {
|
export class ContextHandler {
|
||||||
@ -118,7 +121,7 @@ export class ContextHandler {
|
|||||||
await this.ensureServer();
|
await this.ensureServer();
|
||||||
const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : "";
|
const path = this.clusterUrl.path !== "/" ? this.clusterUrl.path : "";
|
||||||
|
|
||||||
return `http://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix.slice(0, -1)}${path}`;
|
return `https://127.0.0.1:${this.kubeAuthProxy.port}${this.kubeAuthProxy.apiPrefix.slice(0, -1)}${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getApiTarget(isLongRunningRequest = false): Promise<httpProxy.ServerOptions> {
|
async getApiTarget(isLongRunningRequest = false): Promise<httpProxy.ServerOptions> {
|
||||||
@ -132,10 +135,21 @@ export class ContextHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async newApiTarget(timeout: number): Promise<httpProxy.ServerOptions> {
|
protected async newApiTarget(timeout: number): Promise<httpProxy.ServerOptions> {
|
||||||
|
await this.ensureServer();
|
||||||
|
|
||||||
|
const ca = (await readFile(path.join(this.dependencies.certPath, "proxy.crt"))).toString();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
target: await this.resolveAuthProxyUrl(),
|
//target: await this.resolveAuthProxyUrl(),
|
||||||
|
target: {
|
||||||
|
protocol: "https:",
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: this.kubeAuthProxy.port,
|
||||||
|
ca,
|
||||||
|
},
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
timeout,
|
timeout,
|
||||||
|
secure: true,
|
||||||
headers: {
|
headers: {
|
||||||
"Host": this.clusterUrl.hostname,
|
"Host": this.clusterUrl.hostname,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
|||||||
import type { Cluster } from "../../common/cluster/cluster";
|
import type { Cluster } from "../../common/cluster/cluster";
|
||||||
import { ContextHandler } from "./context-handler";
|
import { ContextHandler } from "./context-handler";
|
||||||
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
|
import createKubeAuthProxyInjectable from "../kube-auth-proxy/create-kube-auth-proxy.injectable";
|
||||||
|
import getKubeAuthProxyCertDirInjectable from "../kube-auth-proxy/kube-auth-proxy-cert.injectable";
|
||||||
|
|
||||||
const createContextHandlerInjectable = getInjectable({
|
const createContextHandlerInjectable = getInjectable({
|
||||||
id: "create-context-handler",
|
id: "create-context-handler",
|
||||||
@ -13,6 +14,7 @@ const createContextHandlerInjectable = getInjectable({
|
|||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const dependencies = {
|
const dependencies = {
|
||||||
createKubeAuthProxy: di.inject(createKubeAuthProxyInjectable),
|
createKubeAuthProxy: di.inject(createKubeAuthProxyInjectable),
|
||||||
|
certPath: di.inject(getKubeAuthProxyCertDirInjectable),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (cluster: Cluster) => new ContextHandler(dependencies, cluster);
|
return (cluster: Cluster) => new ContextHandler(dependencies, cluster);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import type { Cluster } from "../../common/cluster/cluster";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { isDevelopment, isWindows } from "../../common/vars";
|
import { isDevelopment, isWindows } from "../../common/vars";
|
||||||
import directoryForBundledBinariesInjectable from "../../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable";
|
import directoryForBundledBinariesInjectable from "../../common/app-paths/directory-for-bundled-binaries/directory-for-bundled-binaries.injectable";
|
||||||
|
import getKubeAuthProxyCertDirInjectable from "./kube-auth-proxy-cert.injectable";
|
||||||
|
|
||||||
const createKubeAuthProxyInjectable = getInjectable({
|
const createKubeAuthProxyInjectable = getInjectable({
|
||||||
id: "create-kube-auth-proxy",
|
id: "create-kube-auth-proxy",
|
||||||
@ -17,6 +18,7 @@ const createKubeAuthProxyInjectable = getInjectable({
|
|||||||
const proxyPath = isDevelopment ? path.join("client", process.platform, process.arch) : process.arch;
|
const proxyPath = isDevelopment ? path.join("client", process.platform, process.arch) : process.arch;
|
||||||
const dependencies = {
|
const dependencies = {
|
||||||
proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), proxyPath, binaryName),
|
proxyBinPath: path.join(di.inject(directoryForBundledBinariesInjectable), proxyPath, binaryName),
|
||||||
|
proxyCertPath: di.inject(getKubeAuthProxyCertDirInjectable),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) =>
|
return (cluster: Cluster, environmentVariables: NodeJS.ProcessEnv) =>
|
||||||
|
|||||||
19
src/main/kube-auth-proxy/kube-auth-proxy-cert.injectable.ts
Normal file
19
src/main/kube-auth-proxy/kube-auth-proxy-cert.injectable.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import directoryForUserDataInjectable from "../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
|
import { createKubeAuthProxyCertificateFiles, getKubeAuthProxyCertificatePath } from "./kube-auth-proxy-cert";
|
||||||
|
|
||||||
|
const getKubeAuthProxyCertDirInjectable = getInjectable({
|
||||||
|
id: "get-kube-auth-proxy-cert-dir",
|
||||||
|
|
||||||
|
setup: async (di) => {
|
||||||
|
await createKubeAuthProxyCertificateFiles(getKubeAuthProxyCertificatePath(await di.inject(directoryForUserDataInjectable)));
|
||||||
|
},
|
||||||
|
|
||||||
|
instantiate: (di) => getKubeAuthProxyCertificatePath(di.inject(directoryForUserDataInjectable)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default getKubeAuthProxyCertDirInjectable;
|
||||||
47
src/main/kube-auth-proxy/kube-auth-proxy-cert.ts
Normal file
47
src/main/kube-auth-proxy/kube-auth-proxy-cert.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { access, mkdir, writeFile } from "fs/promises";
|
||||||
|
import path from "path";
|
||||||
|
import * as selfsigned from "selfsigned";
|
||||||
|
|
||||||
|
export function getKubeAuthProxyCertificate(): selfsigned.SelfSignedCert {
|
||||||
|
const opts = [
|
||||||
|
{ name: "commonName", value: "Lens Certificate Authority" },
|
||||||
|
{ name: "organizationName", value: "Lens" },
|
||||||
|
];
|
||||||
|
|
||||||
|
return selfsigned.generate(opts, {
|
||||||
|
keySize: 2048,
|
||||||
|
algorithm: "sha256",
|
||||||
|
days: 365,
|
||||||
|
extensions: [
|
||||||
|
{ name: "basicConstraints", cA: true },
|
||||||
|
{ name: "subjectAltName", altNames: [
|
||||||
|
{ type: 2, value: "localhost" },
|
||||||
|
{ type: 7, ip: "127.0.0.1" },
|
||||||
|
] },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getKubeAuthProxyCertificatePath(baseDir: string) {
|
||||||
|
return path.join(baseDir, "kube-auth-proxy");
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createKubeAuthProxyCertificateFiles(dir: string): Promise<string> {
|
||||||
|
const cert = getKubeAuthProxyCertificate();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await access(dir);
|
||||||
|
} catch {
|
||||||
|
await mkdir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
await writeFile(path.join(dir, "proxy.key"), cert.private);
|
||||||
|
await writeFile(path.join(dir, "proxy.crt"), cert.cert);
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
@ -15,6 +15,7 @@ const startingServeRegex = /starting to serve on (?<address>.+)/i;
|
|||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
proxyBinPath: string;
|
proxyBinPath: string;
|
||||||
|
proxyCertPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class KubeAuthProxy {
|
export class KubeAuthProxy {
|
||||||
@ -42,6 +43,7 @@ export class KubeAuthProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const proxyBin = this.dependencies.proxyBinPath;
|
const proxyBin = this.dependencies.proxyBinPath;
|
||||||
|
const certPath = await this.dependencies.proxyCertPath;
|
||||||
|
|
||||||
this.proxyProcess = spawn(proxyBin, [], {
|
this.proxyProcess = spawn(proxyBin, [], {
|
||||||
env: {
|
env: {
|
||||||
@ -49,6 +51,7 @@ export class KubeAuthProxy {
|
|||||||
KUBECONFIG: this.cluster.kubeConfigPath,
|
KUBECONFIG: this.cluster.kubeConfigPath,
|
||||||
KUBECONFIG_CONTEXT: this.cluster.contextName,
|
KUBECONFIG_CONTEXT: this.cluster.contextName,
|
||||||
API_PREFIX: this.apiPrefix,
|
API_PREFIX: this.apiPrefix,
|
||||||
|
CERT_PATH: certPath,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.proxyProcess.on("error", (error) => {
|
this.proxyProcess.on("error", (error) => {
|
||||||
|
|||||||
26
types/selfsigned.d.ts
vendored
Normal file
26
types/selfsigned.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module "selfsigned" {
|
||||||
|
export type SelfSignedCert = {
|
||||||
|
private: string;
|
||||||
|
public: string;
|
||||||
|
cert: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type GenerateAttributes = Array<any>;
|
||||||
|
|
||||||
|
type GenerateOptions = {
|
||||||
|
keySize?: number;
|
||||||
|
days?: number;
|
||||||
|
algorithm?: "sha1" | "sha256";
|
||||||
|
extensions?: any;
|
||||||
|
pkcs7?: boolean;
|
||||||
|
clientCertificate?: boolean;
|
||||||
|
clientCertificateCN?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function generate(GenerateAttributes, GenerateOptions): SelfSignedCert;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user