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:
Jari Kolehmainen authored and GitHub committed 2023-01-04 19:18:02 +02:00
1 parent fba93b889e
commit 7052dc0dba
35 files changed
+353 -66

No files matched your search

@@ -0,0 +1,23 @@
/**
* 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 { lensProxyCertificateChannel } from "../../common/certificate/lens-proxy-certificate-channel";
import { getRequestChannelListenerInjectable } from "../utils/channel/channel-listeners/listener-tokens";
import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable";
const lensProxyCertificateRequestHandlerInjectable = getRequestChannelListenerInjectable({
channel: lensProxyCertificateChannel,
handler: (di) => {
const lensProxyCertificate = di.inject(lensProxyCertificateInjectable).get() as SelfSignedCert;
return () => ({
cert: lensProxyCertificate.cert,
public: lensProxyCertificate.public,
private: "",
});
},
});
export default lensProxyCertificateRequestHandlerInjectable;
@@ -13,6 +13,7 @@ import lensProxyPortInjectable from "./lens-proxy-port.injectable";
import contentSecurityPolicyInjectable from "../../common/vars/content-security-policy.injectable";
import emitAppEventInjectable from "../../common/app-event-bus/emit-event.injectable";
import loggerInjectable from "../../common/logger.injectable";
import lensProxyCertificateInjectable from "../../common/certificate/lens-proxy-certificate.injectable";
const lensProxyInjectable = getInjectable({
id: "lens-proxy",
@@ -27,6 +28,7 @@ const lensProxyInjectable = getInjectable({
contentSecurityPolicy: di.inject(contentSecurityPolicyInjectable),
emitAppEvent: di.inject(emitAppEventInjectable),
logger: di.inject(loggerInjectable),
certificate: di.inject(lensProxyCertificateInjectable).get(),
}),
});
+17 -7
View File
@@ -4,7 +4,8 @@
*/
import net from "net";
import http from "http";
import https from "https";
import type http from "http";
import type httpProxy from "http-proxy";
import { apiPrefix, apiKubePrefix } from "../../common/vars";
import type { Router } from "../router/router";
@@ -16,6 +17,7 @@ import assert from "assert";
import type { SetRequired } from "type-fest";
import type { EmitAppEvent } from "../../common/app-event-bus/emit-event.injectable";
import type { Logger } from "../../common/logger";
import type { SelfSignedCert } from "selfsigned";
type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined;
@@ -31,6 +33,7 @@ interface Dependencies {
readonly lensProxyPort: { set: (portNumber: number) => void };
readonly contentSecurityPolicy: string;
readonly logger: Logger;
readonly certificate: SelfSignedCert;
}
const watchParam = "watch";
@@ -61,27 +64,33 @@ const disallowedPorts = new Set([
]);
export class LensProxy {
protected proxyServer: http.Server;
protected proxyServer: https.Server;
protected closed = false;
protected retryCounters = new Map<string, number>();
constructor(private readonly dependencies: Dependencies) {
this.configureProxy(dependencies.proxy);
this.proxyServer = http.createServer((req, res) => {
this.handleRequest(req as ServerIncomingMessage, res);
});
this.proxyServer = https.createServer(
{
key: dependencies.certificate.private,
cert: dependencies.certificate.cert,
},
(req, res) => {
this.handleRequest(req as ServerIncomingMessage, res);
},
);
this.proxyServer
.on("upgrade", (req: ServerIncomingMessage, socket: net.Socket, head: Buffer) => {
const cluster = dependencies.getClusterForRequest(req);
const cluster = this.dependencies.getClusterForRequest(req);
if (!cluster) {
this.dependencies.logger.error(`[LENS-PROXY]: Could not find cluster for upgrade request from url=${req.url}`);
socket.destroy();
} else {
const isInternal = req.url.startsWith(`${apiPrefix}?`);
const reqHandler = isInternal ? dependencies.shellApiRequest : dependencies.kubeApiUpgradeRequest;
const reqHandler = isInternal ? this.dependencies.shellApiRequest : this.dependencies.kubeApiUpgradeRequest;
(async () => reqHandler({ req, socket, head, cluster }))()
.catch(error => this.dependencies.logger.error("[LENS-PROXY]: failed to handle proxy upgrade", error));
@@ -157,6 +166,7 @@ export class LensProxy {
close() {
this.dependencies.logger.info("[LENS-PROXY]: Closing server");
this.proxyServer.close();
this.closed = true;
}