mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Lens proxy with TLS (#6851)
* lens proxy tls support Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * integration test fix Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * don't override getRequestOptions if they are set Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * fix electronAppInjectable override Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * use runnables on renderer Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * move certificate generation to runnables Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> * simplify Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com> Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
1 parent
fba93b889e
commit
7052dc0dba
35 files changed
+353
-66
No files matched your search
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
import { getRequestChannel } from "../utils/channel/get-request-channel";
|
||||
|
||||
export const lensProxyCertificateChannel = getRequestChannel<void, SelfSignedCert>("request-lens-proxy-certificate");
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { getGlobalOverride } from "../test-utils/get-global-override";
|
||||
import lensProxyCertificateInjectable from "./lens-proxy-certificate.injectable";
|
||||
|
||||
export default getGlobalOverride(lensProxyCertificateInjectable, () => {
|
||||
return {
|
||||
get: () => ({
|
||||
public: "<public-data>",
|
||||
private: "<private-data>",
|
||||
cert: "<ca-data>",
|
||||
}),
|
||||
set: () => {},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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 type { SelfSignedCert } from "selfsigned";
|
||||
|
||||
const lensProxyCertificateInjectable = getInjectable({
|
||||
id: "lens-proxy-certificate",
|
||||
instantiate: () => {
|
||||
let certState: SelfSignedCert;
|
||||
const cert = {
|
||||
get: () => {
|
||||
if (!certState) {
|
||||
throw "certificate has not been set";
|
||||
}
|
||||
|
||||
return certState;
|
||||
},
|
||||
set: (certificate: SelfSignedCert) => {
|
||||
if (certState) {
|
||||
throw "certificate has already been set";
|
||||
}
|
||||
|
||||
certState = certificate;
|
||||
},
|
||||
};
|
||||
|
||||
return cert;
|
||||
},
|
||||
});
|
||||
|
||||
export default lensProxyCertificateInjectable;
|
||||
@@ -3,7 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { Agent } from "https";
|
||||
import type { RequestInit } from "node-fetch";
|
||||
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
|
||||
import fetchInjectable from "../fetch/fetch.injectable";
|
||||
import loggerInjectable from "../logger.injectable";
|
||||
import type { JsonApiConfig, JsonApiData, JsonApiDependencies, JsonApiParams } from "./json-api";
|
||||
@@ -18,8 +20,23 @@ const createJsonApiInjectable = getInjectable({
|
||||
fetch: di.inject(fetchInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
const lensProxyCert = di.inject(lensProxyCertificateInjectable);
|
||||
|
||||
return (config, reqInit) => new JsonApi(deps, config, reqInit);
|
||||
return (config, reqInit) => {
|
||||
if (!config.getRequestOptions) {
|
||||
config.getRequestOptions = async () => {
|
||||
const agent = new Agent({
|
||||
ca: lensProxyCert.get().cert,
|
||||
});
|
||||
|
||||
return {
|
||||
agent,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return new JsonApi(deps, config, reqInit);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ const createKubeApiForClusterInjectable = getInjectable({
|
||||
debug: isDevelopment,
|
||||
}, {
|
||||
headers: {
|
||||
"Host": `${cluster.metadata.uid}.localhost:${new URL(apiBase.config.serverAddress).port}`,
|
||||
"Host": `${cluster.metadata.uid}.lens.app:${new URL(apiBase.config.serverAddress).port}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { Agent } from "https";
|
||||
import type { RequestInit } from "node-fetch";
|
||||
import lensProxyCertificateInjectable from "../certificate/lens-proxy-certificate.injectable";
|
||||
import fetchInjectable from "../fetch/fetch.injectable";
|
||||
import loggerInjectable from "../logger.injectable";
|
||||
import type { JsonApiConfig, JsonApiDependencies } from "./json-api";
|
||||
@@ -18,8 +20,23 @@ const createKubeJsonApiInjectable = getInjectable({
|
||||
fetch: di.inject(fetchInjectable),
|
||||
logger: di.inject(loggerInjectable),
|
||||
};
|
||||
const lensProxyCert = di.inject(lensProxyCertificateInjectable);
|
||||
|
||||
return (config, reqInit) => new KubeJsonApi(dependencies, config, reqInit);
|
||||
return (config, reqInit) => {
|
||||
if (!config.getRequestOptions) {
|
||||
config.getRequestOptions = async () => {
|
||||
const agent = new Agent({
|
||||
ca: lensProxyCert.get().cert,
|
||||
});
|
||||
|
||||
return {
|
||||
agent,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return new KubeJsonApi(dependencies, config, reqInit);
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export interface IKubeApiParsed extends IKubeApiLinkRef {
|
||||
}
|
||||
|
||||
export function parseKubeApi(path: string): IKubeApiParsed {
|
||||
const apiPath = new URL(path, "http://localhost").pathname;
|
||||
const apiPath = new URL(path, "https://localhost").pathname;
|
||||
const [, prefix, ...parts] = apiPath.split("/");
|
||||
const apiPrefix = `/${prefix}`;
|
||||
const [left, right, namespaced] = splitArray(parts, "namespaces");
|
||||
|
||||
@@ -9,22 +9,22 @@ describe("getClusterIdFromHost", () => {
|
||||
const clusterFakeId = "fe540901-0bd6-4f6c-b472-bce1559d7c4a";
|
||||
|
||||
it("should return undefined for non cluster frame hosts", () => {
|
||||
expect(getClusterIdFromHost("localhost:45345")).toBeUndefined();
|
||||
expect(getClusterIdFromHost("lens.app:45345")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should return ClusterId for cluster frame hosts", () => {
|
||||
expect(getClusterIdFromHost(`${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
});
|
||||
|
||||
it("should return ClusterId for cluster frame hosts with additional subdomains", () => {
|
||||
expect(getClusterIdFromHost(`abc.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.lens.app:59110`)).toBe(clusterFakeId);
|
||||
});
|
||||
});
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import requestPromise from "request-promise-native";
|
||||
|
||||
export async function getAppVersionFromProxyServer(proxyPort: number): Promise<string> {
|
||||
const response = await requestPromise({
|
||||
method: "GET",
|
||||
uri: `http://127.0.0.1:${proxyPort}/version`,
|
||||
resolveWithFullResponse: true,
|
||||
proxy: undefined,
|
||||
});
|
||||
|
||||
return JSON.parse(response.body).version;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { RequestChannel } from "./request-channel-listener-injection-token";
|
||||
|
||||
export const getRequestChannel = <Request, Response>(id: string): RequestChannel<Request, Response> => ({
|
||||
id,
|
||||
});
|
||||
@@ -14,7 +14,7 @@ export function getClusterIdFromHost(host: string): ClusterId | undefined {
|
||||
// e.g host == "%clusterId.localhost:45345"
|
||||
const subDomains = host.split(":")[0].split(".");
|
||||
|
||||
return subDomains.slice(-2, -1)[0]; // ClusterId or undefined
|
||||
return subDomains.slice(-3, -2)[0]; // ClusterId or undefined
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
export * from "./abort-controller";
|
||||
export * from "./app-version";
|
||||
export * from "./autobind";
|
||||
export * from "./camelCase";
|
||||
export * from "./cluster-id-url-parsing";
|
||||
|
||||
Reference in new issue
Block a user