mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Inject Host header to k8s client requests (#887)
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
ec4d859ef7
commit
c2afd026cc
@ -204,6 +204,7 @@
|
||||
"semver": "^7.3.2",
|
||||
"serializr": "^2.0.3",
|
||||
"shell-env": "^3.0.0",
|
||||
"spdy": "^4.0.2",
|
||||
"tar": "^6.0.2",
|
||||
"tcp-port-used": "^1.0.1",
|
||||
"tempy": "^0.5.0",
|
||||
@ -248,6 +249,7 @@
|
||||
"@types/request-promise-native": "^1.0.17",
|
||||
"@types/semver": "^7.2.0",
|
||||
"@types/shelljs": "^0.8.8",
|
||||
"@types/spdy": "^3.4.4",
|
||||
"@types/tcp-port-used": "^1.0.0",
|
||||
"@types/tempy": "^0.3.0",
|
||||
"@types/terser-webpack-plugin": "^3.0.0",
|
||||
|
||||
@ -44,7 +44,7 @@ export class ClusterManager {
|
||||
// lens-server is connecting to 127.0.0.1:<port>/<uid>
|
||||
if (req.headers.host.startsWith("127.0.0.1")) {
|
||||
const clusterId = req.url.split("/")[1]
|
||||
const cluster = clusterStore.getById(clusterId)
|
||||
cluster = clusterStore.getById(clusterId)
|
||||
if (cluster) {
|
||||
// we need to swap path prefix so that request is proxied to kube api
|
||||
req.url = req.url.replace(`/${clusterId}`, apiKubePrefix)
|
||||
|
||||
@ -92,7 +92,7 @@ export class Cluster implements ClusterModel {
|
||||
async init(port: number) {
|
||||
try {
|
||||
this.contextHandler = new ContextHandler(this);
|
||||
this.kubeconfigManager = new KubeconfigManager(this, this.contextHandler);
|
||||
this.kubeconfigManager = new KubeconfigManager(this, this.contextHandler, port);
|
||||
this.kubeProxyUrl = `http://localhost:${port}${apiKubePrefix}`;
|
||||
this.initialized = true;
|
||||
logger.info(`[CLUSTER]: "${this.contextName}" init success`, {
|
||||
|
||||
@ -11,7 +11,7 @@ export class KubeconfigManager {
|
||||
protected configDir = app.getPath("temp")
|
||||
protected tempFile: string;
|
||||
|
||||
constructor(protected cluster: Cluster, protected contextHandler: ContextHandler) {
|
||||
constructor(protected cluster: Cluster, protected contextHandler: ContextHandler, protected port: number) {
|
||||
this.init();
|
||||
}
|
||||
|
||||
@ -28,6 +28,10 @@ export class KubeconfigManager {
|
||||
return this.tempFile;
|
||||
}
|
||||
|
||||
protected resolveProxyUrl() {
|
||||
return `http://127.0.0.1:${this.port}/${this.cluster.id}`
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new "temporary" kubeconfig that point to the kubectl-proxy.
|
||||
* This way any user of the config does not need to know anything about the auth etc. details.
|
||||
@ -42,7 +46,7 @@ export class KubeconfigManager {
|
||||
clusters: [
|
||||
{
|
||||
name: contextName,
|
||||
server: await contextHandler.resolveAuthProxyUrl(),
|
||||
server: this.resolveProxyUrl(),
|
||||
skipTLSVerify: undefined,
|
||||
}
|
||||
],
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import net from "net";
|
||||
import http from "http";
|
||||
import spdy from "spdy";
|
||||
import httpProxy from "http-proxy";
|
||||
import url from "url";
|
||||
import * as WebSocket from "ws"
|
||||
import { apiPrefix, apiKubePrefix } from "../common/vars"
|
||||
import { openShell } from "./node-shell-session";
|
||||
import { Router } from "./router"
|
||||
import { ClusterManager } from "./cluster-manager"
|
||||
import { ContextHandler } from "./context-handler";
|
||||
import { apiKubePrefix } from "../common/vars";
|
||||
import logger from "./logger"
|
||||
|
||||
export class LensProxy {
|
||||
@ -40,37 +41,49 @@ export class LensProxy {
|
||||
|
||||
protected buildCustomProxy(): http.Server {
|
||||
const proxy = this.createProxy();
|
||||
const customProxy = http.createServer((req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
this.handleRequest(proxy, req, res);
|
||||
});
|
||||
customProxy.on("upgrade", (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
|
||||
this.handleWsUpgrade(req, socket, head)
|
||||
});
|
||||
customProxy.on("error", (err) => {
|
||||
const spdyProxy = spdy.createServer({
|
||||
spdy: {
|
||||
plain: true,
|
||||
connection: {
|
||||
autoSpdy31: true
|
||||
}
|
||||
}
|
||||
}, (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
this.handleRequest(proxy, req, res)
|
||||
})
|
||||
spdyProxy.on("upgrade", (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => {
|
||||
if (req.url.startsWith(`${apiPrefix}/?`)) {
|
||||
this.handleWsUpgrade(req, socket, head)
|
||||
} else {
|
||||
if (req.headers.upgrade?.startsWith("SPDY")) {
|
||||
this.handleSpdyProxy(proxy, req, socket, head)
|
||||
} else {
|
||||
socket.end()
|
||||
}
|
||||
}
|
||||
})
|
||||
spdyProxy.on("error", (err) => {
|
||||
logger.error("proxy error", err)
|
||||
});
|
||||
return customProxy;
|
||||
})
|
||||
return spdyProxy
|
||||
}
|
||||
|
||||
protected async handleSpdyProxy(proxy: httpProxy, req: http.IncomingMessage, socket: net.Socket, head: Buffer) {
|
||||
const cluster = this.clusterManager.getClusterForRequest(req)
|
||||
if (cluster) {
|
||||
const proxyUrl = await cluster.contextHandler.resolveAuthProxyUrl() + req.url.replace(apiKubePrefix, "")
|
||||
const apiUrl = url.parse(cluster.apiUrl)
|
||||
const res = new http.ServerResponse(req)
|
||||
res.assignSocket(socket)
|
||||
res.setHeader("Location", proxyUrl)
|
||||
res.setHeader("Host", apiUrl.hostname)
|
||||
res.statusCode = 302
|
||||
res.end()
|
||||
}
|
||||
}
|
||||
|
||||
protected createProxy(): httpProxy {
|
||||
const proxy = httpProxy.createProxyServer();
|
||||
proxy.on("proxyRes", (proxyRes, req, res) => {
|
||||
if (req.method !== "GET") {
|
||||
return;
|
||||
}
|
||||
if (proxyRes.statusCode === 502) {
|
||||
const cluster = this.clusterManager.getClusterForRequest(req)
|
||||
const proxyError = cluster?.contextHandler.proxyLastError;
|
||||
if (proxyError) {
|
||||
return res.writeHead(502).end(proxyError);
|
||||
}
|
||||
}
|
||||
const reqId = this.getRequestId(req);
|
||||
if (this.retryCounters.has(reqId)) {
|
||||
logger.debug(`Resetting proxy retry cache for url: ${reqId}`);
|
||||
this.retryCounters.delete(reqId)
|
||||
}
|
||||
})
|
||||
proxy.on("error", (error, req, res, target) => {
|
||||
if (this.closed) {
|
||||
return;
|
||||
|
||||
69
yarn.lock
69
yarn.lock
@ -2156,6 +2156,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
|
||||
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
|
||||
|
||||
"@types/spdy@^3.4.4":
|
||||
version "3.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/spdy/-/spdy-3.4.4.tgz#3282fd4ad8c4603aa49f7017dd520a08a345b2bc"
|
||||
integrity sha512-N9LBlbVRRYq6HgYpPkqQc3a9HJ/iEtVZToW6xlTtJiMhmRJ7jJdV7TaZQJw/Ve/1ePUsQiCTDc4JMuzzag94GA==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/stack-utils@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
|
||||
@ -5922,6 +5929,11 @@ growly@^1.3.0:
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
|
||||
|
||||
handle-thing@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
|
||||
integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
|
||||
|
||||
handlebars@^4.7.6:
|
||||
version "4.7.6"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
|
||||
@ -6108,6 +6120,16 @@ hosted-git-info@^3.0.4:
|
||||
dependencies:
|
||||
lru-cache "^5.1.1"
|
||||
|
||||
hpack.js@^2.1.6:
|
||||
version "2.1.6"
|
||||
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
|
||||
integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=
|
||||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
obuf "^1.0.0"
|
||||
readable-stream "^2.0.1"
|
||||
wbuf "^1.1.0"
|
||||
|
||||
html-encoding-sniffer@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
|
||||
@ -6170,6 +6192,11 @@ http-cache-semantics@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
|
||||
http-deceiver@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||
integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
|
||||
|
||||
http-proxy@^1.18.1:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
|
||||
@ -8636,6 +8663,11 @@ object.pick@^1.3.0:
|
||||
dependencies:
|
||||
isobject "^3.0.1"
|
||||
|
||||
obuf@^1.0.0, obuf@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
|
||||
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
|
||||
|
||||
oidc-token-hash@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/oidc-token-hash/-/oidc-token-hash-3.0.2.tgz#5bd4716cc48ad433f4e4e99276811019b165697e"
|
||||
@ -9753,7 +9785,7 @@ read-pkg@^5.2.0:
|
||||
string_decoder "~1.1.1"
|
||||
util-deprecate "~1.0.1"
|
||||
|
||||
readable-stream@^3.1.1, readable-stream@^3.6.0:
|
||||
readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||
@ -10284,6 +10316,11 @@ scss-tokenizer@^0.2.3:
|
||||
js-base64 "^2.1.8"
|
||||
source-map "^0.4.2"
|
||||
|
||||
select-hose@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
@ -10593,6 +10630,29 @@ spdx-license-ids@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654"
|
||||
integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==
|
||||
|
||||
spdy-transport@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
|
||||
integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
detect-node "^2.0.4"
|
||||
hpack.js "^2.1.6"
|
||||
obuf "^1.1.2"
|
||||
readable-stream "^3.0.6"
|
||||
wbuf "^1.7.3"
|
||||
|
||||
spdy@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
|
||||
integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
handle-thing "^2.0.0"
|
||||
http-deceiver "^1.2.7"
|
||||
select-hose "^2.0.0"
|
||||
spdy-transport "^3.0.0"
|
||||
|
||||
spectron@11.0.0:
|
||||
version "11.0.0"
|
||||
resolved "https://registry.yarnpkg.com/spectron/-/spectron-11.0.0.tgz#79d785e6b8898638e77b5186711e3910ed4ca09b"
|
||||
@ -11783,6 +11843,13 @@ watchpack@^1.6.1:
|
||||
chokidar "^3.4.0"
|
||||
watchpack-chokidar2 "^2.0.0"
|
||||
|
||||
wbuf@^1.1.0, wbuf@^1.7.3:
|
||||
version "1.7.3"
|
||||
resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
|
||||
integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
|
||||
dependencies:
|
||||
minimalistic-assert "^1.0.0"
|
||||
|
||||
wcwidth@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user