@backstage/plugin-kubernetes-backend 0.8.0 → 0.8.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs.js +174 -65
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +54 -24
- package/package.json +15 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.8.1-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b585179770: Added Kubernetes proxy API route to backend Kubernetes plugin, allowing Backstage plugin developers to read/write new information from Kubernetes (if proper credentials are provided).
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/catalog-client@1.2.0-next.0
|
|
10
|
+
- @backstage/backend-common@0.16.1-next.0
|
|
11
|
+
- @backstage/backend-test-utils@0.1.31-next.0
|
|
12
|
+
- @backstage/plugin-auth-node@0.2.8-next.0
|
|
13
|
+
- @backstage/plugin-kubernetes-common@0.4.5-next.0
|
|
14
|
+
- @backstage/catalog-model@1.1.4-next.0
|
|
15
|
+
- @backstage/config@1.0.5-next.0
|
|
16
|
+
- @backstage/errors@1.1.4-next.0
|
|
17
|
+
|
|
3
18
|
## 0.8.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -12,9 +12,10 @@ var luxon = require('luxon');
|
|
|
12
12
|
var errors = require('@backstage/errors');
|
|
13
13
|
var catalogClient = require('@backstage/catalog-client');
|
|
14
14
|
var catalogModel = require('@backstage/catalog-model');
|
|
15
|
+
var pluginAuthNode = require('@backstage/plugin-auth-node');
|
|
15
16
|
var clientNode = require('@kubernetes/client-node');
|
|
16
17
|
var lodash = require('lodash');
|
|
17
|
-
var
|
|
18
|
+
var httpProxyMiddleware = require('http-proxy-middleware');
|
|
18
19
|
|
|
19
20
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
21
|
|
|
@@ -548,6 +549,62 @@ const getCombinedClusterSupplier = (rootConfig, catalogClient, refreshInterval =
|
|
|
548
549
|
return new CombinedClustersSupplier(clusterSuppliers);
|
|
549
550
|
};
|
|
550
551
|
|
|
552
|
+
const addResourceRoutesToRouter = (router, catalogApi, objectsProvider) => {
|
|
553
|
+
const getEntityByReq = async (req) => {
|
|
554
|
+
const rawEntityRef = req.body.entityRef;
|
|
555
|
+
if (rawEntityRef && typeof rawEntityRef !== "string") {
|
|
556
|
+
throw new errors.InputError(`entity query must be a string`);
|
|
557
|
+
} else if (!rawEntityRef) {
|
|
558
|
+
throw new errors.InputError("entity is a required field");
|
|
559
|
+
}
|
|
560
|
+
let entityRef = void 0;
|
|
561
|
+
try {
|
|
562
|
+
entityRef = catalogModel.parseEntityRef(rawEntityRef);
|
|
563
|
+
} catch (error) {
|
|
564
|
+
throw new errors.InputError(`Invalid entity ref, ${error}`);
|
|
565
|
+
}
|
|
566
|
+
const token = pluginAuthNode.getBearerTokenFromAuthorizationHeader(
|
|
567
|
+
req.headers.authorization
|
|
568
|
+
);
|
|
569
|
+
if (!token) {
|
|
570
|
+
throw new errors.AuthenticationError("No Backstage token");
|
|
571
|
+
}
|
|
572
|
+
const entity = await catalogApi.getEntityByRef(entityRef, {
|
|
573
|
+
token
|
|
574
|
+
});
|
|
575
|
+
if (!entity) {
|
|
576
|
+
throw new errors.InputError(
|
|
577
|
+
`Entity ref missing, ${catalogModel.stringifyEntityRef(entityRef)}`
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
return entity;
|
|
581
|
+
};
|
|
582
|
+
router.post("/resources/workloads/query", async (req, res) => {
|
|
583
|
+
const entity = await getEntityByReq(req);
|
|
584
|
+
const response = await objectsProvider.getKubernetesObjectsByEntity({
|
|
585
|
+
entity,
|
|
586
|
+
auth: req.body.auth
|
|
587
|
+
});
|
|
588
|
+
res.json(response);
|
|
589
|
+
});
|
|
590
|
+
router.post("/resources/custom/query", async (req, res) => {
|
|
591
|
+
const entity = await getEntityByReq(req);
|
|
592
|
+
if (!req.body.customResources) {
|
|
593
|
+
throw new errors.InputError("customResources is a required field");
|
|
594
|
+
} else if (!Array.isArray(req.body.customResources)) {
|
|
595
|
+
throw new errors.InputError("customResources must be an array");
|
|
596
|
+
} else if (req.body.customResources.length === 0) {
|
|
597
|
+
throw new errors.InputError("at least 1 customResource is required");
|
|
598
|
+
}
|
|
599
|
+
const response = await objectsProvider.getCustomResourcesByEntity({
|
|
600
|
+
entity,
|
|
601
|
+
customResources: req.body.customResources,
|
|
602
|
+
auth: req.body.auth
|
|
603
|
+
});
|
|
604
|
+
res.json(response);
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
|
|
551
608
|
class MultiTenantServiceLocator {
|
|
552
609
|
constructor(clusterSupplier) {
|
|
553
610
|
this.clusterSupplier = clusterSupplier;
|
|
@@ -952,61 +1009,71 @@ class KubernetesClientBasedFetcher {
|
|
|
952
1009
|
}
|
|
953
1010
|
}
|
|
954
1011
|
|
|
955
|
-
const
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
}
|
|
967
|
-
|
|
1012
|
+
const HEADER_KUBERNETES_CLUSTER = "X-Kubernetes-Cluster";
|
|
1013
|
+
class KubernetesProxy {
|
|
1014
|
+
constructor(logger, clusterSupplier) {
|
|
1015
|
+
this.logger = logger;
|
|
1016
|
+
this.clusterSupplier = clusterSupplier;
|
|
1017
|
+
this.middlewareForClusterName = /* @__PURE__ */ new Map();
|
|
1018
|
+
}
|
|
1019
|
+
createRequestHandler() {
|
|
1020
|
+
return async (req, res, next) => {
|
|
1021
|
+
const middleware = await this.getMiddleware(req);
|
|
1022
|
+
middleware(req, res, next);
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
async getMiddleware(originalReq) {
|
|
1026
|
+
const originalCluster = await this.getClusterForRequest(originalReq);
|
|
1027
|
+
let middleware = this.middlewareForClusterName.get(originalCluster.name);
|
|
1028
|
+
if (!middleware) {
|
|
1029
|
+
const logger = this.logger.child({ cluster: originalCluster.name });
|
|
1030
|
+
middleware = httpProxyMiddleware.createProxyMiddleware({
|
|
1031
|
+
logProvider: () => logger,
|
|
1032
|
+
secure: !originalCluster.skipTLSVerify,
|
|
1033
|
+
router: async (req) => {
|
|
1034
|
+
var _a;
|
|
1035
|
+
const cluster = await this.getClusterForRequest(req);
|
|
1036
|
+
const url = new URL(cluster.url);
|
|
1037
|
+
return {
|
|
1038
|
+
protocol: url.protocol,
|
|
1039
|
+
host: url.hostname,
|
|
1040
|
+
port: url.port,
|
|
1041
|
+
ca: (_a = clientNode.bufferFromFileOrString("", cluster.caData)) == null ? void 0 : _a.toString()
|
|
1042
|
+
};
|
|
1043
|
+
},
|
|
1044
|
+
pathRewrite: { [`^${originalReq.baseUrl}`]: "" },
|
|
1045
|
+
onError: (error, req, res) => {
|
|
1046
|
+
const wrappedError = new errors.ForwardedError(
|
|
1047
|
+
`Cluster '${originalCluster.name}' request error`,
|
|
1048
|
+
error
|
|
1049
|
+
);
|
|
1050
|
+
logger.error(wrappedError);
|
|
1051
|
+
const body = {
|
|
1052
|
+
error: errors.serializeError(wrappedError, {
|
|
1053
|
+
includeStack: process.env.NODE_ENV === "development"
|
|
1054
|
+
}),
|
|
1055
|
+
request: { method: req.method, url: req.originalUrl },
|
|
1056
|
+
response: { statusCode: 500 }
|
|
1057
|
+
};
|
|
1058
|
+
res.status(500).json(body);
|
|
1059
|
+
}
|
|
1060
|
+
});
|
|
1061
|
+
this.middlewareForClusterName.set(originalCluster.name, middleware);
|
|
968
1062
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1063
|
+
return middleware;
|
|
1064
|
+
}
|
|
1065
|
+
async getClusterForRequest(req) {
|
|
1066
|
+
const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);
|
|
1067
|
+
if (!clusterName) {
|
|
1068
|
+
throw new errors.InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);
|
|
974
1069
|
}
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
if (!entity) {
|
|
979
|
-
throw new errors.InputError(
|
|
980
|
-
`Entity ref missing, ${catalogModel.stringifyEntityRef(entityRef)}`
|
|
981
|
-
);
|
|
1070
|
+
const cluster = await this.clusterSupplier.getClusters().then((clusters) => clusters.find((c) => c.name === clusterName));
|
|
1071
|
+
if (!cluster) {
|
|
1072
|
+
throw new errors.NotFoundError(`Cluster '${clusterName}' not found`);
|
|
982
1073
|
}
|
|
983
|
-
return
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
const entity = await getEntityByReq(req);
|
|
987
|
-
const response = await objectsProvider.getKubernetesObjectsByEntity({
|
|
988
|
-
entity,
|
|
989
|
-
auth: req.body.auth
|
|
990
|
-
});
|
|
991
|
-
res.json(response);
|
|
992
|
-
});
|
|
993
|
-
router.post("/resources/custom/query", async (req, res) => {
|
|
994
|
-
const entity = await getEntityByReq(req);
|
|
995
|
-
if (!req.body.customResources) {
|
|
996
|
-
throw new errors.InputError("customResources is a required field");
|
|
997
|
-
} else if (!Array.isArray(req.body.customResources)) {
|
|
998
|
-
throw new errors.InputError("customResources must be an array");
|
|
999
|
-
} else if (req.body.customResources.length === 0) {
|
|
1000
|
-
throw new errors.InputError("at least 1 customResource is required");
|
|
1001
|
-
}
|
|
1002
|
-
const response = await objectsProvider.getCustomResourcesByEntity({
|
|
1003
|
-
entity,
|
|
1004
|
-
customResources: req.body.customResources,
|
|
1005
|
-
auth: req.body.auth
|
|
1006
|
-
});
|
|
1007
|
-
res.json(response);
|
|
1008
|
-
});
|
|
1009
|
-
};
|
|
1074
|
+
return cluster;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1010
1077
|
|
|
1011
1078
|
class KubernetesBuilder {
|
|
1012
1079
|
constructor(env) {
|
|
@@ -1019,7 +1086,6 @@ class KubernetesBuilder {
|
|
|
1019
1086
|
return new KubernetesBuilder(env);
|
|
1020
1087
|
}
|
|
1021
1088
|
async build() {
|
|
1022
|
-
var _a, _b, _c, _d;
|
|
1023
1089
|
const logger = this.env.logger;
|
|
1024
1090
|
const config = this.env.config;
|
|
1025
1091
|
logger.info("Initializing Kubernetes backend");
|
|
@@ -1035,10 +1101,11 @@ class KubernetesBuilder {
|
|
|
1035
1101
|
};
|
|
1036
1102
|
}
|
|
1037
1103
|
const customResources = this.buildCustomResources();
|
|
1038
|
-
const fetcher =
|
|
1039
|
-
const clusterSupplier =
|
|
1040
|
-
const
|
|
1041
|
-
const
|
|
1104
|
+
const fetcher = this.getFetcher();
|
|
1105
|
+
const clusterSupplier = this.getClusterSupplier();
|
|
1106
|
+
const proxy = this.getProxy(logger, clusterSupplier);
|
|
1107
|
+
const serviceLocator = this.getServiceLocator();
|
|
1108
|
+
const objectsProvider = this.getObjectsProvider({
|
|
1042
1109
|
logger,
|
|
1043
1110
|
fetcher,
|
|
1044
1111
|
serviceLocator,
|
|
@@ -1048,12 +1115,14 @@ class KubernetesBuilder {
|
|
|
1048
1115
|
const router = this.buildRouter(
|
|
1049
1116
|
objectsProvider,
|
|
1050
1117
|
clusterSupplier,
|
|
1051
|
-
this.env.catalogApi
|
|
1118
|
+
this.env.catalogApi,
|
|
1119
|
+
proxy
|
|
1052
1120
|
);
|
|
1053
1121
|
return {
|
|
1054
1122
|
clusterSupplier,
|
|
1055
1123
|
customResources,
|
|
1056
1124
|
fetcher,
|
|
1125
|
+
proxy,
|
|
1057
1126
|
objectsProvider,
|
|
1058
1127
|
router,
|
|
1059
1128
|
serviceLocator
|
|
@@ -1079,6 +1148,10 @@ class KubernetesBuilder {
|
|
|
1079
1148
|
this.serviceLocator = serviceLocator;
|
|
1080
1149
|
return this;
|
|
1081
1150
|
}
|
|
1151
|
+
setProxy(proxy) {
|
|
1152
|
+
this.proxy = proxy;
|
|
1153
|
+
return this;
|
|
1154
|
+
}
|
|
1082
1155
|
buildCustomResources() {
|
|
1083
1156
|
var _a;
|
|
1084
1157
|
const customResources = ((_a = this.env.config.getOptionalConfigArray("kubernetes.customResources")) != null ? _a : []).map(
|
|
@@ -1096,32 +1169,38 @@ class KubernetesBuilder {
|
|
|
1096
1169
|
}
|
|
1097
1170
|
buildClusterSupplier(refreshInterval) {
|
|
1098
1171
|
const config = this.env.config;
|
|
1099
|
-
|
|
1172
|
+
this.clusterSupplier = getCombinedClusterSupplier(
|
|
1100
1173
|
config,
|
|
1101
1174
|
this.env.catalogApi,
|
|
1102
1175
|
refreshInterval
|
|
1103
1176
|
);
|
|
1177
|
+
return this.clusterSupplier;
|
|
1104
1178
|
}
|
|
1105
1179
|
buildObjectsProvider(options) {
|
|
1106
|
-
|
|
1180
|
+
this.objectsProvider = new KubernetesFanOutHandler(options);
|
|
1181
|
+
return this.objectsProvider;
|
|
1107
1182
|
}
|
|
1108
1183
|
buildFetcher() {
|
|
1109
|
-
|
|
1184
|
+
this.fetcher = new KubernetesClientBasedFetcher({
|
|
1110
1185
|
kubernetesClientProvider: new KubernetesClientProvider(),
|
|
1111
1186
|
logger: this.env.logger
|
|
1112
1187
|
});
|
|
1188
|
+
return this.fetcher;
|
|
1113
1189
|
}
|
|
1114
1190
|
buildServiceLocator(method, clusterSupplier) {
|
|
1115
1191
|
switch (method) {
|
|
1116
1192
|
case "multiTenant":
|
|
1117
|
-
|
|
1193
|
+
this.serviceLocator = this.buildMultiTenantServiceLocator(clusterSupplier);
|
|
1194
|
+
break;
|
|
1118
1195
|
case "http":
|
|
1119
|
-
|
|
1196
|
+
this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);
|
|
1197
|
+
break;
|
|
1120
1198
|
default:
|
|
1121
1199
|
throw new Error(
|
|
1122
1200
|
`Unsupported kubernetes.clusterLocatorMethod "${method}"`
|
|
1123
1201
|
);
|
|
1124
1202
|
}
|
|
1203
|
+
return this.serviceLocator;
|
|
1125
1204
|
}
|
|
1126
1205
|
buildMultiTenantServiceLocator(clusterSupplier) {
|
|
1127
1206
|
return new MultiTenantServiceLocator(clusterSupplier);
|
|
@@ -1129,7 +1208,11 @@ class KubernetesBuilder {
|
|
|
1129
1208
|
buildHttpServiceLocator(_clusterSupplier) {
|
|
1130
1209
|
throw new Error("not implemented");
|
|
1131
1210
|
}
|
|
1132
|
-
|
|
1211
|
+
buildProxy(logger, clusterSupplier) {
|
|
1212
|
+
this.proxy = new KubernetesProxy(logger, clusterSupplier);
|
|
1213
|
+
return this.proxy;
|
|
1214
|
+
}
|
|
1215
|
+
buildRouter(objectsProvider, clusterSupplier, catalogApi, proxy) {
|
|
1133
1216
|
const logger = this.env.logger;
|
|
1134
1217
|
const router = Router__default["default"]();
|
|
1135
1218
|
router.use(express__default["default"].json());
|
|
@@ -1160,6 +1243,7 @@ class KubernetesBuilder {
|
|
|
1160
1243
|
}))
|
|
1161
1244
|
});
|
|
1162
1245
|
});
|
|
1246
|
+
router.use("/proxy", proxy.createRequestHandler());
|
|
1163
1247
|
addResourceRoutesToRouter(router, catalogApi, objectsProvider);
|
|
1164
1248
|
return router;
|
|
1165
1249
|
}
|
|
@@ -1175,6 +1259,25 @@ class KubernetesBuilder {
|
|
|
1175
1259
|
"kubernetes.serviceLocatorMethod.type"
|
|
1176
1260
|
);
|
|
1177
1261
|
}
|
|
1262
|
+
getFetcher() {
|
|
1263
|
+
var _a;
|
|
1264
|
+
return (_a = this.fetcher) != null ? _a : this.buildFetcher();
|
|
1265
|
+
}
|
|
1266
|
+
getClusterSupplier() {
|
|
1267
|
+
var _a;
|
|
1268
|
+
return (_a = this.clusterSupplier) != null ? _a : this.buildClusterSupplier(this.defaultClusterRefreshInterval);
|
|
1269
|
+
}
|
|
1270
|
+
getServiceLocator() {
|
|
1271
|
+
var _a;
|
|
1272
|
+
return (_a = this.serviceLocator) != null ? _a : this.buildServiceLocator(
|
|
1273
|
+
this.getServiceLocatorMethod(),
|
|
1274
|
+
this.getClusterSupplier()
|
|
1275
|
+
);
|
|
1276
|
+
}
|
|
1277
|
+
getObjectsProvider(options) {
|
|
1278
|
+
var _a;
|
|
1279
|
+
return (_a = this.objectsProvider) != null ? _a : this.buildObjectsProvider(options);
|
|
1280
|
+
}
|
|
1178
1281
|
getObjectTypesToFetch() {
|
|
1179
1282
|
const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(
|
|
1180
1283
|
"kubernetes.objectTypes"
|
|
@@ -1198,6 +1301,10 @@ class KubernetesBuilder {
|
|
|
1198
1301
|
}
|
|
1199
1302
|
return objectTypesToFetch;
|
|
1200
1303
|
}
|
|
1304
|
+
getProxy(logger, clusterSupplier) {
|
|
1305
|
+
var _a;
|
|
1306
|
+
return (_a = this.proxy) != null ? _a : this.buildProxy(logger, clusterSupplier);
|
|
1307
|
+
}
|
|
1201
1308
|
}
|
|
1202
1309
|
|
|
1203
1310
|
async function createRouter(options) {
|
|
@@ -1210,9 +1317,11 @@ exports.AzureIdentityKubernetesAuthTranslator = AzureIdentityKubernetesAuthTrans
|
|
|
1210
1317
|
exports.DEFAULT_OBJECTS = DEFAULT_OBJECTS;
|
|
1211
1318
|
exports.GoogleKubernetesAuthTranslator = GoogleKubernetesAuthTranslator;
|
|
1212
1319
|
exports.GoogleServiceAccountAuthTranslator = GoogleServiceAccountAuthTranslator;
|
|
1320
|
+
exports.HEADER_KUBERNETES_CLUSTER = HEADER_KUBERNETES_CLUSTER;
|
|
1213
1321
|
exports.KubernetesAuthTranslatorGenerator = KubernetesAuthTranslatorGenerator;
|
|
1214
1322
|
exports.KubernetesBuilder = KubernetesBuilder;
|
|
1215
1323
|
exports.KubernetesClientProvider = KubernetesClientProvider;
|
|
1324
|
+
exports.KubernetesProxy = KubernetesProxy;
|
|
1216
1325
|
exports.NoopKubernetesAuthTranslator = NoopKubernetesAuthTranslator;
|
|
1217
1326
|
exports.OidcKubernetesAuthTranslator = OidcKubernetesAuthTranslator;
|
|
1218
1327
|
exports.createRouter = createRouter;
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/routes/resourcesRoutes.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @alpha\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @alpha\n */\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @alpha\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @alpha\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @alpha\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\n/**\n *\n * @alpha\n */\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n case 'localKubectlProxy': {\n return new NoopKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n} from '@backstage/catalog-model';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\n/**\n *\n * @alpha\n */\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\n/**\n *\n * @alpha\n */\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'limitranges',\n objectType: 'limitranges',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = await (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n return await Promise.all(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n const fetchResults = Array.from(namespaces).map(ns =>\n topPods(coreApi, metricsClient, ns)\n .then(r => {\n return {\n type: 'podstatus',\n resources: r,\n } as PodStatusFetchResponse;\n })\n .catch(this.captureKubernetesErrorsRethrowOthers.bind(this)),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { InputError, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const token = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity({\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Logger } from 'winston';\nimport { Duration } from 'luxon';\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n KubernetesObjectTypes,\n ServiceLocatorMethod,\n CustomResource,\n KubernetesObjectsProvider,\n ObjectsByEntityRequest,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesServiceLocator,\n KubernetesObjectsProviderOptions,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { CatalogApi } from '@backstage/catalog-client';\n\n/**\n *\n * @alpha\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @alpha\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @alpha\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.fetcher ?? this.buildFetcher();\n\n const clusterSupplier =\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval);\n\n const serviceLocator =\n this.serviceLocator ??\n this.buildServiceLocator(this.getServiceLocatorMethod(), clusterSupplier);\n\n const objectsProvider =\n this.objectsProvider ??\n this.buildObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n return getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n return new KubernetesFanOutHandler(options);\n }\n\n protected buildFetcher(): KubernetesFetcher {\n return new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n return this.buildMultiTenantServiceLocator(clusterSupplier);\n case 'http':\n return this.buildHttpServiceLocator(clusterSupplier);\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\n\n/**\n *\n * @alpha\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @alpha\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","lodash","topPods","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","Duration","Router","express"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts","../src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts","../src/kubernetes-auth-translator/KubernetesAuthTranslatorGenerator.ts","../src/cluster-locator/ConfigClusterLocator.ts","../src/service/runPeriodically.ts","../src/cluster-locator/GkeClusterLocator.ts","../src/cluster-locator/CatalogClusterLocator.ts","../src/cluster-locator/LocalKubectlProxyLocator.ts","../src/cluster-locator/index.ts","../src/routes/resourcesRoutes.ts","../src/service-locator/MultiTenantServiceLocator.ts","../src/service/KubernetesClientProvider.ts","../src/service/KubernetesFanOutHandler.ts","../src/service/KubernetesFetcher.ts","../src/service/KubernetesProxy.ts","../src/service/KubernetesBuilder.ts","../src/service/router.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport AWS, { Credentials } from 'aws-sdk';\nimport { sign } from 'aws4';\nimport { AWSClusterDetails } from '../types/types';\nimport { KubernetesAuthTranslator } from './types';\n\n/**\n *\n * @alpha\n */\nexport type SigningCreds = {\n accessKeyId: string | undefined;\n secretAccessKey: string | undefined;\n sessionToken: string | undefined;\n};\n\n/**\n *\n * @alpha\n */\nexport class AwsIamKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n validCredentials(creds: SigningCreds): boolean {\n return (creds?.accessKeyId && creds?.secretAccessKey) as unknown as boolean;\n }\n\n awsGetCredentials = async (): Promise<Credentials> => {\n return new Promise((resolve, reject) => {\n AWS.config.getCredentials(err => {\n if (err) {\n return reject(err);\n }\n\n return resolve(AWS.config.credentials as Credentials);\n });\n });\n };\n\n async getCredentials(\n assumeRole?: string,\n externalId?: string,\n ): Promise<SigningCreds> {\n return new Promise<SigningCreds>(async (resolve, reject) => {\n const awsCreds = await this.awsGetCredentials();\n\n if (!(awsCreds instanceof Credentials))\n return reject(Error('No AWS credentials found.'));\n\n let creds: SigningCreds = {\n accessKeyId: awsCreds.accessKeyId,\n secretAccessKey: awsCreds.secretAccessKey,\n sessionToken: awsCreds.sessionToken,\n };\n\n if (!this.validCredentials(creds))\n return reject(Error('Invalid AWS credentials found.'));\n if (!assumeRole) return resolve(creds);\n\n try {\n const params: AWS.STS.Types.AssumeRoleRequest = {\n RoleArn: assumeRole,\n RoleSessionName: 'backstage-login',\n };\n if (externalId) params.ExternalId = externalId;\n\n const assumedRole = await new AWS.STS().assumeRole(params).promise();\n\n if (!assumedRole.Credentials) {\n throw new Error(`No credentials returned for role ${assumeRole}`);\n }\n\n creds = {\n accessKeyId: assumedRole.Credentials.AccessKeyId,\n secretAccessKey: assumedRole.Credentials.SecretAccessKey,\n sessionToken: assumedRole.Credentials.SessionToken,\n };\n } catch (e) {\n console.warn(`There was an error assuming the role: ${e}`);\n return reject(Error(`Unable to assume role: ${e}`));\n }\n return resolve(creds);\n });\n }\n async getBearerToken(\n clusterName: string,\n assumeRole?: string,\n externalId?: string,\n ): Promise<string> {\n const credentials = await this.getCredentials(assumeRole, externalId);\n\n const request = {\n host: `sts.amazonaws.com`,\n path: `/?Action=GetCallerIdentity&Version=2011-06-15&X-Amz-Expires=60`,\n headers: {\n 'x-k8s-aws-id': clusterName,\n },\n signQuery: true,\n };\n\n const signed = sign(request, credentials);\n const url = `https://${signed.host}${signed.path}`;\n const base64Url = Buffer.from(url, 'binary').toString('base64');\n const urlSafeBase64Url = base64Url\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n\n return `k8s-aws-v1.${urlSafeBase64Url}`;\n }\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AWSClusterDetails,\n ): Promise<AWSClusterDetails> {\n const clusterDetailsWithAuthToken: AWSClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getBearerToken(\n clusterDetails.name,\n clusterDetails.assumeRole,\n clusterDetails.externalId,\n );\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { AzureClusterDetails } from '../types/types';\nimport {\n AccessToken,\n DefaultAzureCredential,\n TokenCredential,\n} from '@azure/identity';\n\nconst aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope is the same for all Azure Managed Kubernetes\n\n/**\n *\n * @alpha\n */\nexport class AzureIdentityKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 };\n private newTokenPromise: Promise<string> | undefined;\n\n constructor(\n private readonly logger: Logger,\n private readonly tokenCredential: TokenCredential = new DefaultAzureCredential(),\n ) {}\n\n async decorateClusterDetailsWithAuth(\n clusterDetails: AzureClusterDetails,\n ): Promise<AzureClusterDetails> {\n const clusterDetailsWithAuthToken: AzureClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n clusterDetailsWithAuthToken.serviceAccountToken = await this.getToken();\n return clusterDetailsWithAuthToken;\n }\n\n private async getToken(): Promise<string> {\n if (!this.tokenRequiresRefresh()) {\n return this.accessToken.token;\n }\n\n if (!this.newTokenPromise) {\n this.newTokenPromise = this.fetchNewToken();\n }\n\n return this.newTokenPromise;\n }\n\n private async fetchNewToken(): Promise<string> {\n try {\n this.logger.info('Fetching new Azure token for AKS');\n\n const newAccessToken = await this.tokenCredential.getToken(aksScope, {\n requestOptions: { timeout: 10_000 }, // 10 seconds\n });\n if (!newAccessToken) {\n throw new Error('AccessToken is null');\n }\n\n this.accessToken = newAccessToken;\n } catch (err) {\n this.logger.error('Unable to fetch Azure token', err);\n\n // only throw the error if the token has already expired, otherwise re-use existing until we're able to fetch a new token\n if (this.tokenExpired()) {\n throw err;\n }\n }\n\n this.newTokenPromise = undefined;\n return this.accessToken.token;\n }\n\n private tokenRequiresRefresh(): boolean {\n // Set tokens to expire 15 minutes before its actual expiry time\n const expiresOn = this.accessToken.expiresOnTimestamp - 15 * 60 * 1000;\n return Date.now() >= expiresOn;\n }\n\n private tokenExpired(): boolean {\n return Date.now() >= this.accessToken.expiresOnTimestamp;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class GoogleKubernetesAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const authToken: string | undefined = authConfig.google;\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n 'Google token not found under auth.google in request body',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { KubernetesAuthTranslator } from './types';\nimport { GKEClusterDetails } from '../types/types';\nimport * as container from '@google-cloud/container';\n\n/**\n *\n * @alpha\n */\nexport class GoogleServiceAccountAuthTranslator\n implements KubernetesAuthTranslator\n{\n async decorateClusterDetailsWithAuth(\n clusterDetails: GKEClusterDetails,\n ): Promise<GKEClusterDetails> {\n const clusterDetailsWithAuthToken: GKEClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n const client = new container.v1.ClusterManagerClient();\n const accessToken = await client.auth.getAccessToken();\n\n if (accessToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = accessToken;\n } else {\n throw new Error(\n 'Unable to obtain access token for the current Google Application Default Credentials',\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ServiceAccountClusterDetails } from '../types/types';\n\n/**\n *\n * @alpha\n */\nexport class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ServiceAccountClusterDetails,\n ): Promise<ServiceAccountClusterDetails> {\n return clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { KubernetesAuthTranslator } from './types';\nimport { ClusterDetails } from '../types/types';\nimport { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common';\n\n/**\n *\n * @alpha\n */\nexport class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {\n async decorateClusterDetailsWithAuth(\n clusterDetails: ClusterDetails,\n authConfig: KubernetesRequestAuth,\n ): Promise<ClusterDetails> {\n const clusterDetailsWithAuthToken: ClusterDetails = Object.assign(\n {},\n clusterDetails,\n );\n\n const { oidcTokenProvider } = clusterDetails;\n\n if (!oidcTokenProvider || oidcTokenProvider === '') {\n throw new Error(\n `oidc authProvider requires a configured oidcTokenProvider`,\n );\n }\n\n const authToken: string | undefined = authConfig.oidc?.[oidcTokenProvider];\n\n if (authToken) {\n clusterDetailsWithAuthToken.serviceAccountToken = authToken;\n } else {\n throw new Error(\n `Auth token not found under oidc.${oidcTokenProvider} in request body`,\n );\n }\n return clusterDetailsWithAuthToken;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Logger } from 'winston';\nimport { KubernetesAuthTranslator } from './types';\nimport { GoogleKubernetesAuthTranslator } from './GoogleKubernetesAuthTranslator';\nimport { NoopKubernetesAuthTranslator } from './NoopKubernetesAuthTranslator';\nimport { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator';\nimport { GoogleServiceAccountAuthTranslator } from './GoogleServiceAccountAuthProvider';\nimport { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator';\nimport { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator';\n\n/**\n *\n * @alpha\n */\nexport class KubernetesAuthTranslatorGenerator {\n static getKubernetesAuthTranslatorInstance(\n authProvider: string,\n options: {\n logger: Logger;\n },\n ): KubernetesAuthTranslator {\n switch (authProvider) {\n case 'google': {\n return new GoogleKubernetesAuthTranslator();\n }\n case 'aws': {\n return new AwsIamKubernetesAuthTranslator();\n }\n case 'azure': {\n return new AzureIdentityKubernetesAuthTranslator(options.logger);\n }\n case 'serviceAccount': {\n return new NoopKubernetesAuthTranslator();\n }\n case 'googleServiceAccount': {\n return new GoogleServiceAccountAuthTranslator();\n }\n case 'oidc': {\n return new OidcKubernetesAuthTranslator();\n }\n case 'localKubectlProxy': {\n return new NoopKubernetesAuthTranslator();\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no KubernetesAuthTranslator associated with it`,\n );\n }\n }\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class ConfigClusterLocator implements KubernetesClustersSupplier {\n private readonly clusterDetails: ClusterDetails[];\n\n constructor(clusterDetails: ClusterDetails[]) {\n this.clusterDetails = clusterDetails;\n }\n\n static fromConfig(config: Config): ConfigClusterLocator {\n // TODO: Add validation that authProvider is required and serviceAccountToken\n // is required if authProvider is serviceAccount\n return new ConfigClusterLocator(\n config.getConfigArray('clusters').map(c => {\n const authProvider = c.getString('authProvider');\n const clusterDetails: ClusterDetails = {\n name: c.getString('name'),\n url: c.getString('url'),\n serviceAccountToken: c.getOptionalString('serviceAccountToken'),\n skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup: c.getOptionalBoolean('skipMetricsLookup') ?? false,\n caData: c.getOptionalString('caData'),\n authProvider: authProvider,\n };\n const dashboardUrl = c.getOptionalString('dashboardUrl');\n if (dashboardUrl) {\n clusterDetails.dashboardUrl = dashboardUrl;\n }\n const dashboardApp = c.getOptionalString('dashboardApp');\n if (dashboardApp) {\n clusterDetails.dashboardApp = dashboardApp;\n }\n if (c.has('dashboardParameters')) {\n clusterDetails.dashboardParameters = c.get('dashboardParameters');\n }\n\n switch (authProvider) {\n case 'google': {\n return clusterDetails;\n }\n case 'aws': {\n const assumeRole = c.getOptionalString('assumeRole');\n const externalId = c.getOptionalString('externalId');\n\n return { assumeRole, externalId, ...clusterDetails };\n }\n case 'azure': {\n return clusterDetails;\n }\n case 'oidc': {\n const oidcTokenProvider = c.getString('oidcTokenProvider');\n\n return { oidcTokenProvider, ...clusterDetails };\n }\n case 'serviceAccount': {\n return clusterDetails;\n }\n case 'googleServiceAccount': {\n return clusterDetails;\n }\n default: {\n throw new Error(\n `authProvider \"${authProvider}\" has no config associated with it`,\n );\n }\n }\n }),\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Runs a function repeatedly, with a fixed wait between invocations.\n *\n * Supports async functions, and silently ignores exceptions and rejections.\n *\n * @param fn - The function to run. May return a Promise.\n * @param delayMs - The delay between a completed function invocation and the\n * next.\n * @returns A function that, when called, stops the invocation loop.\n */\nexport function runPeriodically(fn: () => any, delayMs: number): () => void {\n let cancel: () => void;\n let cancelled = false;\n const cancellationPromise = new Promise<void>(resolve => {\n cancel = () => {\n resolve();\n cancelled = true;\n };\n });\n\n const startRefresh = async () => {\n while (!cancelled) {\n try {\n await fn();\n } catch {\n // ignore intentionally\n }\n\n await Promise.race([\n new Promise(resolve => setTimeout(resolve, delayMs)),\n cancellationPromise,\n ]);\n }\n };\n startRefresh();\n\n return cancel!;\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { ForwardedError } from '@backstage/errors';\nimport * as container from '@google-cloud/container';\nimport { Duration } from 'luxon';\nimport { runPeriodically } from '../service/runPeriodically';\nimport {\n ClusterDetails,\n GKEClusterDetails,\n KubernetesClustersSupplier,\n} from '../types/types';\n\ninterface MatchResourceLabelEntry {\n key: string;\n value: string;\n}\n\ntype GkeClusterLocatorOptions = {\n projectId: string;\n region?: string;\n skipTLSVerify?: boolean;\n skipMetricsLookup?: boolean;\n exposeDashboard?: boolean;\n matchingResourceLabels?: MatchResourceLabelEntry[];\n};\n\nexport class GkeClusterLocator implements KubernetesClustersSupplier {\n constructor(\n private readonly options: GkeClusterLocatorOptions,\n private readonly client: container.v1.ClusterManagerClient,\n private clusterDetails: GKEClusterDetails[] | undefined = undefined,\n private hasClusterDetails: boolean = false,\n ) {}\n\n static fromConfigWithClient(\n config: Config,\n client: container.v1.ClusterManagerClient,\n refreshInterval?: Duration,\n ): GkeClusterLocator {\n const matchingResourceLabels: MatchResourceLabelEntry[] =\n config.getOptionalConfigArray('matchingResourceLabels')?.map(mrl => {\n return { key: mrl.getString('key'), value: mrl.getString('value') };\n }) ?? [];\n\n const options = {\n projectId: config.getString('projectId'),\n region: config.getOptionalString('region') ?? '-',\n skipTLSVerify: config.getOptionalBoolean('skipTLSVerify') ?? false,\n skipMetricsLookup:\n config.getOptionalBoolean('skipMetricsLookup') ?? false,\n exposeDashboard: config.getOptionalBoolean('exposeDashboard') ?? false,\n matchingResourceLabels,\n };\n const gkeClusterLocator = new GkeClusterLocator(options, client);\n if (refreshInterval) {\n runPeriodically(\n () => gkeClusterLocator.refreshClusters(),\n refreshInterval.toMillis(),\n );\n }\n return gkeClusterLocator;\n }\n\n static fromConfig(\n config: Config,\n refreshInterval: Duration | undefined = undefined,\n ): GkeClusterLocator {\n return GkeClusterLocator.fromConfigWithClient(\n config,\n new container.v1.ClusterManagerClient(),\n refreshInterval,\n );\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n if (!this.hasClusterDetails) {\n // refresh at least once when first called, when retries are disabled and in tests\n await this.refreshClusters();\n }\n return this.clusterDetails ?? [];\n }\n\n // TODO pass caData into the object\n async refreshClusters(): Promise<void> {\n const {\n projectId,\n region,\n skipTLSVerify,\n skipMetricsLookup,\n exposeDashboard,\n matchingResourceLabels,\n } = this.options;\n const request = {\n parent: `projects/${projectId}/locations/${region}`,\n };\n\n try {\n const [response] = await this.client.listClusters(request);\n this.clusterDetails = (response.clusters ?? [])\n .filter(r => {\n return matchingResourceLabels?.every(mrl => {\n if (!r.resourceLabels) {\n return false;\n }\n return r.resourceLabels[mrl.key] === mrl.value;\n });\n })\n .map(r => ({\n // TODO filter out clusters which don't have name or endpoint\n name: r.name ?? 'unknown',\n url: `https://${r.endpoint ?? ''}`,\n authProvider: 'google',\n skipTLSVerify,\n skipMetricsLookup,\n ...(exposeDashboard\n ? {\n dashboardApp: 'gke',\n dashboardParameters: {\n projectId,\n region,\n clusterName: r.name,\n },\n }\n : {}),\n }));\n this.hasClusterDetails = true;\n } catch (e) {\n throw new ForwardedError(\n `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`,\n e,\n );\n }\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { CATALOG_FILTER_EXISTS, CatalogApi } from '@backstage/catalog-client';\nimport {\n ANNOTATION_KUBERNETES_API_SERVER,\n ANNOTATION_KUBERNETES_API_SERVER_CA,\n ANNOTATION_KUBERNETES_AUTH_PROVIDER,\n} from '@backstage/catalog-model';\n\nexport class CatalogClusterLocator implements KubernetesClustersSupplier {\n private catalogClient: CatalogApi;\n\n constructor(catalogClient: CatalogApi) {\n this.catalogClient = catalogClient;\n }\n\n static fromConfig(catalogApi: CatalogApi): CatalogClusterLocator {\n return new CatalogClusterLocator(catalogApi);\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n const apiServerKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER}`;\n const apiServerCaKey = `metadata.annotations.${ANNOTATION_KUBERNETES_API_SERVER_CA}`;\n const authProviderKey = `metadata.annotations.${ANNOTATION_KUBERNETES_AUTH_PROVIDER}`;\n\n const filter: Record<string, symbol | string> = {\n kind: 'Resource',\n 'spec.type': 'kubernetes-cluster',\n [apiServerKey]: CATALOG_FILTER_EXISTS,\n [apiServerCaKey]: CATALOG_FILTER_EXISTS,\n [authProviderKey]: CATALOG_FILTER_EXISTS,\n };\n\n const clusters = await this.catalogClient.getEntities({\n filter: [filter],\n });\n return clusters.items.map(entity => {\n const clusterDetails: ClusterDetails = {\n name: entity.metadata.name,\n url: entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER]!,\n caData:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_API_SERVER_CA]!,\n authProvider:\n entity.metadata.annotations![ANNOTATION_KUBERNETES_AUTH_PROVIDER]!,\n };\n\n return clusterDetails;\n });\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport class LocalKubectlProxyClusterLocator\n implements KubernetesClustersSupplier\n{\n private readonly clusterDetails: ClusterDetails[];\n\n public constructor() {\n this.clusterDetails = [\n {\n name: 'local',\n url: 'http:/localhost:8001',\n authProvider: 'localKubectlProxy',\n skipMetricsLookup: true,\n },\n ];\n }\n\n async getClusters(): Promise<ClusterDetails[]> {\n return this.clusterDetails;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Duration } from 'luxon';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\nimport { ConfigClusterLocator } from './ConfigClusterLocator';\nimport { GkeClusterLocator } from './GkeClusterLocator';\nimport { CatalogClusterLocator } from './CatalogClusterLocator';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { LocalKubectlProxyClusterLocator } from './LocalKubectlProxyLocator';\n\nclass CombinedClustersSupplier implements KubernetesClustersSupplier {\n constructor(readonly clusterSuppliers: KubernetesClustersSupplier[]) {}\n\n async getClusters(): Promise<ClusterDetails[]> {\n return await Promise.all(\n this.clusterSuppliers.map(supplier => supplier.getClusters()),\n )\n .then(res => {\n return res.flat();\n })\n .catch(e => {\n throw e;\n });\n }\n}\n\nexport const getCombinedClusterSupplier = (\n rootConfig: Config,\n catalogClient: CatalogApi,\n refreshInterval: Duration | undefined = undefined,\n): KubernetesClustersSupplier => {\n const clusterSuppliers = rootConfig\n .getConfigArray('kubernetes.clusterLocatorMethods')\n .map(clusterLocatorMethod => {\n const type = clusterLocatorMethod.getString('type');\n switch (type) {\n case 'catalog':\n return CatalogClusterLocator.fromConfig(catalogClient);\n case 'localKubectlProxy':\n return new LocalKubectlProxyClusterLocator();\n case 'config':\n return ConfigClusterLocator.fromConfig(clusterLocatorMethod);\n case 'gke':\n return GkeClusterLocator.fromConfig(\n clusterLocatorMethod,\n refreshInterval,\n );\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethods: \"${type}\"`,\n );\n }\n });\n\n return new CombinedClustersSupplier(clusterSuppliers);\n};\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n CompoundEntityRef,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { InputError, AuthenticationError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '../types/types';\nimport { getBearerTokenFromAuthorizationHeader } from '@backstage/plugin-auth-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalogApi: CatalogApi,\n objectsProvider: KubernetesObjectsProvider,\n) => {\n const getEntityByReq = async (req: Request<any>) => {\n const rawEntityRef = req.body.entityRef;\n if (rawEntityRef && typeof rawEntityRef !== 'string') {\n throw new InputError(`entity query must be a string`);\n } else if (!rawEntityRef) {\n throw new InputError('entity is a required field');\n }\n let entityRef: CompoundEntityRef | undefined = undefined;\n\n try {\n entityRef = parseEntityRef(rawEntityRef);\n } catch (error) {\n throw new InputError(`Invalid entity ref, ${error}`);\n }\n\n const token = getBearerTokenFromAuthorizationHeader(\n req.headers.authorization,\n );\n\n if (!token) {\n throw new AuthenticationError('No Backstage token');\n }\n\n const entity = await catalogApi.getEntityByRef(entityRef, {\n token: token,\n });\n\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity,\n auth: req.body.auth,\n });\n res.json(response);\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n const entity = await getEntityByReq(req);\n\n if (!req.body.customResources) {\n throw new InputError('customResources is a required field');\n } else if (!Array.isArray(req.body.customResources)) {\n throw new InputError('customResources must be an array');\n } else if (req.body.customResources.length === 0) {\n throw new InputError('at least 1 customResource is required');\n }\n\n const response = await objectsProvider.getCustomResourcesByEntity({\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n });\n res.json(response);\n });\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport {\n ClusterDetails,\n KubernetesClustersSupplier,\n KubernetesServiceLocator,\n ServiceLocatorRequestContext,\n} from '../types/types';\n\n// This locator assumes that every service is located on every cluster\n// Therefore it will always return all clusters provided\nexport class MultiTenantServiceLocator implements KubernetesServiceLocator {\n private readonly clusterSupplier: KubernetesClustersSupplier;\n\n constructor(clusterSupplier: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n }\n\n // As this implementation always returns all clusters serviceId is ignored here\n getClustersByEntity(\n _entity: Entity,\n _requestContext: ServiceLocatorRequestContext,\n ): Promise<{ clusters: ClusterDetails[] }> {\n return this.clusterSupplier.getClusters().then(clusters => ({ clusters }));\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n CoreV1Api,\n KubeConfig,\n Metrics,\n CustomObjectsApi,\n} from '@kubernetes/client-node';\nimport { ClusterDetails } from '../types/types';\n\n/**\n *\n * @alpha\n */\nexport class KubernetesClientProvider {\n // visible for testing\n getKubeConfig(clusterDetails: ClusterDetails) {\n const cluster = {\n name: clusterDetails.name,\n server: clusterDetails.url,\n skipTLSVerify: clusterDetails.skipTLSVerify,\n caData: clusterDetails.caData,\n };\n\n // TODO configure\n const user = {\n name: 'backstage',\n token: clusterDetails.serviceAccountToken,\n };\n\n const context = {\n name: `${clusterDetails.name}`,\n user: user.name,\n cluster: cluster.name,\n };\n\n const kc = new KubeConfig();\n if (clusterDetails.serviceAccountToken) {\n kc.loadFromOptions({\n clusters: [cluster],\n users: [user],\n contexts: [context],\n currentContext: context.name,\n });\n } else {\n kc.loadFromDefault();\n }\n\n return kc;\n }\n\n getCoreClientByClusterDetails(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CoreV1Api);\n }\n\n getMetricsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return new Metrics(kc);\n }\n\n getCustomObjectsClient(clusterDetails: ClusterDetails) {\n const kc = this.getKubeConfig(clusterDetails);\n\n return kc.makeApiClient(CustomObjectsApi);\n }\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n KubernetesFetcher,\n KubernetesObjectsProviderOptions,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n FetchResponseWrapper,\n ObjectToFetch,\n CustomResource,\n CustomResourcesByEntity,\n KubernetesObjectsByEntity,\n ServiceLocatorRequestContext,\n} from '../types/types';\nimport { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types';\nimport { KubernetesAuthTranslatorGenerator } from '../kubernetes-auth-translator/KubernetesAuthTranslatorGenerator';\nimport {\n ClientContainerStatus,\n ClientCurrentResourceUsage,\n ClientPodStatus,\n ClusterObjects,\n FetchResponse,\n ObjectsByEntityResponse,\n PodFetchResponse,\n KubernetesRequestAuth,\n CustomResourceMatcher,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport {\n ContainerStatus,\n CurrentResourceUsage,\n PodStatus,\n} from '@kubernetes/client-node';\n\n/**\n *\n * @alpha\n */\nexport const DEFAULT_OBJECTS: ObjectToFetch[] = [\n {\n group: '',\n apiVersion: 'v1',\n plural: 'pods',\n objectType: 'pods',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'services',\n objectType: 'services',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'configmaps',\n objectType: 'configmaps',\n },\n {\n group: '',\n apiVersion: 'v1',\n plural: 'limitranges',\n objectType: 'limitranges',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'deployments',\n objectType: 'deployments',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'replicasets',\n objectType: 'replicasets',\n },\n {\n group: 'autoscaling',\n apiVersion: 'v1',\n plural: 'horizontalpodautoscalers',\n objectType: 'horizontalpodautoscalers',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'jobs',\n objectType: 'jobs',\n },\n {\n group: 'batch',\n apiVersion: 'v1',\n plural: 'cronjobs',\n objectType: 'cronjobs',\n },\n {\n group: 'networking.k8s.io',\n apiVersion: 'v1',\n plural: 'ingresses',\n objectType: 'ingresses',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'statefulsets',\n objectType: 'statefulsets',\n },\n {\n group: 'apps',\n apiVersion: 'v1',\n plural: 'daemonsets',\n objectType: 'daemonsets',\n },\n];\n\nexport interface KubernetesFanOutHandlerOptions\n extends KubernetesObjectsProviderOptions {}\n\nexport interface KubernetesRequestBody extends ObjectsByEntityRequest {}\n\nconst isPodFetchResponse = (fr: FetchResponse): fr is PodFetchResponse =>\n fr.type === 'pods';\nconst isString = (str: string | undefined): str is string => str !== undefined;\n\nconst numberOrBigIntToNumberOrString = (\n value: number | BigInt,\n): number | string => {\n return typeof value === 'bigint' ? value.toString() : (value as number);\n};\n\nconst toClientSafeResource = (\n current: CurrentResourceUsage,\n): ClientCurrentResourceUsage => {\n return {\n currentUsage: numberOrBigIntToNumberOrString(current.CurrentUsage),\n requestTotal: numberOrBigIntToNumberOrString(current.RequestTotal),\n limitTotal: numberOrBigIntToNumberOrString(current.LimitTotal),\n };\n};\n\nconst toClientSafeContainer = (\n container: ContainerStatus,\n): ClientContainerStatus => {\n return {\n container: container.Container,\n cpuUsage: toClientSafeResource(container.CPUUsage),\n memoryUsage: toClientSafeResource(container.MemoryUsage),\n };\n};\n\nconst toClientSafePodMetrics = (\n podMetrics: PodStatusFetchResponse[],\n): ClientPodStatus[] => {\n return podMetrics\n .map(r => r.resources)\n .flat()\n .map((pd: PodStatus): ClientPodStatus => {\n return {\n pod: pd.Pod,\n memory: toClientSafeResource(pd.Memory),\n cpu: toClientSafeResource(pd.CPU),\n containers: pd.Containers.map(toClientSafeContainer),\n };\n });\n};\n\ntype responseWithMetrics = [FetchResponseWrapper, PodStatusFetchResponse[]];\n\nexport class KubernetesFanOutHandler {\n private readonly logger: Logger;\n private readonly fetcher: KubernetesFetcher;\n private readonly serviceLocator: KubernetesServiceLocator;\n private readonly customResources: CustomResource[];\n private readonly objectTypesToFetch: Set<ObjectToFetch>;\n private readonly authTranslators: Record<string, KubernetesAuthTranslator>;\n\n constructor({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch = DEFAULT_OBJECTS,\n }: KubernetesFanOutHandlerOptions) {\n this.logger = logger;\n this.fetcher = fetcher;\n this.serviceLocator = serviceLocator;\n this.customResources = customResources;\n this.objectTypesToFetch = new Set(objectTypesToFetch);\n this.authTranslators = {};\n }\n\n async getCustomResourcesByEntity({\n entity,\n auth,\n customResources,\n }: CustomResourcesByEntity): Promise<ObjectsByEntityResponse> {\n // Don't fetch the default object types only the provided custom resources\n return this.fanOutRequests(\n entity,\n auth,\n new Set<ObjectToFetch>(),\n customResources,\n );\n }\n\n async getKubernetesObjectsByEntity({\n entity,\n auth,\n }: KubernetesObjectsByEntity): Promise<ObjectsByEntityResponse> {\n return this.fanOutRequests(entity, auth, this.objectTypesToFetch);\n }\n\n private async fanOutRequests(\n entity: Entity,\n auth: KubernetesRequestAuth,\n objectTypesToFetch: Set<ObjectToFetch>,\n customResources?: CustomResourceMatcher[],\n ) {\n const entityName =\n entity.metadata?.annotations?.['backstage.io/kubernetes-id'] ||\n entity.metadata?.name;\n\n const clusterDetailsDecoratedForAuth: ClusterDetails[] =\n await this.decorateClusterDetailsWithAuth(entity, auth, {\n objectTypesToFetch: objectTypesToFetch,\n customResources: customResources ?? [],\n });\n\n this.logger.info(\n `entity.metadata.name=${entityName} clusterDetails=[${clusterDetailsDecoratedForAuth\n .map(c => c.name)\n .join(', ')}]`,\n );\n\n const labelSelector: string =\n entity.metadata?.annotations?.[\n 'backstage.io/kubernetes-label-selector'\n ] || `backstage.io/kubernetes-id=${entityName}`;\n\n const namespace =\n entity.metadata?.annotations?.['backstage.io/kubernetes-namespace'];\n\n return Promise.all(\n clusterDetailsDecoratedForAuth.map(clusterDetailsItem => {\n return this.fetcher\n .fetchObjectsForService({\n serviceId: entityName,\n clusterDetails: clusterDetailsItem,\n objectTypesToFetch: objectTypesToFetch,\n labelSelector,\n customResources: (\n customResources ||\n clusterDetailsItem.customResources ||\n this.customResources\n ).map(c => ({\n ...c,\n objectType: 'customresources',\n })),\n namespace,\n })\n .then(result => this.getMetricsForPods(clusterDetailsItem, result))\n .then(r => this.toClusterObjects(clusterDetailsItem, r));\n }),\n ).then(this.toObjectsByEntityResponse);\n }\n\n private async decorateClusterDetailsWithAuth(\n entity: Entity,\n auth: KubernetesRequestAuth,\n requestContext: ServiceLocatorRequestContext,\n ) {\n const clusterDetails: ClusterDetails[] = await (\n await this.serviceLocator.getClustersByEntity(entity, requestContext)\n ).clusters;\n\n // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them\n return await Promise.all(\n clusterDetails.map(cd => {\n const kubernetesAuthTranslator: KubernetesAuthTranslator =\n this.getAuthTranslator(cd.authProvider);\n return kubernetesAuthTranslator.decorateClusterDetailsWithAuth(\n cd,\n auth,\n );\n }),\n );\n }\n\n toObjectsByEntityResponse(\n clusterObjects: ClusterObjects[],\n ): ObjectsByEntityResponse {\n return {\n items: clusterObjects.filter(\n item =>\n (item.errors !== undefined && item.errors.length >= 1) ||\n (item.resources !== undefined &&\n item.resources.length >= 1 &&\n item.resources.some(fr => fr.resources.length >= 1)),\n ),\n };\n }\n\n toClusterObjects(\n clusterDetails: ClusterDetails,\n [result, metrics]: responseWithMetrics,\n ): ClusterObjects {\n const objects: ClusterObjects = {\n cluster: {\n name: clusterDetails.name,\n },\n podMetrics: toClientSafePodMetrics(metrics),\n resources: result.responses,\n errors: result.errors,\n };\n if (clusterDetails.dashboardUrl) {\n objects.cluster.dashboardUrl = clusterDetails.dashboardUrl;\n }\n if (clusterDetails.dashboardApp) {\n objects.cluster.dashboardApp = clusterDetails.dashboardApp;\n }\n if (clusterDetails.dashboardParameters) {\n objects.cluster.dashboardParameters = clusterDetails.dashboardParameters;\n }\n return objects;\n }\n\n async getMetricsForPods(\n clusterDetails: ClusterDetails,\n result: FetchResponseWrapper,\n ): Promise<responseWithMetrics> {\n if (clusterDetails.skipMetricsLookup) {\n return [result, []];\n }\n const namespaces: Set<string> = new Set<string>(\n result.responses\n .filter(isPodFetchResponse)\n .flatMap(r => r.resources)\n .map(p => p.metadata?.namespace)\n .filter(isString),\n );\n\n if (namespaces.size === 0) {\n return [result, []];\n }\n\n const podMetrics = await this.fetcher.fetchPodMetricsByNamespaces(\n clusterDetails,\n namespaces,\n );\n\n result.errors.push(...podMetrics.errors);\n return [result, podMetrics.responses as PodStatusFetchResponse[]];\n }\n\n private getAuthTranslator(provider: string): KubernetesAuthTranslator {\n if (this.authTranslators[provider]) {\n return this.authTranslators[provider];\n }\n\n this.authTranslators[provider] =\n KubernetesAuthTranslatorGenerator.getKubernetesAuthTranslatorInstance(\n provider,\n {\n logger: this.logger,\n },\n );\n return this.authTranslators[provider];\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { topPods } from '@kubernetes/client-node';\nimport lodash, { Dictionary } from 'lodash';\nimport { Logger } from 'winston';\nimport {\n ClusterDetails,\n FetchResponseWrapper,\n KubernetesFetcher,\n KubernetesObjectTypes,\n ObjectFetchParams,\n ObjectToFetch,\n} from '../types/types';\nimport {\n FetchResponse,\n KubernetesFetchError,\n KubernetesErrorTypes,\n PodStatusFetchResponse,\n} from '@backstage/plugin-kubernetes-common';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\n\nexport interface KubernetesClientBasedFetcherOptions {\n kubernetesClientProvider: KubernetesClientProvider;\n logger: Logger;\n}\n\ntype FetchResult = FetchResponse | KubernetesFetchError;\n\nconst isError = (fr: FetchResult): fr is KubernetesFetchError =>\n fr.hasOwnProperty('errorType');\n\nfunction fetchResultsToResponseWrapper(\n results: FetchResult[],\n): FetchResponseWrapper {\n const groupBy: Dictionary<FetchResult[]> = lodash.groupBy(results, value => {\n return isError(value) ? 'errors' : 'responses';\n });\n\n return {\n errors: groupBy.errors ?? [],\n responses: groupBy.responses ?? [],\n } as FetchResponseWrapper; // TODO would be nice to get rid of this 'as'\n}\n\nconst statusCodeToErrorType = (statusCode: number): KubernetesErrorTypes => {\n switch (statusCode) {\n case 400:\n return 'BAD_REQUEST';\n case 401:\n return 'UNAUTHORIZED_ERROR';\n case 404:\n return 'NOT_FOUND';\n case 500:\n return 'SYSTEM_ERROR';\n default:\n return 'UNKNOWN_ERROR';\n }\n};\n\nexport class KubernetesClientBasedFetcher implements KubernetesFetcher {\n private readonly kubernetesClientProvider: KubernetesClientProvider;\n private readonly logger: Logger;\n\n constructor({\n kubernetesClientProvider,\n logger,\n }: KubernetesClientBasedFetcherOptions) {\n this.kubernetesClientProvider = kubernetesClientProvider;\n this.logger = logger;\n }\n\n fetchObjectsForService(\n params: ObjectFetchParams,\n ): Promise<FetchResponseWrapper> {\n const fetchResults = Array.from(params.objectTypesToFetch)\n .concat(params.customResources)\n .map(toFetch => {\n return this.fetchResource(\n params.clusterDetails,\n toFetch,\n params.labelSelector ||\n `backstage.io/kubernetes-id=${params.serviceId}`,\n toFetch.objectType,\n params.namespace,\n ).catch(this.captureKubernetesErrorsRethrowOthers.bind(this));\n });\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n fetchPodMetricsByNamespaces(\n clusterDetails: ClusterDetails,\n namespaces: Set<string>,\n ): Promise<FetchResponseWrapper> {\n const metricsClient =\n this.kubernetesClientProvider.getMetricsClient(clusterDetails);\n const coreApi =\n this.kubernetesClientProvider.getCoreClientByClusterDetails(\n clusterDetails,\n );\n\n const fetchResults = Array.from(namespaces).map(ns =>\n topPods(coreApi, metricsClient, ns)\n .then(r => {\n return {\n type: 'podstatus',\n resources: r,\n } as PodStatusFetchResponse;\n })\n .catch(this.captureKubernetesErrorsRethrowOthers.bind(this)),\n );\n\n return Promise.all(fetchResults).then(fetchResultsToResponseWrapper);\n }\n\n private captureKubernetesErrorsRethrowOthers(e: any): KubernetesFetchError {\n if (e.response && e.response.statusCode) {\n this.logger.warn(\n `statusCode=${e.response.statusCode} for resource ${\n e.response.request.uri.pathname\n } body=[${JSON.stringify(e.response.body)}]`,\n );\n return {\n errorType: statusCodeToErrorType(e.response.statusCode),\n statusCode: e.response.statusCode,\n resourcePath: e.response.request.uri.pathname,\n };\n }\n throw e;\n }\n\n private fetchResource(\n clusterDetails: ClusterDetails,\n resource: ObjectToFetch,\n labelSelector: string,\n objectType: KubernetesObjectTypes,\n namespace?: string,\n ): Promise<FetchResponse> {\n const customObjects =\n this.kubernetesClientProvider.getCustomObjectsClient(clusterDetails);\n\n customObjects.addInterceptor((requestOptions: any) => {\n requestOptions.uri = requestOptions.uri.replace('/apis//v1/', '/api/v1/');\n });\n\n if (namespace) {\n return customObjects\n .listNamespacedCustomObject(\n resource.group,\n resource.apiVersion,\n namespace,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n return customObjects\n .listClusterCustomObject(\n resource.group,\n resource.apiVersion,\n resource.plural,\n '',\n false,\n '',\n '',\n labelSelector,\n )\n .then(r => {\n return {\n type: objectType,\n resources: (r.body as any).items,\n };\n });\n }\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ErrorResponseBody,\n ForwardedError,\n InputError,\n NotFoundError,\n serializeError,\n} from '@backstage/errors';\nimport { bufferFromFileOrString } from '@kubernetes/client-node';\nimport type { Request, RequestHandler } from 'express';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { Logger } from 'winston';\nimport { ClusterDetails, KubernetesClustersSupplier } from '../types/types';\n\nexport const APPLICATION_JSON: string = 'application/json';\n\n/**\n * The header that is used to specify the cluster name.\n *\n * @alpha\n */\nexport const HEADER_KUBERNETES_CLUSTER: string = 'X-Kubernetes-Cluster';\n\n/**\n * A proxy that routes requests to the Kubernetes API.\n *\n * @alpha\n */\nexport class KubernetesProxy {\n private readonly middlewareForClusterName = new Map<string, RequestHandler>();\n\n constructor(\n private readonly logger: Logger,\n private readonly clusterSupplier: KubernetesClustersSupplier,\n ) {}\n\n public createRequestHandler(): RequestHandler {\n return async (req, res, next) => {\n const middleware = await this.getMiddleware(req);\n middleware(req, res, next);\n };\n }\n\n // We create one middleware per remote cluster and hold on to them, because\n // the secure property isn't possible to decide on a per-request basis with a\n // single middleware instance - and we don't expect it to change over time.\n private async getMiddleware(originalReq: Request): Promise<RequestHandler> {\n const originalCluster = await this.getClusterForRequest(originalReq);\n let middleware = this.middlewareForClusterName.get(originalCluster.name);\n if (!middleware) {\n // Probably too risky without permissions protecting this endpoint\n // if (cluster.serviceAccountToken) {\n // options.headers = {\n // Authorization: `Bearer ${cluster.serviceAccountToken}`,\n // };\n // }\n\n const logger = this.logger.child({ cluster: originalCluster.name });\n middleware = createProxyMiddleware({\n logProvider: () => logger,\n secure: !originalCluster.skipTLSVerify,\n router: async req => {\n // Re-evaluate the cluster on each request, in case it has changed\n const cluster = await this.getClusterForRequest(req);\n const url = new URL(cluster.url);\n return {\n protocol: url.protocol,\n host: url.hostname,\n port: url.port,\n ca: bufferFromFileOrString('', cluster.caData)?.toString(),\n };\n },\n pathRewrite: { [`^${originalReq.baseUrl}`]: '' },\n onError: (error, req, res) => {\n const wrappedError = new ForwardedError(\n `Cluster '${originalCluster.name}' request error`,\n error,\n );\n\n logger.error(wrappedError);\n\n const body: ErrorResponseBody = {\n error: serializeError(wrappedError, {\n includeStack: process.env.NODE_ENV === 'development',\n }),\n request: { method: req.method, url: req.originalUrl },\n response: { statusCode: 500 },\n };\n\n res.status(500).json(body);\n },\n });\n\n this.middlewareForClusterName.set(originalCluster.name, middleware);\n }\n\n return middleware;\n }\n\n private async getClusterForRequest(req: Request): Promise<ClusterDetails> {\n const clusterName = req.header(HEADER_KUBERNETES_CLUSTER);\n if (!clusterName) {\n throw new InputError(`Missing '${HEADER_KUBERNETES_CLUSTER}' header.`);\n }\n\n const cluster = await this.clusterSupplier\n .getClusters()\n .then(clusters => clusters.find(c => c.name === clusterName));\n if (!cluster) {\n throw new NotFoundError(`Cluster '${clusterName}' not found`);\n }\n\n return cluster;\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { Config } from '@backstage/config';\nimport express from 'express';\nimport Router from 'express-promise-router';\nimport { Duration } from 'luxon';\nimport { Logger } from 'winston';\n\nimport { getCombinedClusterSupplier } from '../cluster-locator';\nimport { addResourceRoutesToRouter } from '../routes/resourcesRoutes';\nimport { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator';\nimport {\n CustomResource,\n KubernetesClustersSupplier,\n KubernetesFetcher,\n KubernetesObjectsProvider,\n KubernetesObjectsProviderOptions,\n KubernetesObjectTypes,\n KubernetesServiceLocator,\n ObjectsByEntityRequest,\n ServiceLocatorMethod,\n} from '../types/types';\nimport { KubernetesClientProvider } from './KubernetesClientProvider';\nimport {\n DEFAULT_OBJECTS,\n KubernetesFanOutHandler,\n} from './KubernetesFanOutHandler';\nimport { KubernetesClientBasedFetcher } from './KubernetesFetcher';\nimport { KubernetesProxy } from './KubernetesProxy';\n\n/**\n *\n * @alpha\n */\nexport interface KubernetesEnvironment {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n}\n\n/**\n * The return type of the `KubernetesBuilder.build` method\n *\n * @alpha\n */\nexport type KubernetesBuilderReturn = Promise<{\n router: express.Router;\n clusterSupplier: KubernetesClustersSupplier;\n customResources: CustomResource[];\n fetcher: KubernetesFetcher;\n proxy: KubernetesProxy;\n objectsProvider: KubernetesObjectsProvider;\n serviceLocator: KubernetesServiceLocator;\n}>;\n\n/**\n *\n * @alpha\n */\nexport class KubernetesBuilder {\n private clusterSupplier?: KubernetesClustersSupplier;\n private defaultClusterRefreshInterval: Duration = Duration.fromObject({\n minutes: 60,\n });\n private objectsProvider?: KubernetesObjectsProvider;\n private fetcher?: KubernetesFetcher;\n private serviceLocator?: KubernetesServiceLocator;\n private proxy?: KubernetesProxy;\n\n static createBuilder(env: KubernetesEnvironment) {\n return new KubernetesBuilder(env);\n }\n\n constructor(protected readonly env: KubernetesEnvironment) {}\n\n public async build(): KubernetesBuilderReturn {\n const logger = this.env.logger;\n const config = this.env.config;\n\n logger.info('Initializing Kubernetes backend');\n\n if (!config.has('kubernetes')) {\n if (process.env.NODE_ENV !== 'development') {\n throw new Error('Kubernetes configuration is missing');\n }\n logger.warn(\n 'Failed to initialize kubernetes backend: kubernetes config is missing',\n );\n return {\n router: Router(),\n } as unknown as KubernetesBuilderReturn;\n }\n const customResources = this.buildCustomResources();\n\n const fetcher = this.getFetcher();\n\n const clusterSupplier = this.getClusterSupplier();\n\n const proxy = this.getProxy(logger, clusterSupplier);\n\n const serviceLocator = this.getServiceLocator();\n\n const objectsProvider = this.getObjectsProvider({\n logger,\n fetcher,\n serviceLocator,\n customResources,\n objectTypesToFetch: this.getObjectTypesToFetch(),\n });\n\n const router = this.buildRouter(\n objectsProvider,\n clusterSupplier,\n this.env.catalogApi,\n proxy,\n );\n\n return {\n clusterSupplier,\n customResources,\n fetcher,\n proxy,\n objectsProvider,\n router,\n serviceLocator,\n };\n }\n\n public setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier) {\n this.clusterSupplier = clusterSupplier;\n return this;\n }\n\n public setDefaultClusterRefreshInterval(refreshInterval: Duration) {\n this.defaultClusterRefreshInterval = refreshInterval;\n return this;\n }\n\n public setObjectsProvider(objectsProvider?: KubernetesObjectsProvider) {\n this.objectsProvider = objectsProvider;\n return this;\n }\n\n public setFetcher(fetcher?: KubernetesFetcher) {\n this.fetcher = fetcher;\n return this;\n }\n\n public setServiceLocator(serviceLocator?: KubernetesServiceLocator) {\n this.serviceLocator = serviceLocator;\n return this;\n }\n\n public setProxy(proxy?: KubernetesProxy) {\n this.proxy = proxy;\n return this;\n }\n\n protected buildCustomResources() {\n const customResources: CustomResource[] = (\n this.env.config.getOptionalConfigArray('kubernetes.customResources') ?? []\n ).map(\n c =>\n ({\n group: c.getString('group'),\n apiVersion: c.getString('apiVersion'),\n plural: c.getString('plural'),\n objectType: 'customresources',\n } as CustomResource),\n );\n\n this.env.logger.info(\n `action=LoadingCustomResources numOfCustomResources=${customResources.length}`,\n );\n return customResources;\n }\n\n protected buildClusterSupplier(\n refreshInterval: Duration,\n ): KubernetesClustersSupplier {\n const config = this.env.config;\n this.clusterSupplier = getCombinedClusterSupplier(\n config,\n this.env.catalogApi,\n refreshInterval,\n );\n\n return this.clusterSupplier;\n }\n\n protected buildObjectsProvider(\n options: KubernetesObjectsProviderOptions,\n ): KubernetesObjectsProvider {\n this.objectsProvider = new KubernetesFanOutHandler(options);\n return this.objectsProvider;\n }\n\n protected buildFetcher(): KubernetesFetcher {\n this.fetcher = new KubernetesClientBasedFetcher({\n kubernetesClientProvider: new KubernetesClientProvider(),\n logger: this.env.logger,\n });\n\n return this.fetcher;\n }\n\n protected buildServiceLocator(\n method: ServiceLocatorMethod,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n switch (method) {\n case 'multiTenant':\n this.serviceLocator =\n this.buildMultiTenantServiceLocator(clusterSupplier);\n break;\n case 'http':\n this.serviceLocator = this.buildHttpServiceLocator(clusterSupplier);\n break;\n default:\n throw new Error(\n `Unsupported kubernetes.clusterLocatorMethod \"${method}\"`,\n );\n }\n\n return this.serviceLocator;\n }\n\n protected buildMultiTenantServiceLocator(\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n return new MultiTenantServiceLocator(clusterSupplier);\n }\n\n protected buildHttpServiceLocator(\n _clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesServiceLocator {\n throw new Error('not implemented');\n }\n\n protected buildProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ): KubernetesProxy {\n this.proxy = new KubernetesProxy(logger, clusterSupplier);\n return this.proxy;\n }\n\n protected buildRouter(\n objectsProvider: KubernetesObjectsProvider,\n clusterSupplier: KubernetesClustersSupplier,\n catalogApi: CatalogApi,\n proxy: KubernetesProxy,\n ): express.Router {\n const logger = this.env.logger;\n const router = Router();\n router.use(express.json());\n\n // @deprecated\n router.post('/services/:serviceId', async (req, res) => {\n const serviceId = req.params.serviceId;\n const requestBody: ObjectsByEntityRequest = req.body;\n try {\n const response = await objectsProvider.getKubernetesObjectsByEntity({\n entity: requestBody.entity,\n auth: requestBody.auth || {},\n });\n res.json(response);\n } catch (e) {\n logger.error(\n `action=retrieveObjectsByServiceId service=${serviceId}, error=${e}`,\n );\n res.status(500).json({ error: e.message });\n }\n });\n\n router.get('/clusters', async (_, res) => {\n const clusterDetails = await this.fetchClusterDetails(clusterSupplier);\n res.json({\n items: clusterDetails.map(cd => ({\n name: cd.name,\n dashboardUrl: cd.dashboardUrl,\n authProvider: cd.authProvider,\n oidcTokenProvider: cd.oidcTokenProvider,\n })),\n });\n });\n\n router.use('/proxy', proxy.createRequestHandler());\n\n addResourceRoutesToRouter(router, catalogApi, objectsProvider);\n\n return router;\n }\n\n protected async fetchClusterDetails(\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n const clusterDetails = await clusterSupplier.getClusters();\n\n this.env.logger.info(\n `action=loadClusterDetails numOfClustersLoaded=${clusterDetails.length}`,\n );\n\n return clusterDetails;\n }\n\n protected getServiceLocatorMethod() {\n return this.env.config.getString(\n 'kubernetes.serviceLocatorMethod.type',\n ) as ServiceLocatorMethod;\n }\n\n protected getFetcher(): KubernetesFetcher {\n return this.fetcher ?? this.buildFetcher();\n }\n\n protected getClusterSupplier() {\n return (\n this.clusterSupplier ??\n this.buildClusterSupplier(this.defaultClusterRefreshInterval)\n );\n }\n\n protected getServiceLocator(): KubernetesServiceLocator {\n return (\n this.serviceLocator ??\n this.buildServiceLocator(\n this.getServiceLocatorMethod(),\n this.getClusterSupplier(),\n )\n );\n }\n\n protected getObjectsProvider(options: KubernetesObjectsProviderOptions) {\n return this.objectsProvider ?? this.buildObjectsProvider(options);\n }\n\n protected getObjectTypesToFetch() {\n const objectTypesToFetchStrings = this.env.config.getOptionalStringArray(\n 'kubernetes.objectTypes',\n ) as KubernetesObjectTypes[];\n\n const apiVersionOverrides = this.env.config.getOptionalConfig(\n 'kubernetes.apiVersionOverrides',\n );\n\n let objectTypesToFetch;\n\n if (objectTypesToFetchStrings) {\n objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>\n objectTypesToFetchStrings.includes(obj.objectType),\n );\n }\n\n if (apiVersionOverrides) {\n objectTypesToFetch = objectTypesToFetch ?? DEFAULT_OBJECTS;\n\n for (const obj of objectTypesToFetch) {\n if (apiVersionOverrides.has(obj.objectType)) {\n obj.apiVersion = apiVersionOverrides.getString(obj.objectType);\n }\n }\n }\n\n return objectTypesToFetch;\n }\n\n protected getProxy(\n logger: Logger,\n clusterSupplier: KubernetesClustersSupplier,\n ) {\n return this.proxy ?? this.buildProxy(logger, clusterSupplier);\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport { Logger } from 'winston';\nimport { KubernetesClustersSupplier } from '../types/types';\nimport express from 'express';\nimport { KubernetesBuilder } from './KubernetesBuilder';\nimport { PluginEndpointDiscovery } from '@backstage/backend-common';\nimport { CatalogApi } from '@backstage/catalog-client';\n\n/**\n *\n * @alpha\n */\nexport interface RouterOptions {\n logger: Logger;\n config: Config;\n catalogApi: CatalogApi;\n clusterSupplier?: KubernetesClustersSupplier;\n discovery: PluginEndpointDiscovery;\n}\n\n/**\n * creates and configure a new router for handling the kubernetes backend APIs\n * @param options - specifies the options required by this plugin\n * @returns a new router\n * @deprecated Please use the new KubernetesBuilder instead like this\n * ```\n * import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';\n * const { router } = await KubernetesBuilder.createBuilder({\n * logger,\n * config,\n * }).build();\n * ```\n *\n * @alpha\n */\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { router } = await KubernetesBuilder.createBuilder(options)\n .setClusterSupplier(options.clusterSupplier)\n .build();\n return router;\n}\n"],"names":["AWS","Credentials","sign","DefaultAzureCredential","container","_a","ForwardedError","ANNOTATION_KUBERNETES_API_SERVER","ANNOTATION_KUBERNETES_API_SERVER_CA","ANNOTATION_KUBERNETES_AUTH_PROVIDER","CATALOG_FILTER_EXISTS","InputError","parseEntityRef","getBearerTokenFromAuthorizationHeader","AuthenticationError","stringifyEntityRef","KubeConfig","CoreV1Api","Metrics","CustomObjectsApi","lodash","topPods","createProxyMiddleware","bufferFromFileOrString","serializeError","NotFoundError","Duration","Router","express"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ import { Logger } from 'winston';
|
|
|
4
4
|
import { JsonObject } from '@backstage/types';
|
|
5
5
|
import { KubernetesFetchError, FetchResponse, CustomResourceMatcher, KubernetesRequestBody, KubernetesRequestAuth, ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common';
|
|
6
6
|
import { TokenCredential } from '@azure/identity';
|
|
7
|
-
import { Config } from '@backstage/config';
|
|
8
|
-
import express from 'express';
|
|
9
|
-
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
|
10
7
|
import { CatalogApi } from '@backstage/catalog-client';
|
|
8
|
+
import { Config } from '@backstage/config';
|
|
9
|
+
import express, { RequestHandler } from 'express';
|
|
11
10
|
import { Duration } from 'luxon';
|
|
12
11
|
import { KubeConfig, CoreV1Api, Metrics, CustomObjectsApi } from '@kubernetes/client-node';
|
|
12
|
+
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
*
|
|
@@ -312,32 +312,25 @@ declare class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator {
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
/**
|
|
315
|
+
* The header that is used to specify the cluster name.
|
|
315
316
|
*
|
|
316
317
|
* @alpha
|
|
317
318
|
*/
|
|
318
|
-
|
|
319
|
-
logger: Logger;
|
|
320
|
-
config: Config;
|
|
321
|
-
catalogApi: CatalogApi;
|
|
322
|
-
clusterSupplier?: KubernetesClustersSupplier;
|
|
323
|
-
discovery: PluginEndpointDiscovery;
|
|
324
|
-
}
|
|
319
|
+
declare const HEADER_KUBERNETES_CLUSTER: string;
|
|
325
320
|
/**
|
|
326
|
-
*
|
|
327
|
-
* @param options - specifies the options required by this plugin
|
|
328
|
-
* @returns a new router
|
|
329
|
-
* @deprecated Please use the new KubernetesBuilder instead like this
|
|
330
|
-
* ```
|
|
331
|
-
* import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
|
|
332
|
-
* const { router } = await KubernetesBuilder.createBuilder({
|
|
333
|
-
* logger,
|
|
334
|
-
* config,
|
|
335
|
-
* }).build();
|
|
336
|
-
* ```
|
|
321
|
+
* A proxy that routes requests to the Kubernetes API.
|
|
337
322
|
*
|
|
338
323
|
* @alpha
|
|
339
324
|
*/
|
|
340
|
-
declare
|
|
325
|
+
declare class KubernetesProxy {
|
|
326
|
+
private readonly logger;
|
|
327
|
+
private readonly clusterSupplier;
|
|
328
|
+
private readonly middlewareForClusterName;
|
|
329
|
+
constructor(logger: Logger, clusterSupplier: KubernetesClustersSupplier);
|
|
330
|
+
createRequestHandler(): RequestHandler;
|
|
331
|
+
private getMiddleware;
|
|
332
|
+
private getClusterForRequest;
|
|
333
|
+
}
|
|
341
334
|
|
|
342
335
|
/**
|
|
343
336
|
*
|
|
@@ -358,6 +351,7 @@ declare type KubernetesBuilderReturn = Promise<{
|
|
|
358
351
|
clusterSupplier: KubernetesClustersSupplier;
|
|
359
352
|
customResources: CustomResource[];
|
|
360
353
|
fetcher: KubernetesFetcher;
|
|
354
|
+
proxy: KubernetesProxy;
|
|
361
355
|
objectsProvider: KubernetesObjectsProvider;
|
|
362
356
|
serviceLocator: KubernetesServiceLocator;
|
|
363
357
|
}>;
|
|
@@ -372,6 +366,7 @@ declare class KubernetesBuilder {
|
|
|
372
366
|
private objectsProvider?;
|
|
373
367
|
private fetcher?;
|
|
374
368
|
private serviceLocator?;
|
|
369
|
+
private proxy?;
|
|
375
370
|
static createBuilder(env: KubernetesEnvironment): KubernetesBuilder;
|
|
376
371
|
constructor(env: KubernetesEnvironment);
|
|
377
372
|
build(): KubernetesBuilderReturn;
|
|
@@ -380,6 +375,7 @@ declare class KubernetesBuilder {
|
|
|
380
375
|
setObjectsProvider(objectsProvider?: KubernetesObjectsProvider): this;
|
|
381
376
|
setFetcher(fetcher?: KubernetesFetcher): this;
|
|
382
377
|
setServiceLocator(serviceLocator?: KubernetesServiceLocator): this;
|
|
378
|
+
setProxy(proxy?: KubernetesProxy): this;
|
|
383
379
|
protected buildCustomResources(): CustomResource[];
|
|
384
380
|
protected buildClusterSupplier(refreshInterval: Duration): KubernetesClustersSupplier;
|
|
385
381
|
protected buildObjectsProvider(options: KubernetesObjectsProviderOptions): KubernetesObjectsProvider;
|
|
@@ -387,10 +383,16 @@ declare class KubernetesBuilder {
|
|
|
387
383
|
protected buildServiceLocator(method: ServiceLocatorMethod, clusterSupplier: KubernetesClustersSupplier): KubernetesServiceLocator;
|
|
388
384
|
protected buildMultiTenantServiceLocator(clusterSupplier: KubernetesClustersSupplier): KubernetesServiceLocator;
|
|
389
385
|
protected buildHttpServiceLocator(_clusterSupplier: KubernetesClustersSupplier): KubernetesServiceLocator;
|
|
390
|
-
protected
|
|
386
|
+
protected buildProxy(logger: Logger, clusterSupplier: KubernetesClustersSupplier): KubernetesProxy;
|
|
387
|
+
protected buildRouter(objectsProvider: KubernetesObjectsProvider, clusterSupplier: KubernetesClustersSupplier, catalogApi: CatalogApi, proxy: KubernetesProxy): express.Router;
|
|
391
388
|
protected fetchClusterDetails(clusterSupplier: KubernetesClustersSupplier): Promise<ClusterDetails[]>;
|
|
392
389
|
protected getServiceLocatorMethod(): ServiceLocatorMethod;
|
|
390
|
+
protected getFetcher(): KubernetesFetcher;
|
|
391
|
+
protected getClusterSupplier(): KubernetesClustersSupplier;
|
|
392
|
+
protected getServiceLocator(): KubernetesServiceLocator;
|
|
393
|
+
protected getObjectsProvider(options: KubernetesObjectsProviderOptions): KubernetesObjectsProvider;
|
|
393
394
|
protected getObjectTypesToFetch(): ObjectToFetch[] | undefined;
|
|
395
|
+
protected getProxy(logger: Logger, clusterSupplier: KubernetesClustersSupplier): KubernetesProxy;
|
|
394
396
|
}
|
|
395
397
|
|
|
396
398
|
/**
|
|
@@ -410,4 +412,32 @@ declare class KubernetesClientProvider {
|
|
|
410
412
|
*/
|
|
411
413
|
declare const DEFAULT_OBJECTS: ObjectToFetch[];
|
|
412
414
|
|
|
413
|
-
|
|
415
|
+
/**
|
|
416
|
+
*
|
|
417
|
+
* @alpha
|
|
418
|
+
*/
|
|
419
|
+
interface RouterOptions {
|
|
420
|
+
logger: Logger;
|
|
421
|
+
config: Config;
|
|
422
|
+
catalogApi: CatalogApi;
|
|
423
|
+
clusterSupplier?: KubernetesClustersSupplier;
|
|
424
|
+
discovery: PluginEndpointDiscovery;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* creates and configure a new router for handling the kubernetes backend APIs
|
|
428
|
+
* @param options - specifies the options required by this plugin
|
|
429
|
+
* @returns a new router
|
|
430
|
+
* @deprecated Please use the new KubernetesBuilder instead like this
|
|
431
|
+
* ```
|
|
432
|
+
* import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend';
|
|
433
|
+
* const { router } = await KubernetesBuilder.createBuilder({
|
|
434
|
+
* logger,
|
|
435
|
+
* config,
|
|
436
|
+
* }).build();
|
|
437
|
+
* ```
|
|
438
|
+
*
|
|
439
|
+
* @alpha
|
|
440
|
+
*/
|
|
441
|
+
declare function createRouter(options: RouterOptions): Promise<express.Router>;
|
|
442
|
+
|
|
443
|
+
export { AWSClusterDetails, AwsIamKubernetesAuthTranslator, AzureClusterDetails, AzureIdentityKubernetesAuthTranslator, ClusterDetails, CustomResource, CustomResourcesByEntity, DEFAULT_OBJECTS, FetchResponseWrapper, GKEClusterDetails, GoogleKubernetesAuthTranslator, GoogleServiceAccountAuthTranslator, HEADER_KUBERNETES_CLUSTER, KubernetesAuthTranslator, KubernetesAuthTranslatorGenerator, KubernetesBuilder, KubernetesBuilderReturn, KubernetesClientProvider, KubernetesClustersSupplier, KubernetesEnvironment, KubernetesFetcher, KubernetesObjectTypes, KubernetesObjectsByEntity, KubernetesObjectsProvider, KubernetesObjectsProviderOptions, KubernetesProxy, KubernetesServiceLocator, NoopKubernetesAuthTranslator, ObjectFetchParams, ObjectToFetch, ObjectsByEntityRequest, OidcKubernetesAuthTranslator, RouterOptions, ServiceAccountClusterDetails, ServiceLocatorMethod, ServiceLocatorRequestContext, SigningCreds, createRouter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-kubernetes-backend",
|
|
3
3
|
"description": "A Backstage backend plugin that integrates towards Kubernetes",
|
|
4
|
-
"version": "0.8.0",
|
|
4
|
+
"version": "0.8.1-next.0",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -35,14 +35,16 @@
|
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@azure/identity": "^2.0.4",
|
|
38
|
-
"@backstage/backend-common": "^0.16.0",
|
|
39
|
-
"@backstage/
|
|
40
|
-
"@backstage/catalog-
|
|
41
|
-
"@backstage/
|
|
42
|
-
"@backstage/
|
|
43
|
-
"@backstage/
|
|
44
|
-
"@backstage/plugin-
|
|
38
|
+
"@backstage/backend-common": "^0.16.1-next.0",
|
|
39
|
+
"@backstage/backend-test-utils": "^0.1.31-next.0",
|
|
40
|
+
"@backstage/catalog-client": "^1.2.0-next.0",
|
|
41
|
+
"@backstage/catalog-model": "^1.1.4-next.0",
|
|
42
|
+
"@backstage/config": "^1.0.5-next.0",
|
|
43
|
+
"@backstage/errors": "^1.1.4-next.0",
|
|
44
|
+
"@backstage/plugin-auth-node": "^0.2.8-next.0",
|
|
45
|
+
"@backstage/plugin-kubernetes-common": "^0.4.5-next.0",
|
|
45
46
|
"@google-cloud/container": "^4.0.0",
|
|
47
|
+
"@jest-mock/express": "^2.0.1",
|
|
46
48
|
"@kubernetes/client-node": "0.17.0",
|
|
47
49
|
"@types/express": "^4.17.6",
|
|
48
50
|
"@types/luxon": "^3.0.0",
|
|
@@ -54,17 +56,21 @@
|
|
|
54
56
|
"express-promise-router": "^4.1.0",
|
|
55
57
|
"fs-extra": "10.1.0",
|
|
56
58
|
"helmet": "^6.0.0",
|
|
59
|
+
"http-proxy-middleware": "^2.0.6",
|
|
57
60
|
"lodash": "^4.17.21",
|
|
58
61
|
"luxon": "^3.0.0",
|
|
59
62
|
"morgan": "^1.10.0",
|
|
63
|
+
"node-fetch": "^2.6.7",
|
|
60
64
|
"stream-buffers": "^3.0.2",
|
|
61
65
|
"winston": "^3.2.1",
|
|
62
66
|
"yn": "^4.0.0"
|
|
63
67
|
},
|
|
64
68
|
"devDependencies": {
|
|
65
|
-
"@backstage/cli": "^0.21.0",
|
|
69
|
+
"@backstage/cli": "^0.21.2-next.0",
|
|
66
70
|
"@types/aws4": "^1.5.1",
|
|
71
|
+
"@types/http-proxy-middleware": "^0.19.3",
|
|
67
72
|
"aws-sdk-mock": "^5.2.1",
|
|
73
|
+
"msw": "^0.49.0",
|
|
68
74
|
"supertest": "^6.1.3"
|
|
69
75
|
},
|
|
70
76
|
"files": [
|