mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
/**
|
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
*/
|
|
|
|
import type { KubeConfig } from "@kubernetes/client-node";
|
|
import { dumpConfigYaml } from "../../common/kube-helpers";
|
|
import { isErrnoException } from "@k8slens/utilities";
|
|
import type { PartialDeep } from "type-fest";
|
|
import type { Logger } from "../../common/logger";
|
|
import type { JoinPaths } from "../../common/path/join-paths.injectable";
|
|
import type { GetDirnameOfPath } from "../../common/path/get-dirname.injectable";
|
|
import type { PathExists } from "../../common/fs/path-exists.injectable";
|
|
import type { RemovePath } from "../../common/fs/remove.injectable";
|
|
import type { WriteFile } from "../../common/fs/write-file.injectable";
|
|
import type { SelfSignedCert } from "selfsigned";
|
|
import type { Cluster } from "../../common/cluster/cluster";
|
|
import type { LoadKubeconfig } from "../../common/cluster/load-kubeconfig.injectable";
|
|
import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable";
|
|
|
|
interface KubeconfigManagerDependencies {
|
|
readonly directoryForTemp: string;
|
|
readonly logger: Logger;
|
|
readonly certificate: SelfSignedCert;
|
|
readonly kubeAuthProxyServer: KubeAuthProxyServer;
|
|
readonly kubeAuthProxyUrl: string;
|
|
joinPaths: JoinPaths;
|
|
getDirnameOfPath: GetDirnameOfPath;
|
|
pathExists: PathExists;
|
|
removePath: RemovePath;
|
|
writeFile: WriteFile;
|
|
loadKubeconfig: LoadKubeconfig;
|
|
}
|
|
|
|
export class KubeconfigManager {
|
|
/**
|
|
* The path to the temp config file
|
|
*
|
|
* - if `string` then path
|
|
* - if `null` then not yet created or was cleared
|
|
*/
|
|
protected tempFilePath: string | null = null;
|
|
|
|
constructor(
|
|
private readonly dependencies: KubeconfigManagerDependencies,
|
|
private readonly cluster: Cluster,
|
|
) {}
|
|
|
|
/**
|
|
*
|
|
* @returns The path to the temporary kubeconfig
|
|
*/
|
|
async ensurePath(): Promise<string> {
|
|
if (this.tempFilePath === null || !(await this.dependencies.pathExists(this.tempFilePath))) {
|
|
return await this.ensureFile();
|
|
}
|
|
|
|
return this.tempFilePath;
|
|
}
|
|
|
|
/**
|
|
* Deletes the temporary kubeconfig file
|
|
*/
|
|
async clear(): Promise<void> {
|
|
if (!this.tempFilePath) {
|
|
return;
|
|
}
|
|
|
|
this.dependencies.logger.info(`[KUBECONFIG-MANAGER]: Deleting temporary kubeconfig: ${this.tempFilePath}`);
|
|
|
|
try {
|
|
await this.dependencies.removePath(this.tempFilePath);
|
|
} catch (error) {
|
|
if (isErrnoException(error) && error.code !== "ENOENT") {
|
|
throw error;
|
|
}
|
|
} finally {
|
|
this.tempFilePath = null;
|
|
}
|
|
}
|
|
|
|
protected async ensureFile() {
|
|
try {
|
|
await this.dependencies.kubeAuthProxyServer.ensureRunning();
|
|
|
|
return this.tempFilePath = await this.createProxyKubeconfig();
|
|
} catch (error) {
|
|
throw new Error(`Failed to create temp config for auth-proxy: ${error}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
protected async createProxyKubeconfig(): Promise<string> {
|
|
const { id, preferences: { defaultNamespace }} = this.cluster;
|
|
const contextName = this.cluster.contextName.get();
|
|
const tempFile = this.dependencies.joinPaths(
|
|
this.dependencies.directoryForTemp,
|
|
`kubeconfig-${id}`,
|
|
);
|
|
const kubeConfig = await this.dependencies.loadKubeconfig();
|
|
const proxyConfig: PartialDeep<KubeConfig> = {
|
|
currentContext: contextName,
|
|
clusters: [
|
|
{
|
|
name: contextName,
|
|
server: this.dependencies.kubeAuthProxyUrl,
|
|
skipTLSVerify: false,
|
|
caData: Buffer.from(this.dependencies.certificate.cert).toString("base64"),
|
|
},
|
|
],
|
|
users: [
|
|
{ name: "proxy", username: "lens", password: "fake" },
|
|
],
|
|
contexts: [
|
|
{
|
|
user: "proxy",
|
|
name: contextName,
|
|
cluster: contextName,
|
|
namespace: defaultNamespace || kubeConfig.getContextObject(contextName)?.namespace,
|
|
},
|
|
],
|
|
};
|
|
// write
|
|
const configYaml = dumpConfigYaml(proxyConfig);
|
|
|
|
await this.dependencies.writeFile(tempFile, configYaml, { mode: 0o600 });
|
|
this.dependencies.logger.debug(`[KUBECONFIG-MANAGER]: Created temp kubeconfig "${contextName}" at "${tempFile}": \n${configYaml}`);
|
|
|
|
return tempFile;
|
|
}
|
|
}
|