@backstage/plugin-kubernetes-backend 0.21.7-next.0 → 0.21.7
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 +28 -0
- package/config.schema.json +24 -0
- package/dist/index.d.ts +29 -3
- package/dist/package.json.cjs.js +1 -1
- package/dist/plugin.cjs.js +5 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/routes/resourcesRoutes.cjs.js +75 -39
- package/dist/routes/resourcesRoutes.cjs.js.map +1 -1
- package/dist/service/KubernetesProxy.cjs.js +177 -64
- package/dist/service/KubernetesProxy.cjs.js.map +1 -1
- package/dist/service/KubernetesRouter.cjs.js +116 -40
- package/dist/service/KubernetesRouter.cjs.js.map +1 -1
- package/dist/service/ProxyAuditSession.cjs.js +128 -0
- package/dist/service/ProxyAuditSession.cjs.js.map +1 -0
- package/dist/service/ProxyMiddlewareCache.cjs.js +69 -0
- package/dist/service/ProxyMiddlewareCache.cjs.js.map +1 -0
- package/package.json +18 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @backstage/plugin-kubernetes-backend
|
|
2
2
|
|
|
3
|
+
## 0.21.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 684c9b9: Fixed `AwsIamStrategy` to resolve account-specific AWS credentials when an assume role ARN is configured, enabling support for `webIdentityTokenFile` and `accountDefaults` in environments without default AWS credentials.
|
|
8
|
+
- c6af8ac: Added audit logging for kubernetes-backend routes. The plugin now emits auditor events for cluster list, cluster proxy, entity workload queries, custom resource queries, and the deprecated services endpoint. Administrators can filter audit logs by `eventId` values `cluster-fetch` and `resource-fetch`, and by `queryType` in event metadata.
|
|
9
|
+
|
|
10
|
+
`KubernetesProxyOptions` accepts an optional `auditor` for adopters that construct the proxy directly. When omitted, proxy requests are handled as before without audit events.
|
|
11
|
+
|
|
12
|
+
- bac00a5: The Kubernetes API proxy now refreshes cached middleware when cluster details change, after a configurable TTL, or when the cache reaches its size limit. At startup, the backend logs a warning for each cluster configured with `skipTLSVerify: true`. Invalid cache configuration values fall back to defaults. Optional configuration is available under `kubernetes.proxy.middlewareCache`.
|
|
13
|
+
- f0834bd: Added a `kubernetes.clusterLocatorContinueOnError` configuration option. When set to `true`, a failing cluster locator no longer causes the entire cluster list request to fail — errors are logged and clusters from the remaining successful locators are still returned. The default is `false`, preserving the existing behavior.
|
|
14
|
+
- Updated dependencies
|
|
15
|
+
- @backstage/catalog-model@1.10.0
|
|
16
|
+
- @backstage/backend-plugin-api@1.10.0
|
|
17
|
+
- @backstage/integration-aws-node@0.2.1
|
|
18
|
+
- @backstage/plugin-permission-common@0.9.10
|
|
19
|
+
- @backstage/plugin-permission-node@0.11.3
|
|
20
|
+
- @backstage/plugin-catalog-node@2.2.4
|
|
21
|
+
- @backstage/plugin-kubernetes-node@0.4.7
|
|
22
|
+
|
|
23
|
+
## 0.22.0-next.1
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- c6af8ac: Added audit logging for kubernetes-backend routes. The plugin now emits auditor events for cluster list, cluster proxy, entity workload queries, custom resource queries, and the deprecated services endpoint. Administrators can filter audit logs by `eventId` values `cluster-fetch` and `resource-fetch`, and by `queryType` in event metadata.
|
|
28
|
+
|
|
29
|
+
**BREAKING**: `KubernetesProxyOptions` now requires `AuditorService`.
|
|
30
|
+
|
|
3
31
|
## 0.21.7-next.0
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/config.schema.json
CHANGED
|
@@ -289,6 +289,30 @@
|
|
|
289
289
|
}
|
|
290
290
|
},
|
|
291
291
|
"description": "(Optional) API Version Overrides If set, the specified api version will be used to make requests for the corresponding object. If running a legacy Kubernetes version, you may use this to override the default api versions that are not supported in your cluster."
|
|
292
|
+
},
|
|
293
|
+
"proxy": {
|
|
294
|
+
"type": "object",
|
|
295
|
+
"properties": {
|
|
296
|
+
"middlewareCache": {
|
|
297
|
+
"type": "object",
|
|
298
|
+
"properties": {
|
|
299
|
+
"maxSize": {
|
|
300
|
+
"type": "number",
|
|
301
|
+
"description": "Maximum number of cached middleware instances. Defaults to 100."
|
|
302
|
+
},
|
|
303
|
+
"ttl": {
|
|
304
|
+
"type": "object",
|
|
305
|
+
"properties": {
|
|
306
|
+
"milliseconds": {
|
|
307
|
+
"type": "number",
|
|
308
|
+
"description": "Time-to-live for cached middleware in milliseconds. Defaults to 60000."
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
"description": "Options for the Kubernetes API proxy middleware cache."
|
|
292
316
|
}
|
|
293
317
|
},
|
|
294
318
|
"required": [
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
|
|
2
|
-
import { LoggerService, DiscoveryService, HttpAuthService, PermissionsService } from '@backstage/backend-plugin-api';
|
|
2
|
+
import { LoggerService, DiscoveryService, HttpAuthService, AuditorService, PermissionsService } from '@backstage/backend-plugin-api';
|
|
3
3
|
import * as k8sTypes from '@backstage/plugin-kubernetes-node';
|
|
4
4
|
import { AuthenticationStrategy, ClusterDetails, KubernetesCredential, AuthMetadata, ObjectToFetch, KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node';
|
|
5
5
|
import { KubernetesRequestAuth, KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
|
|
@@ -222,6 +222,11 @@ type KubernetesProxyOptions = {
|
|
|
222
222
|
authStrategy: AuthenticationStrategy;
|
|
223
223
|
discovery: DiscoveryService;
|
|
224
224
|
httpAuth: HttpAuthService;
|
|
225
|
+
auditor?: AuditorService;
|
|
226
|
+
middlewareCache?: {
|
|
227
|
+
ttlMs?: number;
|
|
228
|
+
maxSize?: number;
|
|
229
|
+
};
|
|
225
230
|
};
|
|
226
231
|
/**
|
|
227
232
|
* A proxy that routes requests to the Kubernetes API.
|
|
@@ -229,14 +234,35 @@ type KubernetesProxyOptions = {
|
|
|
229
234
|
* @public
|
|
230
235
|
*/
|
|
231
236
|
declare class KubernetesProxy {
|
|
232
|
-
private readonly
|
|
237
|
+
private readonly middlewareCache;
|
|
233
238
|
private readonly logger;
|
|
234
239
|
private readonly clusterSupplier;
|
|
235
240
|
private readonly authStrategy;
|
|
236
241
|
private readonly httpAuth;
|
|
242
|
+
private readonly auditor?;
|
|
237
243
|
constructor(options: KubernetesProxyOptions);
|
|
238
244
|
createRequestHandler(options: KubernetesProxyCreateRequestHandlerOptions): RequestHandler;
|
|
239
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Authorizes the request, resolves the target cluster, and dispatches
|
|
247
|
+
* to either the HTTP or WebSocket proxy path. Returns `true` when
|
|
248
|
+
* HTTP finish listeners have been attached.
|
|
249
|
+
*/
|
|
250
|
+
private authorizeAndDispatch;
|
|
251
|
+
/**
|
|
252
|
+
* Resolves the cluster, credentials, and target URL for a proxy request
|
|
253
|
+
* before dispatching to the middleware. This ensures all async preparation
|
|
254
|
+
* completes under the caller's try/catch, avoiding unhandled rejections
|
|
255
|
+
* from http-proxy-middleware's fire-and-forget upgrade() path.
|
|
256
|
+
*/
|
|
257
|
+
private prepareProxyTarget;
|
|
258
|
+
private getOrCreateMiddleware;
|
|
259
|
+
/**
|
|
260
|
+
* Branches to WebSocket upgrade or HTTP middleware dispatch and wires
|
|
261
|
+
* up the appropriate audit listeners. Returns `true` when HTTP finish
|
|
262
|
+
* listeners have been attached (used by the caller's catch block to
|
|
263
|
+
* avoid double-finalizing).
|
|
264
|
+
*/
|
|
265
|
+
private static dispatchToProxy;
|
|
240
266
|
private getClusterForRequest;
|
|
241
267
|
private static authHeadersToKubernetesRequestAuth;
|
|
242
268
|
private static headerToDictionary;
|
package/dist/package.json.cjs.js
CHANGED
package/dist/plugin.cjs.js
CHANGED
|
@@ -146,7 +146,8 @@ const kubernetesPlugin = backendPluginApi.createBackendPlugin({
|
|
|
146
146
|
catalog: pluginCatalogNode.catalogServiceRef,
|
|
147
147
|
permissions: backendPluginApi.coreServices.permissions,
|
|
148
148
|
auth: backendPluginApi.coreServices.auth,
|
|
149
|
-
httpAuth: backendPluginApi.coreServices.httpAuth
|
|
149
|
+
httpAuth: backendPluginApi.coreServices.httpAuth,
|
|
150
|
+
auditor: backendPluginApi.coreServices.auditor
|
|
150
151
|
},
|
|
151
152
|
async init({
|
|
152
153
|
http,
|
|
@@ -156,7 +157,8 @@ const kubernetesPlugin = backendPluginApi.createBackendPlugin({
|
|
|
156
157
|
catalog,
|
|
157
158
|
permissions,
|
|
158
159
|
auth,
|
|
159
|
-
httpAuth
|
|
160
|
+
httpAuth,
|
|
161
|
+
auditor
|
|
160
162
|
}) {
|
|
161
163
|
if (config.has("kubernetes")) {
|
|
162
164
|
const initializer = KubernetesInitializer.KubernetesInitializer.create({
|
|
@@ -185,6 +187,7 @@ const kubernetesPlugin = backendPluginApi.createBackendPlugin({
|
|
|
185
187
|
discovery,
|
|
186
188
|
auth,
|
|
187
189
|
httpAuth,
|
|
190
|
+
auditor,
|
|
188
191
|
authStrategyMap: Object.fromEntries(authStrategyMap.entries()),
|
|
189
192
|
fetcher,
|
|
190
193
|
clusterSupplier,
|
package/dist/plugin.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\n\nimport {\n type AuthenticationStrategy,\n kubernetesAuthStrategyExtensionPoint,\n type KubernetesAuthStrategyExtensionPoint,\n type KubernetesClustersSupplier,\n kubernetesClusterSupplierExtensionPoint,\n type KubernetesClusterSupplierExtensionPoint,\n KubernetesClusterSupplierFactory,\n type KubernetesFetcher,\n kubernetesFetcherExtensionPoint,\n type KubernetesFetcherExtensionPoint,\n KubernetesFetcherFactory,\n type KubernetesObjectsProvider,\n kubernetesObjectsProviderExtensionPoint,\n type KubernetesObjectsProviderExtensionPoint,\n KubernetesObjectsProviderFactory,\n KubernetesRouterExtensionPoint,\n kubernetesRouterExtensionPoint,\n KubernetesRouterFactory,\n type KubernetesServiceLocator,\n kubernetesServiceLocatorExtensionPoint,\n type KubernetesServiceLocatorExtensionPoint,\n KubernetesServiceLocatorFactory,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesRouter } from './service/KubernetesRouter';\nimport { KubernetesInitializer } from './service/KubernetesInitializer';\n\nclass ObjectsProvider implements KubernetesObjectsProviderExtensionPoint {\n private objectsProvider: KubernetesObjectsProviderFactory | undefined;\n\n getObjectsProvider() {\n return this.objectsProvider;\n }\n\n addObjectsProvider(\n provider: KubernetesObjectsProvider | KubernetesObjectsProviderFactory,\n ) {\n if (this.objectsProvider) {\n throw new Error(\n 'Multiple Kubernetes objects provider is not supported at this time',\n );\n }\n if (typeof provider !== 'function') {\n this.objectsProvider = async () => provider;\n } else {\n this.objectsProvider = provider;\n }\n }\n}\n\nclass ClusterSuplier implements KubernetesClusterSupplierExtensionPoint {\n private clusterSupplier: KubernetesClusterSupplierFactory | undefined;\n\n getClusterSupplier() {\n return this.clusterSupplier;\n }\n\n addClusterSupplier(\n clusterSupplier:\n | KubernetesClustersSupplier\n | KubernetesClusterSupplierFactory,\n ) {\n if (this.clusterSupplier) {\n throw new Error(\n 'Multiple Kubernetes Cluster Suppliers is not supported at this time',\n );\n }\n if (typeof clusterSupplier !== 'function') {\n this.clusterSupplier = async () => clusterSupplier;\n } else {\n this.clusterSupplier = clusterSupplier;\n }\n }\n}\n\nclass Fetcher implements KubernetesFetcherExtensionPoint {\n private fetcher: KubernetesFetcherFactory | undefined;\n\n getFetcher() {\n return this.fetcher;\n }\n\n addFetcher(fetcher: KubernetesFetcher | KubernetesFetcherFactory) {\n if (this.fetcher) {\n throw new Error(\n 'Multiple Kubernetes Fetchers is not supported at this time',\n );\n }\n if (typeof fetcher !== 'function') {\n this.fetcher = async () => fetcher;\n } else {\n this.fetcher = fetcher;\n }\n }\n}\n\nclass ServiceLocator implements KubernetesServiceLocatorExtensionPoint {\n private serviceLocator: KubernetesServiceLocatorFactory | undefined;\n\n getServiceLocator() {\n return this.serviceLocator;\n }\n\n addServiceLocator(\n serviceLocator: KubernetesServiceLocator | KubernetesServiceLocatorFactory,\n ) {\n if (this.serviceLocator) {\n throw new Error(\n 'Multiple Kubernetes Service Locators is not supported at this time',\n );\n }\n\n if (typeof serviceLocator !== 'function') {\n this.serviceLocator = async () => serviceLocator;\n } else {\n this.serviceLocator = serviceLocator;\n }\n }\n}\n\nclass AuthStrategy implements KubernetesAuthStrategyExtensionPoint {\n private authStrategies: Map<string, AuthenticationStrategy> | undefined;\n\n getAuthenticationStrategies() {\n return this.authStrategies;\n }\n\n addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) {\n if (!this.authStrategies) {\n this.authStrategies = new Map<string, AuthenticationStrategy>();\n }\n\n if (key.includes('-')) {\n throw new Error('Strategy name can not include dashes');\n }\n\n this.authStrategies.set(key, authStrategy);\n }\n}\n\nclass CustomRouter implements KubernetesRouterExtensionPoint {\n private router: KubernetesRouterFactory | undefined;\n\n getRouter() {\n return this.router;\n }\n\n addRouter(router: KubernetesRouterFactory) {\n if (this.router) {\n throw new Error(\n 'Multiple Kubernetes routers is not supported at this time',\n );\n }\n\n this.router = router;\n }\n}\n\n/**\n * This is the backend plugin that provides the Kubernetes integration.\n * @public\n */\nexport const kubernetesPlugin = createBackendPlugin({\n pluginId: 'kubernetes',\n register(env) {\n const extPointObjectsProvider = new ObjectsProvider();\n const extPointClusterSuplier = new ClusterSuplier();\n const extPointAuthStrategy = new AuthStrategy();\n const extPointFetcher = new Fetcher();\n const extPointServiceLocator = new ServiceLocator();\n const extPointRouter = new CustomRouter();\n\n env.registerExtensionPoint(\n kubernetesObjectsProviderExtensionPoint,\n extPointObjectsProvider,\n );\n env.registerExtensionPoint(\n kubernetesClusterSupplierExtensionPoint,\n extPointClusterSuplier,\n );\n env.registerExtensionPoint(\n kubernetesAuthStrategyExtensionPoint,\n extPointAuthStrategy,\n );\n env.registerExtensionPoint(\n kubernetesFetcherExtensionPoint,\n extPointFetcher,\n );\n env.registerExtensionPoint(\n kubernetesServiceLocatorExtensionPoint,\n extPointServiceLocator,\n );\n env.registerExtensionPoint(kubernetesRouterExtensionPoint, extPointRouter);\n\n env.registerInit({\n deps: {\n http: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n catalog: catalogServiceRef,\n permissions: coreServices.permissions,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n },\n async init({\n http,\n logger,\n config,\n discovery,\n catalog,\n permissions,\n auth,\n httpAuth,\n }) {\n // TODO: this could do with a cleanup and push some of this initialization somewhere else\n if (config.has('kubernetes')) {\n const initializer = KubernetesInitializer.create({\n logger,\n config,\n catalog,\n auth,\n fetcher: extPointFetcher.getFetcher(),\n clusterSupplier: extPointClusterSuplier.getClusterSupplier(),\n serviceLocator: extPointServiceLocator.getServiceLocator(),\n objectsProvider: extPointObjectsProvider.getObjectsProvider(),\n authStrategyMap: extPointAuthStrategy.getAuthenticationStrategies(),\n });\n\n const {\n fetcher,\n authStrategyMap,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n } = await initializer.init();\n\n const router = KubernetesRouter.create({\n logger,\n config,\n catalog,\n permissions,\n discovery,\n auth,\n httpAuth,\n authStrategyMap: Object.fromEntries(authStrategyMap.entries()),\n fetcher,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n customRouter: extPointRouter.getRouter(),\n });\n\n http.use(await router.getRouter());\n } else {\n logger.warn(\n 'Failed to initialize kubernetes backend: valid kubernetes config is missing',\n );\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","kubernetesObjectsProviderExtensionPoint","kubernetesClusterSupplierExtensionPoint","kubernetesAuthStrategyExtensionPoint","kubernetesFetcherExtensionPoint","kubernetesServiceLocatorExtensionPoint","kubernetesRouterExtensionPoint","coreServices","catalogServiceRef","KubernetesInitializer","KubernetesRouter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { catalogServiceRef } from '@backstage/plugin-catalog-node';\n\nimport {\n type AuthenticationStrategy,\n kubernetesAuthStrategyExtensionPoint,\n type KubernetesAuthStrategyExtensionPoint,\n type KubernetesClustersSupplier,\n kubernetesClusterSupplierExtensionPoint,\n type KubernetesClusterSupplierExtensionPoint,\n KubernetesClusterSupplierFactory,\n type KubernetesFetcher,\n kubernetesFetcherExtensionPoint,\n type KubernetesFetcherExtensionPoint,\n KubernetesFetcherFactory,\n type KubernetesObjectsProvider,\n kubernetesObjectsProviderExtensionPoint,\n type KubernetesObjectsProviderExtensionPoint,\n KubernetesObjectsProviderFactory,\n KubernetesRouterExtensionPoint,\n kubernetesRouterExtensionPoint,\n KubernetesRouterFactory,\n type KubernetesServiceLocator,\n kubernetesServiceLocatorExtensionPoint,\n type KubernetesServiceLocatorExtensionPoint,\n KubernetesServiceLocatorFactory,\n} from '@backstage/plugin-kubernetes-node';\nimport { KubernetesRouter } from './service/KubernetesRouter';\nimport { KubernetesInitializer } from './service/KubernetesInitializer';\n\nclass ObjectsProvider implements KubernetesObjectsProviderExtensionPoint {\n private objectsProvider: KubernetesObjectsProviderFactory | undefined;\n\n getObjectsProvider() {\n return this.objectsProvider;\n }\n\n addObjectsProvider(\n provider: KubernetesObjectsProvider | KubernetesObjectsProviderFactory,\n ) {\n if (this.objectsProvider) {\n throw new Error(\n 'Multiple Kubernetes objects provider is not supported at this time',\n );\n }\n if (typeof provider !== 'function') {\n this.objectsProvider = async () => provider;\n } else {\n this.objectsProvider = provider;\n }\n }\n}\n\nclass ClusterSuplier implements KubernetesClusterSupplierExtensionPoint {\n private clusterSupplier: KubernetesClusterSupplierFactory | undefined;\n\n getClusterSupplier() {\n return this.clusterSupplier;\n }\n\n addClusterSupplier(\n clusterSupplier:\n | KubernetesClustersSupplier\n | KubernetesClusterSupplierFactory,\n ) {\n if (this.clusterSupplier) {\n throw new Error(\n 'Multiple Kubernetes Cluster Suppliers is not supported at this time',\n );\n }\n if (typeof clusterSupplier !== 'function') {\n this.clusterSupplier = async () => clusterSupplier;\n } else {\n this.clusterSupplier = clusterSupplier;\n }\n }\n}\n\nclass Fetcher implements KubernetesFetcherExtensionPoint {\n private fetcher: KubernetesFetcherFactory | undefined;\n\n getFetcher() {\n return this.fetcher;\n }\n\n addFetcher(fetcher: KubernetesFetcher | KubernetesFetcherFactory) {\n if (this.fetcher) {\n throw new Error(\n 'Multiple Kubernetes Fetchers is not supported at this time',\n );\n }\n if (typeof fetcher !== 'function') {\n this.fetcher = async () => fetcher;\n } else {\n this.fetcher = fetcher;\n }\n }\n}\n\nclass ServiceLocator implements KubernetesServiceLocatorExtensionPoint {\n private serviceLocator: KubernetesServiceLocatorFactory | undefined;\n\n getServiceLocator() {\n return this.serviceLocator;\n }\n\n addServiceLocator(\n serviceLocator: KubernetesServiceLocator | KubernetesServiceLocatorFactory,\n ) {\n if (this.serviceLocator) {\n throw new Error(\n 'Multiple Kubernetes Service Locators is not supported at this time',\n );\n }\n\n if (typeof serviceLocator !== 'function') {\n this.serviceLocator = async () => serviceLocator;\n } else {\n this.serviceLocator = serviceLocator;\n }\n }\n}\n\nclass AuthStrategy implements KubernetesAuthStrategyExtensionPoint {\n private authStrategies: Map<string, AuthenticationStrategy> | undefined;\n\n getAuthenticationStrategies() {\n return this.authStrategies;\n }\n\n addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) {\n if (!this.authStrategies) {\n this.authStrategies = new Map<string, AuthenticationStrategy>();\n }\n\n if (key.includes('-')) {\n throw new Error('Strategy name can not include dashes');\n }\n\n this.authStrategies.set(key, authStrategy);\n }\n}\n\nclass CustomRouter implements KubernetesRouterExtensionPoint {\n private router: KubernetesRouterFactory | undefined;\n\n getRouter() {\n return this.router;\n }\n\n addRouter(router: KubernetesRouterFactory) {\n if (this.router) {\n throw new Error(\n 'Multiple Kubernetes routers is not supported at this time',\n );\n }\n\n this.router = router;\n }\n}\n\n/**\n * This is the backend plugin that provides the Kubernetes integration.\n * @public\n */\nexport const kubernetesPlugin = createBackendPlugin({\n pluginId: 'kubernetes',\n register(env) {\n const extPointObjectsProvider = new ObjectsProvider();\n const extPointClusterSuplier = new ClusterSuplier();\n const extPointAuthStrategy = new AuthStrategy();\n const extPointFetcher = new Fetcher();\n const extPointServiceLocator = new ServiceLocator();\n const extPointRouter = new CustomRouter();\n\n env.registerExtensionPoint(\n kubernetesObjectsProviderExtensionPoint,\n extPointObjectsProvider,\n );\n env.registerExtensionPoint(\n kubernetesClusterSupplierExtensionPoint,\n extPointClusterSuplier,\n );\n env.registerExtensionPoint(\n kubernetesAuthStrategyExtensionPoint,\n extPointAuthStrategy,\n );\n env.registerExtensionPoint(\n kubernetesFetcherExtensionPoint,\n extPointFetcher,\n );\n env.registerExtensionPoint(\n kubernetesServiceLocatorExtensionPoint,\n extPointServiceLocator,\n );\n env.registerExtensionPoint(kubernetesRouterExtensionPoint, extPointRouter);\n\n env.registerInit({\n deps: {\n http: coreServices.httpRouter,\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n discovery: coreServices.discovery,\n catalog: catalogServiceRef,\n permissions: coreServices.permissions,\n auth: coreServices.auth,\n httpAuth: coreServices.httpAuth,\n auditor: coreServices.auditor,\n },\n async init({\n http,\n logger,\n config,\n discovery,\n catalog,\n permissions,\n auth,\n httpAuth,\n auditor,\n }) {\n // TODO: this could do with a cleanup and push some of this initialization somewhere else\n if (config.has('kubernetes')) {\n const initializer = KubernetesInitializer.create({\n logger,\n config,\n catalog,\n auth,\n fetcher: extPointFetcher.getFetcher(),\n clusterSupplier: extPointClusterSuplier.getClusterSupplier(),\n serviceLocator: extPointServiceLocator.getServiceLocator(),\n objectsProvider: extPointObjectsProvider.getObjectsProvider(),\n authStrategyMap: extPointAuthStrategy.getAuthenticationStrategies(),\n });\n\n const {\n fetcher,\n authStrategyMap,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n } = await initializer.init();\n\n const router = KubernetesRouter.create({\n logger,\n config,\n catalog,\n permissions,\n discovery,\n auth,\n httpAuth,\n auditor,\n authStrategyMap: Object.fromEntries(authStrategyMap.entries()),\n fetcher,\n clusterSupplier,\n serviceLocator,\n objectsProvider,\n customRouter: extPointRouter.getRouter(),\n });\n\n http.use(await router.getRouter());\n } else {\n logger.warn(\n 'Failed to initialize kubernetes backend: valid kubernetes config is missing',\n );\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","kubernetesObjectsProviderExtensionPoint","kubernetesClusterSupplierExtensionPoint","kubernetesAuthStrategyExtensionPoint","kubernetesFetcherExtensionPoint","kubernetesServiceLocatorExtensionPoint","kubernetesRouterExtensionPoint","coreServices","catalogServiceRef","KubernetesInitializer","KubernetesRouter"],"mappings":"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"}
|
|
@@ -5,9 +5,9 @@ var errors = require('@backstage/errors');
|
|
|
5
5
|
var requirePermission = require('../auth/requirePermission.cjs.js');
|
|
6
6
|
var pluginKubernetesCommon = require('@backstage/plugin-kubernetes-common');
|
|
7
7
|
|
|
8
|
-
const addResourceRoutesToRouter = (router, catalog, objectsProvider, httpAuth, permissionApi) => {
|
|
8
|
+
const addResourceRoutesToRouter = (router, catalog, objectsProvider, httpAuth, permissionApi, auditor, logger) => {
|
|
9
9
|
const getEntityByReq = async (req) => {
|
|
10
|
-
const rawEntityRef = req.body
|
|
10
|
+
const rawEntityRef = req.body?.entityRef;
|
|
11
11
|
if (rawEntityRef && typeof rawEntityRef !== "string") {
|
|
12
12
|
throw new errors.InputError(`entity query must be a string`);
|
|
13
13
|
} else if (!rawEntityRef) {
|
|
@@ -30,46 +30,82 @@ const addResourceRoutesToRouter = (router, catalog, objectsProvider, httpAuth, p
|
|
|
30
30
|
return entity;
|
|
31
31
|
};
|
|
32
32
|
router.post("/resources/workloads/query", async (req, res) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
33
|
+
const entityRef = typeof req.body?.entityRef === "string" ? req.body.entityRef : void 0;
|
|
34
|
+
const auditorEvent = await auditor.createEvent({
|
|
35
|
+
eventId: "resource-fetch",
|
|
36
|
+
request: req,
|
|
37
|
+
meta: { queryType: "workloads", entityRef }
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
await requirePermission.requirePermission(
|
|
41
|
+
permissionApi,
|
|
42
|
+
pluginKubernetesCommon.kubernetesResourcesReadPermission,
|
|
43
|
+
httpAuth,
|
|
44
|
+
req
|
|
45
|
+
);
|
|
46
|
+
const entity = await getEntityByReq(req);
|
|
47
|
+
const response = await objectsProvider.getKubernetesObjectsByEntity(
|
|
48
|
+
{
|
|
49
|
+
entity,
|
|
50
|
+
auth: req.body.auth
|
|
51
|
+
},
|
|
52
|
+
{ credentials: await httpAuth.credentials(req) }
|
|
53
|
+
);
|
|
54
|
+
res.json(response);
|
|
55
|
+
auditorEvent.success().catch(
|
|
56
|
+
(error) => logger.error(
|
|
57
|
+
"Failed to emit audit event resource-fetch (workloads)",
|
|
58
|
+
error
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
63
|
+
await auditorEvent.fail({ error: err });
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
48
66
|
});
|
|
49
67
|
router.post("/resources/custom/query", async (req, res) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
const entityRef = typeof req.body?.entityRef === "string" ? req.body.entityRef : void 0;
|
|
69
|
+
const auditorEvent = await auditor.createEvent({
|
|
70
|
+
eventId: "resource-fetch",
|
|
71
|
+
request: req,
|
|
72
|
+
meta: { queryType: "custom", entityRef }
|
|
73
|
+
});
|
|
74
|
+
try {
|
|
75
|
+
await requirePermission.requirePermission(
|
|
76
|
+
permissionApi,
|
|
77
|
+
pluginKubernetesCommon.kubernetesResourcesReadPermission,
|
|
78
|
+
httpAuth,
|
|
79
|
+
req
|
|
80
|
+
);
|
|
81
|
+
const entity = await getEntityByReq(req);
|
|
82
|
+
if (!req.body.customResources) {
|
|
83
|
+
throw new errors.InputError("customResources is a required field");
|
|
84
|
+
} else if (!Array.isArray(req.body.customResources)) {
|
|
85
|
+
throw new errors.InputError("customResources must be an array");
|
|
86
|
+
} else if (req.body.customResources.length === 0) {
|
|
87
|
+
throw new errors.InputError("at least 1 customResource is required");
|
|
88
|
+
}
|
|
89
|
+
const response = await objectsProvider.getCustomResourcesByEntity(
|
|
90
|
+
{
|
|
91
|
+
entity,
|
|
92
|
+
customResources: req.body.customResources,
|
|
93
|
+
auth: req.body.auth
|
|
94
|
+
},
|
|
95
|
+
{ credentials: await httpAuth.credentials(req) }
|
|
96
|
+
);
|
|
97
|
+
res.json(response);
|
|
98
|
+
auditorEvent.success().catch(
|
|
99
|
+
(error) => logger.error(
|
|
100
|
+
"Failed to emit audit event resource-fetch (custom)",
|
|
101
|
+
error
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
106
|
+
await auditorEvent.fail({ error: err });
|
|
107
|
+
throw error;
|
|
63
108
|
}
|
|
64
|
-
const response = await objectsProvider.getCustomResourcesByEntity(
|
|
65
|
-
{
|
|
66
|
-
entity,
|
|
67
|
-
customResources: req.body.customResources,
|
|
68
|
-
auth: req.body.auth
|
|
69
|
-
},
|
|
70
|
-
{ credentials: await httpAuth.credentials(req) }
|
|
71
|
-
);
|
|
72
|
-
res.json(response);
|
|
73
109
|
});
|
|
74
110
|
};
|
|
75
111
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resourcesRoutes.cjs.js","sources":["../../src/routes/resourcesRoutes.ts"],"sourcesContent":["/*\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 { InputError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node';\nimport {
|
|
1
|
+
{"version":3,"file":"resourcesRoutes.cjs.js","sources":["../../src/routes/resourcesRoutes.ts"],"sourcesContent":["/*\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 { InputError } from '@backstage/errors';\nimport express, { Request } from 'express';\nimport { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node';\nimport {\n AuditorService,\n HttpAuthService,\n LoggerService,\n} from '@backstage/backend-plugin-api';\nimport { PermissionEvaluator } from '@backstage/plugin-permission-common';\nimport { requirePermission } from '../auth/requirePermission';\nimport { kubernetesResourcesReadPermission } from '@backstage/plugin-kubernetes-common';\nimport { CatalogService } from '@backstage/plugin-catalog-node';\n\nexport const addResourceRoutesToRouter = (\n router: express.Router,\n catalog: CatalogService,\n objectsProvider: KubernetesObjectsProvider,\n httpAuth: HttpAuthService,\n permissionApi: PermissionEvaluator,\n auditor: AuditorService,\n logger: LoggerService,\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 entity = await catalog.getEntityByRef(entityRef, {\n credentials: await httpAuth.credentials(req),\n });\n if (!entity) {\n throw new InputError(\n `Entity ref missing, ${stringifyEntityRef(entityRef)}`,\n );\n }\n\n return entity;\n };\n\n router.post('/resources/workloads/query', async (req, res) => {\n const entityRef =\n typeof req.body?.entityRef === 'string' ? req.body.entityRef : undefined;\n\n const auditorEvent = await auditor.createEvent({\n eventId: 'resource-fetch',\n request: req,\n meta: { queryType: 'workloads', entityRef },\n });\n\n try {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\n const entity = await getEntityByReq(req);\n const response = await objectsProvider.getKubernetesObjectsByEntity(\n {\n entity,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n auditorEvent\n .success()\n .catch(error =>\n logger.error(\n 'Failed to emit audit event resource-fetch (workloads)',\n error,\n ),\n );\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n await auditorEvent.fail({ error: err });\n throw error;\n }\n });\n\n router.post('/resources/custom/query', async (req, res) => {\n const entityRef =\n typeof req.body?.entityRef === 'string' ? req.body.entityRef : undefined;\n\n const auditorEvent = await auditor.createEvent({\n eventId: 'resource-fetch',\n request: req,\n meta: { queryType: 'custom', entityRef },\n });\n\n try {\n await requirePermission(\n permissionApi,\n kubernetesResourcesReadPermission,\n httpAuth,\n req,\n );\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 {\n entity,\n customResources: req.body.customResources,\n auth: req.body.auth,\n },\n { credentials: await httpAuth.credentials(req) },\n );\n res.json(response);\n auditorEvent\n .success()\n .catch(error =>\n logger.error(\n 'Failed to emit audit event resource-fetch (custom)',\n error,\n ),\n );\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n await auditorEvent.fail({ error: err });\n throw error;\n }\n });\n};\n"],"names":["InputError","parseEntityRef","stringifyEntityRef","requirePermission","kubernetesResourcesReadPermission"],"mappings":"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"}
|