diff --git a/dashboard/client/components/app.tsx b/dashboard/client/components/app.tsx
index 882bcdfcab..b07d72749c 100755
--- a/dashboard/client/components/app.tsx
+++ b/dashboard/client/components/app.tsx
@@ -14,6 +14,7 @@ import { UserManagement } from "./+user-management/user-management";
import { ConfirmDialog } from "./confirm-dialog";
import { usersManagementRoute } from "./+user-management/user-management.routes";
import { clusterRoute, clusterURL } from "./+cluster";
+import { KubeConfigDialog } from "./kubeconfig-dialog/kubeconfig-dialog";
import { Nodes, nodesRoute } from "./+nodes";
import { Workloads, workloadsRoute, workloadsURL } from "./+workloads";
import { Namespaces, namespacesRoute } from "./+namespaces";
@@ -70,6 +71,7 @@ class App extends React.Component {
+
diff --git a/dashboard/server/api/get-cluster-info.ts b/dashboard/server/api/get-cluster-info.ts
index c24178741a..339e225245 100644
--- a/dashboard/server/api/get-cluster-info.ts
+++ b/dashboard/server/api/get-cluster-info.ts
@@ -1,39 +1,20 @@
// Get cluster info
-import config from "../config"
import { kubeRequest } from "./kube-request";
-import { IClusterInfo, IClusterConfigMap } from "../common/cluster"
+import { IClusterInfo } from "../common/cluster"
export async function getClusterInfo(): Promise {
- const [configMap, kubeVersion, pharosVersion] = await Promise.all([
- getClusterConfigMap().catch(() => ({} as IClusterConfigMap)),
+ const [kubeVersion] = await Promise.all([
getKubeVersion().catch(() => null),
- getPharosVersion().catch(() => null),
]);
return {
- ...configMap,
kubeVersion,
- pharosVersion,
};
}
-export async function getClusterConfigMap() {
- const res = await kubeRequest<{ data: IClusterConfigMap }>({
- path: `/api/v1/namespaces/${config.LENS_NAMESPACE}/configmaps/config`,
- });
- return res.data;
-}
-
export async function getKubeVersion() {
const res = await kubeRequest<{ gitVersion: string }>({
path: "/version",
});
return res.gitVersion.slice(1);
}
-
-export async function getPharosVersion() {
- const res = await kubeRequest<{ data: { "pharos-version": string } }>({
- path: `/api/v1/namespaces/kube-system/configmaps/pharos-config`,
- });
- return res ? res.data["pharos-version"] : null;
-}
diff --git a/dashboard/server/app.ts b/dashboard/server/app.ts
index 73da918e89..6de90d466a 100644
--- a/dashboard/server/app.ts
+++ b/dashboard/server/app.ts
@@ -8,7 +8,7 @@ import compression from "compression"
import helmet from "helmet"
import morgan from "morgan"
import { logger } from "../server/utils/logger"
-import { configRoute, kubeconfigRoute, kubewatchRoute, metricsRoute, readyStateRoute } from "../server/routes";
+import { configRoute, kubewatchRoute, metricsRoute, readyStateRoute } from "../server/routes";
import { useRequestHeaderToken } from "../server/middlewares";
const {
@@ -25,7 +25,6 @@ app.set('trust proxy', 1); // trust first proxy
localApis.use(
configRoute(),
readyStateRoute(),
- kubeconfigRoute(),
kubewatchRoute(),
metricsRoute()
);
diff --git a/dashboard/server/routes/index.ts b/dashboard/server/routes/index.ts
index d7ca1a4cb1..3b2fdaaf8b 100644
--- a/dashboard/server/routes/index.ts
+++ b/dashboard/server/routes/index.ts
@@ -1,5 +1,4 @@
export * from "./config-route"
-export * from "./kubeconfig-route"
export * from "./kubewatch-route"
export * from "./metrics-route"
export * from "./ready-state-route"
diff --git a/dashboard/server/routes/kubeconfig-route.ts b/dashboard/server/routes/kubeconfig-route.ts
deleted file mode 100644
index 9ed0f445e6..0000000000
--- a/dashboard/server/routes/kubeconfig-route.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-//-- Kubeconfig route
-
-import { Router } from "express";
-import { AxiosError } from "axios";
-import { userSession } from "../user-session";
-import { kubeRequest } from "../api/kube-request";
-import { Secret } from "../../client/api/endpoints";
-import { base64 } from "../../client/utils/base64";
-import { getCertificateAuthorityData } from "../api/get-cert-auth-data";
-import { getClusterConfigMap } from "../api/get-cluster-info";
-
-interface IKubeConfigParams {
- username: string;
- authToken: string;
- certificateAuthority: string;
- namespace?: string;
-}
-
-export function kubeconfigRoute() {
- const router = Router();
-
- router.route('/kubeconfig/user')
- .get(async (req, res) => {
- const { username = "kubernetes" } = userSession.get(req);
- const authToken = userSession.getToken(req);
- const cert = await getCertificateAuthorityData('base64');
- const data = await generateKubeConfig({
- username,
- authToken: authToken,
- certificateAuthority: cert
- });
- res.json(data);
- });
-
- router.route('/kubeconfig/service-account/:namespace/:account')
- .get(async (req, res) => {
- const { authHeader } = userSession.get(req);
- const { namespace, account } = req.params;
- try {
- const secret = await kubeRequest<{ items: Secret[] }>({
- path: `/api/v1/namespaces/${namespace}/secrets`,
- authHeader: authHeader,
- }).then(secrets => {
- return secrets.items.find(secret => {
- const { annotations } = secret.metadata;
- return annotations && annotations["kubernetes.io/service-account.name"] == account;
- });
- });
- const data = await generateKubeConfig({
- username: account,
- namespace: namespace,
- authToken: base64.decode(secret.data.token),
- certificateAuthority: secret.data["ca.crt"],
- });
- res.json(data);
- } catch (err) {
- const { response }: AxiosError = err;
- res.status(403).json(response ? response.data : err.toString());
- }
- });
-
- return router;
-}
-
-async function generateKubeConfig(params: IKubeConfigParams) {
- const { clusterName, clusterUrl } = await getClusterConfigMap();
- const { authToken, username, certificateAuthority, namespace = "" } = params;
- return {
- 'apiVersion': 'v1',
- 'kind': 'Config',
- 'clusters': [
- {
- 'name': clusterName,
- 'cluster': {
- 'server': clusterUrl,
- 'certificate-authority-data': certificateAuthority
- }
- }
- ],
- 'users': [
- {
- 'name': username,
- 'user': {
- 'token': authToken,
- }
- }
- ],
- 'contexts': [
- {
- 'name': clusterName,
- 'context': {
- 'user': username,
- 'cluster': clusterName,
- 'namespace': namespace,
- }
- }
- ],
- 'current-context': clusterName
- }
-}
diff --git a/src/main/router.ts b/src/main/router.ts
index 04abad4c7c..7093189f2c 100644
--- a/src/main/router.ts
+++ b/src/main/router.ts
@@ -2,6 +2,7 @@ import * as http from "http";
import { Cluster } from "./cluster";
import { helmApi } from "./helm-api"
import { resourceApplierApi } from "./resource-applier-api"
+import { kubeconfigRoute } from "./routes/kubeconfig"
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Call = require('@hapi/call');
@@ -65,6 +66,8 @@ export class Router {
}
protected addRoutes() {
+ this.router.add({ method: 'get', path: '/api/kubeconfig/service-account/{namespace}/{account}' }, kubeconfigRoute.routeServiceAccountRoute.bind(kubeconfigRoute))
+
// Helm API
this.router.add({ method: 'get', path: '/api-helm/v2/charts' }, helmApi.listCharts.bind(helmApi))
this.router.add({ method: 'get', path: '/api-helm/v2/charts/{repo}/{chart}' }, helmApi.getChart.bind(helmApi))
diff --git a/src/main/routes/kubeconfig.ts b/src/main/routes/kubeconfig.ts
new file mode 100644
index 0000000000..6a6f173f3a
--- /dev/null
+++ b/src/main/routes/kubeconfig.ts
@@ -0,0 +1,58 @@
+import { LensApiRequest } from "../router"
+import { LensApi } from "../lens-api"
+import { Cluster } from "../cluster"
+import { CoreV1Api, V1Secret } from "@kubernetes/client-node"
+
+function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster) {
+ const tokenData = new Buffer(secret.data["token"], "base64")
+ return {
+ 'apiVersion': 'v1',
+ 'kind': 'Config',
+ 'clusters': [
+ {
+ 'name': cluster.contextName,
+ 'cluster': {
+ 'server': cluster.contextHandler.kc.getCurrentCluster().server,
+ 'certificate-authority-data': secret.data["ca.crt"]
+ }
+ }
+ ],
+ 'users': [
+ {
+ 'name': username,
+ 'user': {
+ 'token': tokenData.toString("utf8"),
+ }
+ }
+ ],
+ 'contexts': [
+ {
+ 'name': cluster.contextName,
+ 'context': {
+ 'user': username,
+ 'cluster': cluster.contextName,
+ 'namespace': secret.metadata.namespace,
+ }
+ }
+ ],
+ 'current-context': cluster.contextName
+ }
+}
+
+class KubeconfigRoute extends LensApi {
+
+ public async routeServiceAccountRoute(request: LensApiRequest) {
+ const { params, response, cluster} = request
+
+ const client = cluster.contextHandler.kc.makeApiClient(CoreV1Api);
+ const secretList = await client.listNamespacedSecret(params.namespace)
+ const secret = secretList.body.items.find(secret => {
+ const { annotations } = secret.metadata;
+ return annotations && annotations["kubernetes.io/service-account.name"] == params.account;
+ });
+ const data = generateKubeConfig(params.account, secret, cluster);
+ this.respondJson(response, data)
+ }
+}
+
+export const kubeconfigRoute = new KubeconfigRoute()