From 9a31cbec8b16ff0a7d536df2f01cf7d93639f602 Mon Sep 17 00:00:00 2001 From: Lauri Nevala Date: Tue, 15 Sep 2020 14:14:14 +0300 Subject: [PATCH] Explicitly add Host header to k8s client requests Signed-off-by: Lauri Nevala --- src/main/cluster.ts | 6 ++++++ src/main/routes/watch-route.ts | 24 +++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/cluster.ts b/src/main/cluster.ts index a4ba94a75f..148a8926f8 100644 --- a/src/main/cluster.ts +++ b/src/main/cluster.ts @@ -14,6 +14,7 @@ import { getFeatures, installFeature, uninstallFeature, upgradeFeature } from ". import request, { RequestPromiseOptions } from "request-promise-native" import { apiResources } from "../common/rbac"; import logger from "./logger" +import url, { UrlWithStringQuery } from "url"; export enum ClusterStatus { AccessGranted = 2, @@ -46,6 +47,7 @@ export class Cluster implements ClusterModel { public contextHandler: ContextHandler; protected kubeconfigManager: KubeconfigManager; protected eventDisposers: Function[] = []; + protected clusterUrl: UrlWithStringQuery whenInitialized = when(() => this.initialized); whenReady = when(() => this.ready); @@ -80,6 +82,7 @@ export class Cluster implements ClusterModel { const kubeconfig = this.getKubeconfig() if (kubeconfig.getContextObject(this.contextName)) { this.apiUrl = kubeconfig.getCluster(kubeconfig.getContextObject(this.contextName).cluster).server + this.clusterUrl = url.parse(this.apiUrl) } } @@ -280,6 +283,7 @@ export class Cluster implements ClusterModel { async canI(resourceAttributes: V1ResourceAttributes): Promise { const authApi = this.getProxyKubeconfig().makeApiClient(AuthorizationV1Api) + authApi.defaultHeaders = { Host: this.clusterUrl.hostname } try { const accessReview = await authApi.createSelfSubjectAccessReview({ apiVersion: "authorization.k8s.io/v1", @@ -327,6 +331,7 @@ export class Cluster implements ClusterModel { return 0; } const client = this.getProxyKubeconfig().makeApiClient(CoreV1Api); + client.defaultHeaders = { Host: this.clusterUrl.hostname } try { const response = await client.listEventForAllNamespaces(false, null, null, null, 1000); const uniqEventSources = new Set(); @@ -420,6 +425,7 @@ export class Cluster implements ClusterModel { protected async getAllowedNamespaces() { const api = this.getProxyKubeconfig().makeApiClient(CoreV1Api) + api.defaultHeaders = { Host: this.clusterUrl.hostname } try { const namespaceList = await api.listNamespace() const nsAccessStatuses = await Promise.all( diff --git a/src/main/routes/watch-route.ts b/src/main/routes/watch-route.ts index d88276eaac..91dd7e66bb 100644 --- a/src/main/routes/watch-route.ts +++ b/src/main/routes/watch-route.ts @@ -1,9 +1,21 @@ import { LensApiRequest } from "../router" import { LensApi } from "../lens-api" -import { Watch, KubeConfig } from "@kubernetes/client-node" +import { Watch, KubeConfig, RequestInterface } from "@kubernetes/client-node" import { ServerResponse } from "http" -import { Request } from "request" +import request, { Request, Options, CoreOptions } from "request" import logger from "../logger" +import url from "url" + +class WatchRequestImpl implements RequestInterface { + private opts: CoreOptions + constructor(opts: CoreOptions) { + this.opts = opts + } + public webRequest(opts: request.Options, callback: (err: any, response: request.Response, body: any) => void): any { + opts.headers = Object.assign({}, opts.headers, this.opts.headers) + return request(opts, callback); + } +} class ApiWatcher { private apiUrl: string @@ -13,9 +25,11 @@ class ApiWatcher { private processor: NodeJS.Timeout private eventBuffer: any[] = [] - constructor(apiUrl: string, kubeConfig: KubeConfig, response: ServerResponse) { + constructor(apiUrl: string, clusterUrl: string, kubeConfig: KubeConfig, response: ServerResponse) { this.apiUrl = apiUrl - this.watch = new Watch(kubeConfig) + const opts: CoreOptions = { headers: { Host:url.parse(clusterUrl).hostname}} + const reqImpl = new WatchRequestImpl(opts) + this.watch = new Watch(kubeConfig, reqImpl) this.response = response } @@ -90,7 +104,7 @@ class WatchRoute extends LensApi { logger.debug("watch using kubeconfig:" + JSON.stringify(cluster.getProxyKubeconfig(), null, 2)) apis.forEach(apiUrl => { - const watcher = new ApiWatcher(apiUrl, cluster.getProxyKubeconfig(), response) + const watcher = new ApiWatcher(apiUrl, cluster.apiUrl, cluster.getProxyKubeconfig(), response) watcher.start() watchers.push(watcher) })