From 49e6285275167d4713e35d9409e9ec8ad3e63872 Mon Sep 17 00:00:00 2001 From: Andres Mauricio Gomez P Date: Thu, 23 Nov 2023 10:44:44 -0500 Subject: [PATCH] Creating extension point for kubernetesAuthStrategy Signed-off-by: Andres Mauricio Gomez P --- plugins/kubernetes-backend/src/auth/types.ts | 38 --------------- plugins/kubernetes-backend/src/plugin.ts | 47 +++++++++++++++++-- .../src/service/KubernetesBuilder.ts | 6 ++- .../src/service/KubernetesFanOutHandler.ts | 5 +- .../src/service/KubernetesFetcher.ts | 6 ++- plugins/kubernetes-backend/src/types/types.ts | 12 ++++- plugins/kubernetes-node/src/extensions.ts | 20 ++++++++ plugins/kubernetes-node/src/index.ts | 2 + plugins/kubernetes-node/src/types/types.ts | 20 ++++++++ 9 files changed, 107 insertions(+), 49 deletions(-) delete mode 100644 plugins/kubernetes-backend/src/auth/types.ts diff --git a/plugins/kubernetes-backend/src/auth/types.ts b/plugins/kubernetes-backend/src/auth/types.ts deleted file mode 100644 index fff9952bae..0000000000 --- a/plugins/kubernetes-backend/src/auth/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { AuthMetadata, ClusterDetails } from '../types/types'; -import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; - -/** - * Authentication data used to make a request to Kubernetes - * @public - */ -export type KubernetesCredential = - | { type: 'bearer token'; token: string } - | { type: 'anonymous' }; - -/** - * - * @public - */ -export interface AuthenticationStrategy { - getCredential( - clusterDetails: ClusterDetails, - authConfig: KubernetesRequestAuth, - ): Promise; - validateCluster(authMetadata: AuthMetadata): Error[]; -} diff --git a/plugins/kubernetes-backend/src/plugin.ts b/plugins/kubernetes-backend/src/plugin.ts index 2d5f1e1d46..e93e8c5700 100644 --- a/plugins/kubernetes-backend/src/plugin.ts +++ b/plugins/kubernetes-backend/src/plugin.ts @@ -29,6 +29,9 @@ import { KubernetesClusterSupplierExtensionPoint, kubernetesClusterSupplierExtensionPoint, KubernetesClustersSupplier, + KubernetesAuthStrategyExtensionPoint, + AuthenticationStrategy, + kubernetesAuthStrategyExtensionPoint, } from '@backstage/plugin-kubernetes-node'; class ObjectsProvider implements KubernetesObjectsProviderExtensionPoint { @@ -65,6 +68,35 @@ class ClusterSuplier implements KubernetesClusterSupplierExtensionPoint { } } +class AuthStrategy implements KubernetesAuthStrategyExtensionPoint { + private authStrategies: Array<{ + key: string; + strategy: AuthenticationStrategy; + }>; + + constructor() { + this.authStrategies = new Array<{ + key: string; + strategy: AuthenticationStrategy; + }>(); + } + + static addAuthStrategiesFromArray( + authStrategies: Array<{ key: string; strategy: AuthenticationStrategy }>, + builder: KubernetesBuilder, + ) { + authStrategies.forEach(st => builder.addAuthStrategy(st.key, st.strategy)); + } + + getAuthenticationStrategies() { + return this.authStrategies; + } + + addAuthStrategy(key: string, authStrategy: AuthenticationStrategy) { + this.authStrategies.push({ key, strategy: authStrategy }); + } +} + /** * This is the backend plugin that provides the Kubernetes integration. * @alpha @@ -75,6 +107,7 @@ export const kubernetesPlugin = createBackendPlugin({ register(env) { const extPointObjectsProvider = new ObjectsProvider(); const extPointClusterSuplier = new ClusterSuplier(); + const extPointAuthStrategy = new AuthStrategy(); env.registerExtensionPoint( kubernetesObjectsProviderExtensionPoint, extPointObjectsProvider, @@ -83,6 +116,10 @@ export const kubernetesPlugin = createBackendPlugin({ kubernetesClusterSupplierExtensionPoint, extPointClusterSuplier, ); + env.registerExtensionPoint( + kubernetesAuthStrategyExtensionPoint, + extPointAuthStrategy, + ); env.registerInit({ deps: { @@ -95,15 +132,19 @@ export const kubernetesPlugin = createBackendPlugin({ async init({ http, logger, config, catalogApi, permissions }) { const winstonLogger = loggerToWinstonLogger(logger); // TODO: expose all of the customization & extension points of the builder here - const { router } = await KubernetesBuilder.createBuilder({ + const builder: KubernetesBuilder = KubernetesBuilder.createBuilder({ logger: winstonLogger, config, catalogApi, permissions, }) .setObjectsProvider(extPointObjectsProvider.getObjectsProvider()) - .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()) - .build(); + .setClusterSupplier(extPointClusterSuplier.getClusterSupplier()); + AuthStrategy.addAuthStrategiesFromArray( + extPointAuthStrategy.getAuthenticationStrategies(), + builder, + ); + const { router } = await builder.build(); http.use(router); }, }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 3bc7402179..c1ff4688e7 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -46,7 +46,6 @@ import { MultiTenantServiceLocator } from '../service-locator/MultiTenantService import { SingleTenantServiceLocator } from '../service-locator/SingleTenantServiceLocator'; import { CustomResource, - KubernetesClustersSupplier, KubernetesFetcher, KubernetesObjectsProviderOptions, KubernetesObjectTypes, @@ -54,7 +53,10 @@ import { ObjectsByEntityRequest, ServiceLocatorMethod, } from '../types/types'; -import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; +import { + KubernetesClustersSupplier, + KubernetesObjectsProvider, +} from '@backstage/plugin-kubernetes-node'; import { DEFAULT_OBJECTS, KubernetesFanOutHandler, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 3ea06e061e..7a8ff1bf2d 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -17,7 +17,6 @@ import { Entity } from '@backstage/catalog-model'; import { Logger } from 'winston'; import { - ClusterDetails, KubernetesFetcher, KubernetesObjectsProviderOptions, KubernetesServiceLocator, @@ -26,7 +25,6 @@ import { ObjectToFetch, CustomResource, } from '../types/types'; -import { AuthenticationStrategy, KubernetesCredential } from '../auth/types'; import { ClientContainerStatus, ClientCurrentResourceUsage, @@ -45,7 +43,10 @@ import { PodStatus, } from '@kubernetes/client-node'; import { + AuthenticationStrategy, + ClusterDetails, CustomResourcesByEntity, + KubernetesCredential, KubernetesObjectsByEntity, } from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index d5c945a864..99501c48c6 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -26,12 +26,10 @@ import { import lodash, { Dictionary } from 'lodash'; import { Logger } from 'winston'; import { - ClusterDetails, FetchResponseWrapper, KubernetesFetcher, ObjectFetchParams, } from '../types/types'; -import { KubernetesCredential } from '../auth/types'; import { ANNOTATION_KUBERNETES_AUTH_PROVIDER, FetchResponse, @@ -43,6 +41,10 @@ import fetch, { RequestInit, Response } from 'node-fetch'; import * as https from 'https'; import fs from 'fs-extra'; import { JsonObject } from '@backstage/types'; +import { + ClusterDetails, + KubernetesCredential, +} from '@backstage/plugin-kubernetes-node'; export interface KubernetesClientBasedFetcherOptions { logger: Logger; diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index a4bd38802b..c64a2b7863 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -23,8 +23,10 @@ import type { KubernetesRequestBody, } from '@backstage/plugin-kubernetes-common'; import { Config } from '@backstage/config'; -import { KubernetesCredential } from '../auth/types'; -import { ClusterDetails } from '@backstage/plugin-kubernetes-node'; +import { + ClusterDetails, + KubernetesCredential, +} from '@backstage/plugin-kubernetes-node'; /** * @@ -150,3 +152,9 @@ export interface KubernetesObjectsProviderOptions { * @public */ export type ObjectsByEntityRequest = KubernetesRequestBody; + +export type { + AuthMetadata, + ClusterDetails, + KubernetesClustersSupplier, +} from '@backstage/plugin-kubernetes-node'; diff --git a/plugins/kubernetes-node/src/extensions.ts b/plugins/kubernetes-node/src/extensions.ts index 3975fa65c3..3c110be348 100644 --- a/plugins/kubernetes-node/src/extensions.ts +++ b/plugins/kubernetes-node/src/extensions.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { createExtensionPoint } from '@backstage/backend-plugin-api'; +import { AuthenticationStrategy } from '@backstage/plugin-kubernetes-node'; import { KubernetesClustersSupplier } from '@backstage/plugin-kubernetes-node'; import { KubernetesObjectsProvider } from '@backstage/plugin-kubernetes-node'; @@ -54,3 +55,22 @@ export const kubernetesClusterSupplierExtensionPoint = createExtensionPoint({ id: 'kubernetes.cluster-supplier', }); + +/** + * The interface for {@link kubernetesAuthStrategyExtensionPoint}. + * + * @public + */ +export interface KubernetesAuthStrategyExtensionPoint { + addAuthStrategy(key: string, strategy: AuthenticationStrategy): void; +} + +/** + * An extension point the exposes the ability to add an Auth Strategy. + * + * @public + */ +export const kubernetesAuthStrategyExtensionPoint = + createExtensionPoint({ + id: 'kubernetes.auth-strategy', + }); diff --git a/plugins/kubernetes-node/src/index.ts b/plugins/kubernetes-node/src/index.ts index a3da594b43..63a478593c 100644 --- a/plugins/kubernetes-node/src/index.ts +++ b/plugins/kubernetes-node/src/index.ts @@ -34,6 +34,8 @@ export { type KubernetesObjectsProviderExtensionPoint, kubernetesClusterSupplierExtensionPoint, type KubernetesClusterSupplierExtensionPoint, + kubernetesAuthStrategyExtensionPoint, + type KubernetesAuthStrategyExtensionPoint, } from './extensions'; export * from './types'; diff --git a/plugins/kubernetes-node/src/types/types.ts b/plugins/kubernetes-node/src/types/types.ts index f9f60b7085..dfc0395bc4 100644 --- a/plugins/kubernetes-node/src/types/types.ts +++ b/plugins/kubernetes-node/src/types/types.ts @@ -130,3 +130,23 @@ export interface KubernetesClustersSupplier { */ getClusters(): Promise; } + +/** + * Authentication data used to make a request to Kubernetes + * @public + */ +export type KubernetesCredential = + | { type: 'bearer token'; token: string } + | { type: 'anonymous' }; + +/** + * + * @public + */ +export interface AuthenticationStrategy { + getCredential( + clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, + ): Promise; + validateCluster(authMetadata: AuthMetadata): Error[]; +}