Skip to content

Commit 0dd12be

Browse files
committed
added key vault keys mao
1 parent 67d94e1 commit 0dd12be

File tree

14 files changed

+587
-37
lines changed

14 files changed

+587
-37
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12+
"@azure/identity": "^4.8.0",
13+
"@azure/keyvault-secrets": "^4.9.0",
1214
"@kubernetes/client-node": "^1.1.0",
1315
"axios": "^1.8.4",
1416
"bootstrap": "5.3.3",

src/app/page.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import { workLoads } from "@/setting";
44
import DeploymentTab from "@/components/deployment/main";
55
import ConfigMapTab from "@/components/configmap";
66
import { getWorkLoadData, saveWorkLoadData } from "@/functions/localstorage";
7+
import KeyVaultTab from "@/components/keyvault";
78

89
const tabs = ["Deployments", "Config Map", "Key Vault"];
910

1011
export default function Home() {
1112
const [loading, setLoading] = useState<boolean>(true);
1213
const [workLoadOne, setWorkLoadOne] = useState<string>('');
1314
const [workLoadTwo, setWorkLoadTwo] = useState<string>('');
14-
const [activeTab, setActiveTab] = useState(tabs[1]);
15+
const [activeTab, setActiveTab] = useState(tabs[0]);
1516

1617
const setWorkLoadValueOne = (e: any) => {
1718
setWorkLoadOne(e.target.value);
@@ -89,7 +90,7 @@ export default function Home() {
8990
<div className="mt-4 tab body">
9091
{activeTab === "Deployments" && <DeploymentTab workLoadOne={workLoadOne} workLoadTwo={workLoadTwo} loading={loading} closeLoading={closeLoading} />}
9192
{activeTab === "Config Map" && <ConfigMapTab loading={loading} closeLoading={closeLoading} workLoadOne={workLoadOne} workLoadTwo={workLoadTwo}/>}
92-
{activeTab === "Key Vault" && <p>📜 Key vaults</p>}
93+
{activeTab === "Key Vault" && <KeyVaultTab/>}
9394
</div>
9495
</div>
9596
</main>

src/components/configmap/tables/configItemList.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11

2-
import { getDeploymentStatus } from "@/functions";
3-
42
const ConfigMapDeploymentListItems = ({ deployment, index }: { deployment: any,index: number }) => {
53
return (
64
<tr><td className="border border-gray-300 px-4 py-2">{index+1}</td> </tr>

src/components/configmap/tables/deploymentItem.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { getDeploymentStatus } from "@/functions";
21

32
const ConfigMapDeploymentList = ({ deployment, index }: { deployment: any, index: number }) => {
4-
5-
console.log("deploymentcmap", deployment)
63
return (
74
<>
85
<tr>

src/components/keyvault/index.tsx

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { getKvData, saveKvData } from "@/functions/localstorage";
2+
import httpRequest from "axios";
3+
import { useEffect, useState } from "react";
4+
import KeyVaultsDetail from "./table/listkv";
5+
import { findKv, findName } from "@/functions";
6+
import CompareKv from "./kvValues";
7+
8+
const KeyVaultTab = (props: any) => {
9+
const { workLoadOne, workLoadTwo, loading } = props;
10+
const [keyVaults, setData] = useState<any | null>([]);
11+
const [kvKeys, setKvKeys] = useState<any>([]);
12+
const [kvSelected, setKvSelected] = useState("");
13+
const [selectedKey, setSelectedKey] = useState([]);
14+
15+
const getKeyVaults = async (props: any) => {
16+
let queryString = [
17+
props.workLoadOne ? `workload1=${props.workLoadOne}` : '',
18+
props.workLoadTwo ? `workload2=${props.workLoadTwo}` : ''
19+
].filter(Boolean).join('&');
20+
try {
21+
const response = await httpRequest.get(`/api/keyvault?`);
22+
// saveDeploymentsData(response.data);
23+
setData(response.data);
24+
saveKvData(response.data);
25+
// setDataDiff(findDifferentNamesInList(response.data as unknown as any));
26+
27+
// if (response && response.data && response.data.length > 0) {
28+
// props.closeLoading(false);ss
29+
// }
30+
} catch (error) {
31+
console.error('Error fetching deployments:', error);
32+
props.closeLoading(false);
33+
}
34+
35+
};
36+
37+
const setKeyName = (e: any) => {
38+
setKvSelected(e.target.value);
39+
}
40+
const getFromLc = () => {
41+
const kvData = getKvData();
42+
const getKeys = kvData[0];
43+
setKvKeys(Object.keys(getKeys).map((item) => item));
44+
setData(kvData);
45+
}
46+
47+
useEffect(() => {
48+
getFromLc();
49+
}, []);
50+
51+
if (!keyVaults.length || !kvKeys.length) {
52+
return;
53+
}
54+
return (
55+
<>
56+
<div>
57+
<select onChange={setKeyName} className="p-2 text-l bg-gray-100 rounded-lg">
58+
<option value="">Choose Keys </option>
59+
{
60+
kvKeys && kvKeys.map((keys: string, index: number) => (
61+
<option value={keys} key={index}>{keys}</option>
62+
))
63+
}
64+
</select>
65+
<CompareKv selectedKey={kvSelected} deployments={keyVaults} />
66+
</div>
67+
<div className="flex flex-row p-2 gap-8">
68+
{
69+
keyVaults.map((deployment: any, index: number) => (
70+
<div key={index} className="flex flex-col gap-2">
71+
72+
<h3 className="font-bold flex-row text-l p-2">
73+
{`${index + 1}.`} <span className="text-blue-500"> {index == 0 ? findKv(workLoadOne || workLoadTwo) : findKv(workLoadTwo)} </span> <small className="text-sm">({index == 0 ? workLoadOne || workLoadTwo : workLoadTwo})</small>
74+
&nbsp; <small className="text-xs font-light text-green-500">{loading ? "Loading..." : ""}</small>
75+
</h3>
76+
<div className="flex flex-col gap-2">
77+
<KeyVaultsDetail deployments={deployment} title="Keys" />
78+
</div>
79+
</div>
80+
))
81+
}
82+
</div>
83+
</>
84+
85+
)
86+
}
87+
88+
export default KeyVaultTab;

src/components/keyvault/kvValues.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import KvFullDetail from "./table/itemfulldetail";
2+
3+
const CompareKv = (props: any) => {
4+
const { deployments, selectedKey } = props;
5+
const arrayData = Object.entries(deployments);
6+
return (
7+
<div className="flex flex-row p-2 gap-8 flex-text-wrap">
8+
9+
{arrayData.map((deployment: any, index: number) => (
10+
<KvFullDetail key={index} index={index} deployment={deployment} selectedKey={selectedKey} />
11+
))}
12+
13+
</div>);
14+
};
15+
16+
export default CompareKv;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const KvFullDetail = ({ deployment, index, selectedKey }: { deployment: any, index: number, selectedKey: any }) => {
2+
let allKeys = []
3+
try {
4+
allKeys = selectedKey ? Object.entries(JSON.parse(atob(deployment[1][selectedKey]))) : [];
5+
} catch (error: any) {
6+
return <>{error.message}</>
7+
}
8+
9+
return (
10+
<div>
11+
<table className="w-full table-auto border-collapse border border-gray-300 mt-2 text-sm">
12+
<tbody>
13+
{
14+
allKeys.map((item: any, index: number) => {
15+
return <tr key={index}>
16+
<td className="border border-gray-300 px-4 py-2">{index + 1}</td>
17+
<td className="border border-gray-300 px-4 py-2">{item[0]}</td>
18+
<td className="border border-gray-300 px-4 py-2 text-wrap"></td>
19+
</tr>
20+
})
21+
}
22+
23+
</tbody>
24+
</table>
25+
</div>
26+
)
27+
}
28+
29+
export default KvFullDetail;
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const KeyVaultItem = ({ deployment, index }: { deployment: any,index: number }) => {
2+
return (
3+
<tr>
4+
<td className="border border-gray-300 px-4 py-2">{index+1}</td>
5+
<td className="border border-gray-300 px-4 py-2">{deployment[0]}</td>
6+
</tr>
7+
)
8+
}
9+
10+
export default KeyVaultItem;
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import React from 'react';
3+
import KeyVaultItem from './itemkv';
4+
const KeyVaultsDetail = (props: any) => {
5+
const { deployments } = props;
6+
const deploymentList: any[] = Object.entries( deployments);
7+
8+
return (
9+
<div className="overflow-x-auto">
10+
<h4>{props.title}</h4>
11+
<table className="w-full table-auto border-collapse border border-gray-300 mt-2">
12+
<tbody>
13+
{deploymentList.map((deployment: any, index: number) => (
14+
<KeyVaultItem key={index} index={index} deployment={deployment} />
15+
))}
16+
</tbody>
17+
</table>
18+
</div>
19+
);
20+
};
21+
22+
export default KeyVaultsDetail;

src/functions/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,8 @@ export const findDifferentNamesInList = (list: any[]) => {
8888

8989
export const findName = ( workload: any) => {
9090
return workLoads.find((item: { value: any; }) => item.value == workload)?.name;
91+
}
92+
93+
export const findKv = ( workload: any) => {
94+
return workLoads.find((item: { value: any; }) => item.value == workload)?.name;
9195
}

src/functions/localstorage.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@ export const getConfigData = () => {
1818
return deployments ? JSON.parse(deployments) : [];
1919
}
2020

21+
export const saveKvData = (kv: any) => {
22+
localStorage.setItem('kv892', btoa(JSON.stringify(kv)));
23+
}
24+
25+
export const getKvData = () => {
26+
const deployments = localStorage.getItem('kv892');
27+
return deployments ? JSON.parse(atob(deployments)) : [];
28+
}
29+
2130
export const saveWorkLoadData = (workload: string, value: string) => {
2231
localStorage.setItem(workload, JSON.stringify(value));
2332
}
2433

2534
export const getWorkLoadData = (workload:string) => {
2635
const deployments = localStorage.getItem(workload);
2736
return deployments ? JSON.parse(deployments) : [];
28-
}
37+
}

src/pages/api/deploy.ts

-26
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,6 @@ import { KubeConfig, AppsV1Api, CoreV1Api, CoreV1ApiReadNamespacedConfigMapReque
33
import { DEFAULT_NAMESPACE } from '@/setting';
44
import { Deployment } from '@/types';
55

6-
const extractConfigMaps = (podSpec: any): string[] => {
7-
const configMaps = new Set<string>();
8-
9-
const containers = podSpec?.containers || [];
10-
containers.forEach((container: { env?: any; envFrom?: any }) => {
11-
(container.env || []).forEach((env: { valueFrom?: { configMapKeyRef?: { name: string } } }) => {
12-
if (env.valueFrom?.configMapKeyRef?.name) {
13-
configMaps.add(env.valueFrom.configMapKeyRef.name);
14-
}
15-
});
16-
(container.envFrom || []).forEach((envFrom: { configMapRef?: { name: string } }) => {
17-
if (envFrom.configMapRef?.name) {
18-
configMaps.add(envFrom.configMapRef.name);
19-
}
20-
});
21-
});
22-
23-
(podSpec?.volumes || []).forEach((volume: { configMap?: { name: string } }) => {
24-
if (volume.configMap?.name) {
25-
configMaps.add(volume.configMap.name);
26-
}
27-
});
28-
29-
return Array.from(configMaps);
30-
};
31-
326
async function getConfigMapData(apiClient: CoreV1Api, namespace: string, configMapName: string) {
337

348
try {

src/pages/api/keyvault.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import type { NextApiRequest, NextApiResponse } from 'next';
2+
import { DefaultAzureCredential } from "@azure/identity";
3+
import { SecretClient } from "@azure/keyvault-secrets";
4+
5+
6+
async function getKeyVaults(keyVaultName: string) {
7+
try {
8+
const keyVaultUrl = `https://${keyVaultName}.vault.azure.net`;
9+
10+
const credential = new DefaultAzureCredential();
11+
const client = new SecretClient(keyVaultUrl, credential);
12+
const secrets: Record<string, string> = {};
13+
14+
// Iterate over all secret properties (names)
15+
for await (const secretProperties of client.listPropertiesOfSecrets()) {
16+
try {
17+
// Fetch the secret value
18+
const secret = await client.getSecret(secretProperties.name);
19+
secrets[secret.name] = secret.value || "(Secret value not available)";
20+
} catch (err) {
21+
console.error(`❌ Error retrieving secret ${secretProperties.name}:`, err);
22+
}
23+
}
24+
25+
return secrets;
26+
27+
} catch (err) {
28+
console.error(`Error fetching key vault keys ${keyVaultName} :`, err);
29+
throw err; // Re-throw to handle in the caller
30+
}
31+
}
32+
33+
export default async function handler(
34+
req: NextApiRequest,
35+
res: NextApiResponse<any[] | { error: string }>
36+
) {
37+
try {
38+
const keyVaultLists: any[] = [];
39+
const workloads: string[] = [];
40+
const workLoad1 = req.query.workload1 as string;
41+
const workLoad2 = req.query.workload2 as string;
42+
const loadConfig = req.query.loadConfig as unknown as boolean;
43+
44+
if (workLoad1) {
45+
workloads.push(workLoad1);
46+
}
47+
if (workLoad2) {
48+
workloads.push(workLoad2);
49+
}
50+
51+
const compareWorkLoads = workloads; //req.query.compareWorkLoads as string;
52+
for (let i = 0; i < compareWorkLoads.length; i++) {
53+
keyVaultLists.push(await getKeyVaults(compareWorkLoads[i]));
54+
}
55+
res.status(200).json(keyVaultLists);
56+
} catch (err) {
57+
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
58+
res.status(500).json({ error: errorMessage });
59+
}
60+
}

0 commit comments

Comments
 (0)