mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
move kubeconfig route
Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
parent
9c9196e4de
commit
f0716e7a28
@ -14,6 +14,7 @@ import { UserManagement } from "./+user-management/user-management";
|
|||||||
import { ConfirmDialog } from "./confirm-dialog";
|
import { ConfirmDialog } from "./confirm-dialog";
|
||||||
import { usersManagementRoute } from "./+user-management/user-management.routes";
|
import { usersManagementRoute } from "./+user-management/user-management.routes";
|
||||||
import { clusterRoute, clusterURL } from "./+cluster";
|
import { clusterRoute, clusterURL } from "./+cluster";
|
||||||
|
import { KubeConfigDialog } from "./kubeconfig-dialog/kubeconfig-dialog";
|
||||||
import { Nodes, nodesRoute } from "./+nodes";
|
import { Nodes, nodesRoute } from "./+nodes";
|
||||||
import { Workloads, workloadsRoute, workloadsURL } from "./+workloads";
|
import { Workloads, workloadsRoute, workloadsURL } from "./+workloads";
|
||||||
import { Namespaces, namespacesRoute } from "./+namespaces";
|
import { Namespaces, namespacesRoute } from "./+namespaces";
|
||||||
@ -70,6 +71,7 @@ class App extends React.Component {
|
|||||||
<KubeObjectDetails/>
|
<KubeObjectDetails/>
|
||||||
<Notifications/>
|
<Notifications/>
|
||||||
<ConfirmDialog/>
|
<ConfirmDialog/>
|
||||||
|
<KubeConfigDialog/>
|
||||||
<AddRoleBindingDialog/>
|
<AddRoleBindingDialog/>
|
||||||
<PodLogsDialog/>
|
<PodLogsDialog/>
|
||||||
<DeploymentScaleDialog/>
|
<DeploymentScaleDialog/>
|
||||||
|
|||||||
@ -1,39 +1,20 @@
|
|||||||
// Get cluster info
|
// Get cluster info
|
||||||
|
|
||||||
import config from "../config"
|
|
||||||
import { kubeRequest } from "./kube-request";
|
import { kubeRequest } from "./kube-request";
|
||||||
import { IClusterInfo, IClusterConfigMap } from "../common/cluster"
|
import { IClusterInfo } from "../common/cluster"
|
||||||
|
|
||||||
export async function getClusterInfo(): Promise<IClusterInfo> {
|
export async function getClusterInfo(): Promise<IClusterInfo> {
|
||||||
const [configMap, kubeVersion, pharosVersion] = await Promise.all([
|
const [kubeVersion] = await Promise.all([
|
||||||
getClusterConfigMap().catch(() => ({} as IClusterConfigMap)),
|
|
||||||
getKubeVersion().catch(() => null),
|
getKubeVersion().catch(() => null),
|
||||||
getPharosVersion().catch(() => null),
|
|
||||||
]);
|
]);
|
||||||
return {
|
return {
|
||||||
...configMap,
|
|
||||||
kubeVersion,
|
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() {
|
export async function getKubeVersion() {
|
||||||
const res = await kubeRequest<{ gitVersion: string }>({
|
const res = await kubeRequest<{ gitVersion: string }>({
|
||||||
path: "/version",
|
path: "/version",
|
||||||
});
|
});
|
||||||
return res.gitVersion.slice(1);
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import compression from "compression"
|
|||||||
import helmet from "helmet"
|
import helmet from "helmet"
|
||||||
import morgan from "morgan"
|
import morgan from "morgan"
|
||||||
import { logger } from "../server/utils/logger"
|
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";
|
import { useRequestHeaderToken } from "../server/middlewares";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -25,7 +25,6 @@ app.set('trust proxy', 1); // trust first proxy
|
|||||||
localApis.use(
|
localApis.use(
|
||||||
configRoute(),
|
configRoute(),
|
||||||
readyStateRoute(),
|
readyStateRoute(),
|
||||||
kubeconfigRoute(),
|
|
||||||
kubewatchRoute(),
|
kubewatchRoute(),
|
||||||
metricsRoute()
|
metricsRoute()
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
export * from "./config-route"
|
export * from "./config-route"
|
||||||
export * from "./kubeconfig-route"
|
|
||||||
export * from "./kubewatch-route"
|
export * from "./kubewatch-route"
|
||||||
export * from "./metrics-route"
|
export * from "./metrics-route"
|
||||||
export * from "./ready-state-route"
|
export * from "./ready-state-route"
|
||||||
|
|||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,6 +2,7 @@ import * as http from "http";
|
|||||||
import { Cluster } from "./cluster";
|
import { Cluster } from "./cluster";
|
||||||
import { helmApi } from "./helm-api"
|
import { helmApi } from "./helm-api"
|
||||||
import { resourceApplierApi } from "./resource-applier-api"
|
import { resourceApplierApi } from "./resource-applier-api"
|
||||||
|
import { kubeconfigRoute } from "./routes/kubeconfig"
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const Call = require('@hapi/call');
|
const Call = require('@hapi/call');
|
||||||
@ -65,6 +66,8 @@ export class Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected addRoutes() {
|
protected addRoutes() {
|
||||||
|
this.router.add({ method: 'get', path: '/api/kubeconfig/service-account/{namespace}/{account}' }, kubeconfigRoute.routeServiceAccountRoute.bind(kubeconfigRoute))
|
||||||
|
|
||||||
// Helm API
|
// 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' }, helmApi.listCharts.bind(helmApi))
|
||||||
this.router.add({ method: 'get', path: '/api-helm/v2/charts/{repo}/{chart}' }, helmApi.getChart.bind(helmApi))
|
this.router.add({ method: 'get', path: '/api-helm/v2/charts/{repo}/{chart}' }, helmApi.getChart.bind(helmApi))
|
||||||
|
|||||||
58
src/main/routes/kubeconfig.ts
Normal file
58
src/main/routes/kubeconfig.ts
Normal file
@ -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()
|
||||||
Loading…
Reference in New Issue
Block a user