From 54c957c1bc96aaa1718efc7a0b40c18b64c64427 Mon Sep 17 00:00:00 2001 From: Jamie Klassen Date: Wed, 6 Sep 2023 11:22:30 -0400 Subject: [PATCH] rename translators to strategies to encompass their upcoming new responsibilities Signed-off-by: Jamie Klassen --- plugins/kubernetes-backend/api-report.md | 72 ++++++++---------- .../AksStrategy.test.ts} | 8 +- .../AksStrategy.ts} | 3 +- .../AwsIamStrategy.test.ts} | 20 ++--- .../AwsIamStrategy.ts} | 6 +- .../AzureIdentityStrategy.test.ts} | 40 +++++----- .../AzureIdentityStrategy.ts} | 6 +- .../DispatchStrategy.test.ts} | 30 ++++---- .../DispatchStrategy.ts} | 26 +++---- .../GoogleServiceAccountStrategy.ts} | 6 +- .../GoogleStrategy.ts} | 6 +- .../NoopStrategy.ts} | 4 +- .../OidcStrategy.test.ts} | 12 +-- .../OidcStrategy.ts} | 4 +- .../index.ts | 16 ++-- .../types.ts | 2 +- plugins/kubernetes-backend/src/index.ts | 2 +- .../src/service/KubernetesBuilder.ts | 74 +++++++++---------- .../service/KubernetesFanOutHandler.test.ts | 4 +- .../src/service/KubernetesFanOutHandler.ts | 12 +-- .../src/service/KubernetesProxy.test.ts | 43 +++++------ .../src/service/KubernetesProxy.ts | 12 ++- 22 files changed, 191 insertions(+), 217 deletions(-) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AksKubernetesAuthTranslator.test.ts => auth/AksStrategy.test.ts} (76%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AksKubernetesAuthTranslator.ts => auth/AksStrategy.ts} (90%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts => auth/AwsIamStrategy.test.ts} (83%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts => auth/AwsIamStrategy.ts} (96%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.test.ts => auth/AzureIdentityStrategy.test.ts} (70%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts => auth/AzureIdentityStrategy.ts} (95%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.test.ts => auth/DispatchStrategy.test.ts} (60%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.ts => auth/DispatchStrategy.ts} (61%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts => auth/GoogleServiceAccountStrategy.ts} (91%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts => auth/GoogleStrategy.ts} (91%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts => auth/NoopStrategy.ts} (86%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts => auth/OidcStrategy.test.ts} (83%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts => auth/OidcStrategy.ts} (93%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator => auth}/index.ts (60%) rename plugins/kubernetes-backend/src/{kubernetes-auth-translator => auth}/types.ts (95%) diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 37155edc1b..17f1a4e5d9 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -22,7 +22,7 @@ import type { RequestHandler } from 'express'; import { TokenCredential } from '@azure/identity'; // @public (undocumented) -export class AksKubernetesAuthTranslator { +export class AksStrategy implements AuthenticationStrategy { // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, @@ -31,9 +31,16 @@ export class AksKubernetesAuthTranslator { } // @public (undocumented) -export class AwsIamKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export interface AuthenticationStrategy { + // (undocumented) + decorateClusterDetailsWithAuth( + clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, + ): Promise; +} + +// @public (undocumented) +export class AwsIamStrategy implements AuthenticationStrategy { constructor(opts: { config: Config }); // (undocumented) decorateClusterDetailsWithAuth( @@ -42,9 +49,7 @@ export class AwsIamKubernetesAuthTranslator } // @public (undocumented) -export class AzureIdentityKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export class AzureIdentityStrategy implements AuthenticationStrategy { constructor(logger: Logger, tokenCredential?: TokenCredential); // (undocumented) decorateClusterDetailsWithAuth( @@ -92,10 +97,8 @@ export interface CustomResourcesByEntity extends KubernetesObjectsByEntity { export const DEFAULT_OBJECTS: ObjectToFetch[]; // @public -export class DispatchingKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ - constructor(options: DispatchingKubernetesAuthTranslatorOptions); +export class DispatchStrategy implements AuthenticationStrategy { + constructor(options: DispatchStrategyOptions); // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, @@ -104,9 +107,9 @@ export class DispatchingKubernetesAuthTranslator } // @public (undocumented) -export type DispatchingKubernetesAuthTranslatorOptions = { - authTranslatorMap: { - [key: string]: KubernetesAuthTranslator; +export type DispatchStrategyOptions = { + authStrategyMap: { + [key: string]: AuthenticationStrategy; }; }; @@ -119,23 +122,19 @@ export interface FetchResponseWrapper { } // @public (undocumented) -export class GoogleKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export class GoogleServiceAccountStrategy implements AuthenticationStrategy { // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, - authConfig: KubernetesRequestAuth, ): Promise; } // @public (undocumented) -export class GoogleServiceAccountAuthTranslator - implements KubernetesAuthTranslator -{ +export class GoogleStrategy implements AuthenticationStrategy { // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, + authConfig: KubernetesRequestAuth, ): Promise; } @@ -145,23 +144,14 @@ export const HEADER_KUBERNETES_AUTH: string; // @public export const HEADER_KUBERNETES_CLUSTER: string; -// @public (undocumented) -export interface KubernetesAuthTranslator { - // (undocumented) - decorateClusterDetailsWithAuth( - clusterDetails: ClusterDetails, - authConfig: KubernetesRequestAuth, - ): Promise; -} - // @public (undocumented) export class KubernetesBuilder { constructor(env: KubernetesEnvironment); // (undocumented) build(): KubernetesBuilderReturn; // (undocumented) - protected buildAuthTranslatorMap(): { - [key: string]: KubernetesAuthTranslator; + protected buildAuthStrategyMap(): { + [key: string]: AuthenticationStrategy; }; // (undocumented) protected buildClusterSupplier( @@ -210,8 +200,8 @@ export class KubernetesBuilder { clusterSupplier: KubernetesClustersSupplier, ): Promise; // (undocumented) - protected getAuthTranslatorMap(): { - [key: string]: KubernetesAuthTranslator; + protected getAuthStrategyMap(): { + [key: string]: AuthenticationStrategy; }; // (undocumented) protected getClusterSupplier(): KubernetesClustersSupplier; @@ -233,8 +223,8 @@ export class KubernetesBuilder { // (undocumented) protected getServiceLocatorMethod(): ServiceLocatorMethod; // (undocumented) - setAuthTranslatorMap(authTranslatorMap: { - [key: string]: KubernetesAuthTranslator; + setAuthStrategyMap(authStrategyMap: { + [key: string]: AuthenticationStrategy; }): void; // (undocumented) setClusterSupplier(clusterSupplier?: KubernetesClustersSupplier): this; @@ -259,8 +249,8 @@ export type KubernetesBuilderReturn = Promise<{ proxy: KubernetesProxy; objectsProvider: KubernetesObjectsProvider; serviceLocator: KubernetesServiceLocator; - authTranslatorMap: { - [key: string]: KubernetesAuthTranslator; + authStrategyMap: { + [key: string]: AuthenticationStrategy; }; }>; @@ -365,7 +355,7 @@ export type KubernetesProxyCreateRequestHandlerOptions = { export type KubernetesProxyOptions = { logger: Logger; clusterSupplier: KubernetesClustersSupplier; - authTranslator: KubernetesAuthTranslator; + authStrategy: AuthenticationStrategy; }; // @public @@ -380,7 +370,7 @@ export interface KubernetesServiceLocator { } // @public (undocumented) -export class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator { +export class NoopStrategy implements AuthenticationStrategy { // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, @@ -419,7 +409,7 @@ export interface ObjectToFetch { } // @public (undocumented) -export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { +export class OidcStrategy implements AuthenticationStrategy { // (undocumented) decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/auth/AksStrategy.test.ts similarity index 76% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.test.ts rename to plugins/kubernetes-backend/src/auth/AksStrategy.test.ts index b39377f5a3..47d045d6b2 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.test.ts +++ b/plugins/kubernetes-backend/src/auth/AksStrategy.test.ts @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AksKubernetesAuthTranslator } from './AksKubernetesAuthTranslator'; +import { AksStrategy } from './AksStrategy'; -describe('AksKubernetesAuthTranslator', () => { +describe('AksStrategy', () => { it('uses auth.aks value as bearer token', async () => { - const translator = new AksKubernetesAuthTranslator(); + const strategy = new AksStrategy(); - const details = await translator.decorateClusterDetailsWithAuth( + const details = await strategy.decorateClusterDetailsWithAuth( { name: '', authProvider: 'aks', url: '' }, { aks: 'aksToken' }, ); diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/AksStrategy.ts similarity index 90% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/AksStrategy.ts index bdaafc507b..8bd22bcb64 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AksKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/AksStrategy.ts @@ -14,13 +14,14 @@ * limitations under the License. */ import { ClusterDetails } from '../types/types'; +import { AuthenticationStrategy } from './types'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; /** * * @public */ -export class AksKubernetesAuthTranslator { +export class AksStrategy implements AuthenticationStrategy { async decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, auth: KubernetesRequestAuth, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/auth/AwsIamStrategy.test.ts similarity index 83% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts rename to plugins/kubernetes-backend/src/auth/AwsIamStrategy.test.ts index b024283c20..b7182c6c96 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.test.ts +++ b/plugins/kubernetes-backend/src/auth/AwsIamStrategy.test.ts @@ -18,7 +18,7 @@ import { ANNOTATION_KUBERNETES_AWS_ASSUME_ROLE, ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID, } from '@backstage/plugin-kubernetes-common'; -import { AwsIamKubernetesAuthTranslator } from './AwsIamKubernetesAuthTranslator'; +import { AwsIamStrategy } from './AwsIamStrategy'; let presign = jest.fn(async () => ({ hostname: 'https://example.com', @@ -55,12 +55,12 @@ jest.mock('@aws-sdk/credential-providers', () => ({ }, })); -describe('AwsIamKubernetesAuthTranslator tests', () => { +describe('AwsIamStrategy tests', () => { beforeEach(() => {}); it('returns a signed url for AWS credentials without assume role', async () => { - const authTranslator = new AwsIamKubernetesAuthTranslator({ config }); + const strategy = new AwsIamStrategy({ config }); - const authPromise = authTranslator.decorateClusterDetailsWithAuth({ + const authPromise = strategy.decorateClusterDetailsWithAuth({ name: 'test-cluster', url: '', authProvider: 'aws', @@ -71,9 +71,9 @@ describe('AwsIamKubernetesAuthTranslator tests', () => { }); it('returns a signed url for AWS credentials with assume role', async () => { - const authTranslator = new AwsIamKubernetesAuthTranslator({ config }); + const strategy = new AwsIamStrategy({ config }); - const authPromise = authTranslator.decorateClusterDetailsWithAuth({ + const authPromise = strategy.decorateClusterDetailsWithAuth({ name: 'test-cluster', url: '', authProvider: 'aws', @@ -97,9 +97,9 @@ describe('AwsIamKubernetesAuthTranslator tests', () => { }); it('returns a signed url for AWS credentials and passes the external id', async () => { - const authTranslator = new AwsIamKubernetesAuthTranslator({ config }); + const strategy = new AwsIamStrategy({ config }); - const authPromise = authTranslator.decorateClusterDetailsWithAuth({ + const authPromise = strategy.decorateClusterDetailsWithAuth({ name: 'test-cluster', url: '', authProvider: 'aws', @@ -132,9 +132,9 @@ describe('AwsIamKubernetesAuthTranslator tests', () => { }); }); it('throws the right error', async () => { - const authTranslator = new AwsIamKubernetesAuthTranslator({ config }); + const strategy = new AwsIamStrategy({ config }); await expect( - authTranslator.decorateClusterDetailsWithAuth({ + strategy.decorateClusterDetailsWithAuth({ name: 'test-cluster', url: '', authProvider: 'aws', diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts similarity index 96% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts index d76ae985de..131535a67b 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AwsIamKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/AwsIamStrategy.ts @@ -26,7 +26,7 @@ import { ANNOTATION_KUBERNETES_AWS_EXTERNAL_ID, } from '@backstage/plugin-kubernetes-common'; import { ClusterDetails } from '../types/types'; -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; /** * @@ -44,9 +44,7 @@ const defaultRegion = 'us-east-1'; * * @public */ -export class AwsIamKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export class AwsIamStrategy implements AuthenticationStrategy { private readonly credsManager: AwsCredentialsManager; constructor(opts: { config: Config }) { this.credsManager = DefaultAwsCredentialsManager.fromConfig(opts.config); diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.test.ts similarity index 70% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.test.ts rename to plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.test.ts index dbc48857f4..2325593271 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.test.ts +++ b/plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.test.ts @@ -16,7 +16,7 @@ import { AccessToken, TokenCredential } from '@azure/identity'; import { getVoidLogger } from '@backstage/backend-common'; -import { AzureIdentityKubernetesAuthTranslator } from './AzureIdentityKubernetesAuthTranslator'; +import { AzureIdentityStrategy } from './AzureIdentityStrategy'; const logger = getVoidLogger(); @@ -39,7 +39,7 @@ class StaticTokenCredential implements TokenCredential { } } -describe('AzureIdentityKubernetesAuthTranslator tests', () => { +describe('AzureIdentityStrategy tests', () => { const cd = { authProvider: 'Azure', name: 'My Cluster', @@ -51,90 +51,88 @@ describe('AzureIdentityKubernetesAuthTranslator tests', () => { }); it('should decorate cluster with Azure token', async () => { - const authTranslator = new AzureIdentityKubernetesAuthTranslator( + const strategy = new AzureIdentityStrategy( logger, new StaticTokenCredential(5 * 60 * 1000), ); - const response = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response = await strategy.decorateClusterDetailsWithAuth(cd); expect(response.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); }); it('should re-use token before expiry', async () => { - const authTranslator = new AzureIdentityKubernetesAuthTranslator( + const strategy = new AzureIdentityStrategy( logger, new StaticTokenCredential(20 * 60 * 1000), ); - const response = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response = await strategy.decorateClusterDetailsWithAuth(cd); expect(response.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); - const response2 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response2 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response2.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); }); it('should issue new token 15 minutes befory expiry', async () => { jest.useFakeTimers(); - const authTranslator = new AzureIdentityKubernetesAuthTranslator( + const strategy = new AzureIdentityStrategy( logger, new StaticTokenCredential(16 * 60 * 1000), // token expires in 16min ); - const response = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response = await strategy.decorateClusterDetailsWithAuth(cd); expect(response.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); jest.setSystemTime(Date.now() + 2 * 60 * 1000); // advance time by 2mins - const response2 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response2 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response2.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_2'); }); it('should re-use existing token if there is afailure', async () => { jest.useFakeTimers(); - const authTranslator = new AzureIdentityKubernetesAuthTranslator( + const strategy = new AzureIdentityStrategy( logger, new StaticTokenCredential(16 * 60 * 1000), // new tokens expires in 16min ); - const response = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response = await strategy.decorateClusterDetailsWithAuth(cd); expect(response.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); jest.setSystemTime(Date.now() + 2 * 60 * 1000); // advance time by 2min - const response2 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response2 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response2.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_2'); jest.setSystemTime(Date.now() + 2 * 60 * 1000); // advance time by 2min - const response3 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response3 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response3.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_2'); - const response4 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response4 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response4.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_4'); }); it('should throw if existing token expired and failed to fetch a new one', async () => { jest.useFakeTimers(); - const authTranslator = new AzureIdentityKubernetesAuthTranslator( + const strategy = new AzureIdentityStrategy( logger, new StaticTokenCredential(16 * 60 * 1000), // new tokens expires in 16min ); - const response = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response = await strategy.decorateClusterDetailsWithAuth(cd); expect(response.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_1'); jest.setSystemTime(Date.now() + 2 * 60 * 1000); // advance time by 2min - const response2 = await authTranslator.decorateClusterDetailsWithAuth(cd); + const response2 = await strategy.decorateClusterDetailsWithAuth(cd); expect(response2.authMetadata!.serviceAccountToken).toEqual('MY_TOKEN_2'); jest.setSystemTime(Date.now() + 17 * 60 * 1000); // advance time by 17min - await expect( - authTranslator.decorateClusterDetailsWithAuth(cd), - ).rejects.toThrow(); + await expect(strategy.decorateClusterDetailsWithAuth(cd)).rejects.toThrow(); }); }); diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.ts similarity index 95% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.ts index 3e0622a9d2..038100a19f 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/AzureIdentityKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/AzureIdentityStrategy.ts @@ -15,7 +15,7 @@ */ import { Logger } from 'winston'; -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types/types'; import { AccessToken, @@ -29,9 +29,7 @@ const aksScope = '6dae42f8-4368-4678-94ff-3960e28e3630/.default'; // This scope * * @public */ -export class AzureIdentityKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export class AzureIdentityStrategy implements AuthenticationStrategy { private accessToken: AccessToken = { token: '', expiresOnTimestamp: 0 }; private newTokenPromise: Promise | undefined; diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/auth/DispatchStrategy.test.ts similarity index 60% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.test.ts rename to plugins/kubernetes-backend/src/auth/DispatchStrategy.test.ts index be41c593f2..d53f9f1e6c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.test.ts +++ b/plugins/kubernetes-backend/src/auth/DispatchStrategy.test.ts @@ -14,50 +14,50 @@ * limitations under the License. */ -import { DispatchingKubernetesAuthTranslator } from './DispatchingKubernetesAuthTranslator'; +import { DispatchStrategy } from './DispatchStrategy'; import { ClusterDetails } from '../types'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; describe('decorateClusterDetailsWithAuth', () => { - let authTranslator: DispatchingKubernetesAuthTranslator; - let mockTranslator: jest.Mocked; + let strategy: DispatchStrategy; + let mockStrategy: jest.Mocked; const authObject: KubernetesRequestAuth = {}; beforeEach(() => { - mockTranslator = { decorateClusterDetailsWithAuth: jest.fn() }; - authTranslator = new DispatchingKubernetesAuthTranslator({ - authTranslatorMap: { google: mockTranslator }, + mockStrategy = { decorateClusterDetailsWithAuth: jest.fn() }; + strategy = new DispatchStrategy({ + authStrategyMap: { google: mockStrategy }, }); }); - it('can decorate cluster details if the auth provider is in the translator map', async () => { + it('can decorate cluster details if the auth provider is in the strategy map', async () => { const expectedClusterDetails: ClusterDetails = { url: 'notanything.com', name: 'randomName', authProvider: 'google', - authMetadata: { serviceAccountToken: 'added by mock translator' }, + authMetadata: { serviceAccountToken: 'added by mock strategy' }, }; - mockTranslator.decorateClusterDetailsWithAuth.mockResolvedValue( + mockStrategy.decorateClusterDetailsWithAuth.mockResolvedValue( expectedClusterDetails, ); - const returnedValue = await authTranslator.decorateClusterDetailsWithAuth( + const returnedValue = await strategy.decorateClusterDetailsWithAuth( { name: 'googleCluster', url: 'anything.com', authProvider: 'google' }, authObject, ); - expect(mockTranslator.decorateClusterDetailsWithAuth).toHaveBeenCalledWith( + expect(mockStrategy.decorateClusterDetailsWithAuth).toHaveBeenCalledWith( { name: 'googleCluster', url: 'anything.com', authProvider: 'google' }, authObject, ); expect(returnedValue).toBe(expectedClusterDetails); }); - it('throws an error when asked for an auth translator for an unsupported auth type', () => { + it('throws an error when asked for a strategy for an unsupported auth type', () => { expect(() => - authTranslator.decorateClusterDetailsWithAuth( + strategy.decorateClusterDetailsWithAuth( { name: 'test-cluster', url: 'anything.com', @@ -66,7 +66,7 @@ describe('decorateClusterDetailsWithAuth', () => { authObject, ), ).toThrow( - 'authProvider "linode" has no KubernetesAuthTranslator associated with it', + 'authProvider "linode" has no AuthenticationStrategy associated with it', ); }); }); diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/DispatchStrategy.ts similarity index 61% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/DispatchStrategy.ts index 82d9538cac..c40ff66d27 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/DispatchingKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/DispatchStrategy.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; @@ -22,35 +22,33 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; * * @public */ -export type DispatchingKubernetesAuthTranslatorOptions = { - authTranslatorMap: { - [key: string]: KubernetesAuthTranslator; +export type DispatchStrategyOptions = { + authStrategyMap: { + [key: string]: AuthenticationStrategy; }; }; /** - * used to direct a KubernetesAuthProvider to its corresponding KubernetesAuthTranslator + * used to direct a KubernetesAuthProvider to its corresponding AuthenticationStrategy * @public */ -export class DispatchingKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ - private readonly translatorMap: { [key: string]: KubernetesAuthTranslator }; +export class DispatchStrategy implements AuthenticationStrategy { + private readonly strategyMap: { [key: string]: AuthenticationStrategy }; - constructor(options: DispatchingKubernetesAuthTranslatorOptions) { - this.translatorMap = options.authTranslatorMap; + constructor(options: DispatchStrategyOptions) { + this.strategyMap = options.authStrategyMap; } public decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, auth: KubernetesRequestAuth, ) { - if (this.translatorMap[clusterDetails.authProvider]) { - return this.translatorMap[ + if (this.strategyMap[clusterDetails.authProvider]) { + return this.strategyMap[ clusterDetails.authProvider ].decorateClusterDetailsWithAuth(clusterDetails, auth); } throw new Error( - `authProvider "${clusterDetails.authProvider}" has no KubernetesAuthTranslator associated with it`, + `authProvider "${clusterDetails.authProvider}" has no AuthenticationStrategy associated with it`, ); } } diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts b/plugins/kubernetes-backend/src/auth/GoogleServiceAccountStrategy.ts similarity index 91% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts rename to plugins/kubernetes-backend/src/auth/GoogleServiceAccountStrategy.ts index 8aa60e0012..db8d9d2c2c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleServiceAccountAuthProvider.ts +++ b/plugins/kubernetes-backend/src/auth/GoogleServiceAccountStrategy.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types/types'; import * as container from '@google-cloud/container'; @@ -21,9 +21,7 @@ import * as container from '@google-cloud/container'; * * @public */ -export class GoogleServiceAccountAuthTranslator - implements KubernetesAuthTranslator -{ +export class GoogleServiceAccountStrategy implements AuthenticationStrategy { async decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, ): Promise { diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/GoogleStrategy.ts similarity index 91% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/GoogleStrategy.ts index d0bef9c21b..c14f85051c 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/GoogleKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/GoogleStrategy.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types/types'; import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; @@ -22,9 +22,7 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; * * @public */ -export class GoogleKubernetesAuthTranslator - implements KubernetesAuthTranslator -{ +export class GoogleStrategy implements AuthenticationStrategy { async decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, authConfig: KubernetesRequestAuth, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/NoopStrategy.ts similarity index 86% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/NoopStrategy.ts index a44710f58b..c96d2a55c7 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/NoopKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/NoopStrategy.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types/types'; /** * * @public */ -export class NoopKubernetesAuthTranslator implements KubernetesAuthTranslator { +export class NoopStrategy implements AuthenticationStrategy { async decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, ): Promise { diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts b/plugins/kubernetes-backend/src/auth/OidcStrategy.test.ts similarity index 83% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts rename to plugins/kubernetes-backend/src/auth/OidcStrategy.test.ts index 2641922b3a..1160308521 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.test.ts +++ b/plugins/kubernetes-backend/src/auth/OidcStrategy.test.ts @@ -15,11 +15,11 @@ */ import { ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER } from '@backstage/plugin-kubernetes-common'; -import { OidcKubernetesAuthTranslator } from './OidcKubernetesAuthTranslator'; +import { OidcStrategy } from './OidcStrategy'; import { ClusterDetails } from '../types/types'; -describe('OidcKubernetesAuthTranslator tests', () => { - const at = new OidcKubernetesAuthTranslator(); +describe('OidcStrategy tests', () => { + const strategy = new OidcStrategy(); const baseClusterDetails: ClusterDetails = { name: 'test', authProvider: 'oidc', @@ -27,7 +27,7 @@ describe('OidcKubernetesAuthTranslator tests', () => { }; it('returns cluster details with auth token', async () => { - const details = await at.decorateClusterDetailsWithAuth( + const details = await strategy.decorateClusterDetailsWithAuth( { authMetadata: { [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'okta' }, ...baseClusterDetails, @@ -42,7 +42,7 @@ describe('OidcKubernetesAuthTranslator tests', () => { it('returns error when oidcTokenProvider is not configured', async () => { await expect( - at.decorateClusterDetailsWithAuth(baseClusterDetails, {}), + strategy.decorateClusterDetailsWithAuth(baseClusterDetails, {}), ).rejects.toThrow( 'oidc authProvider requires a configured oidcTokenProvider', ); @@ -50,7 +50,7 @@ describe('OidcKubernetesAuthTranslator tests', () => { it('returns error when token is not included in request body', async () => { await expect( - at.decorateClusterDetailsWithAuth( + strategy.decorateClusterDetailsWithAuth( { authMetadata: { [ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER]: 'okta' }, ...baseClusterDetails, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts b/plugins/kubernetes-backend/src/auth/OidcStrategy.ts similarity index 93% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts rename to plugins/kubernetes-backend/src/auth/OidcStrategy.ts index ef13bfb146..db41ba6776 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/OidcKubernetesAuthTranslator.ts +++ b/plugins/kubernetes-backend/src/auth/OidcStrategy.ts @@ -17,14 +17,14 @@ import { ANNOTATION_KUBERNETES_OIDC_TOKEN_PROVIDER, KubernetesRequestAuth, } from '@backstage/plugin-kubernetes-common'; -import { KubernetesAuthTranslator } from './types'; +import { AuthenticationStrategy } from './types'; import { ClusterDetails } from '../types/types'; /** * * @public */ -export class OidcKubernetesAuthTranslator implements KubernetesAuthTranslator { +export class OidcStrategy implements AuthenticationStrategy { async decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, authConfig: KubernetesRequestAuth, diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/index.ts b/plugins/kubernetes-backend/src/auth/index.ts similarity index 60% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/index.ts rename to plugins/kubernetes-backend/src/auth/index.ts index 71dcedfee6..2caefc3a12 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/index.ts +++ b/plugins/kubernetes-backend/src/auth/index.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -export * from './AksKubernetesAuthTranslator'; -export * from './AwsIamKubernetesAuthTranslator'; -export * from './AzureIdentityKubernetesAuthTranslator'; -export * from './GoogleKubernetesAuthTranslator'; -export * from './GoogleServiceAccountAuthProvider'; -export * from './DispatchingKubernetesAuthTranslator'; -export * from './NoopKubernetesAuthTranslator'; -export * from './OidcKubernetesAuthTranslator'; +export * from './AksStrategy'; +export * from './AwsIamStrategy'; +export * from './AzureIdentityStrategy'; +export * from './GoogleStrategy'; +export * from './GoogleServiceAccountStrategy'; +export * from './DispatchStrategy'; +export * from './NoopStrategy'; +export * from './OidcStrategy'; export * from './types'; diff --git a/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts b/plugins/kubernetes-backend/src/auth/types.ts similarity index 95% rename from plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts rename to plugins/kubernetes-backend/src/auth/types.ts index efbbff8250..79a581bfd0 100644 --- a/plugins/kubernetes-backend/src/kubernetes-auth-translator/types.ts +++ b/plugins/kubernetes-backend/src/auth/types.ts @@ -21,7 +21,7 @@ import { KubernetesRequestAuth } from '@backstage/plugin-kubernetes-common'; * * @public */ -export interface KubernetesAuthTranslator { +export interface AuthenticationStrategy { decorateClusterDetailsWithAuth( clusterDetails: ClusterDetails, authConfig: KubernetesRequestAuth, diff --git a/plugins/kubernetes-backend/src/index.ts b/plugins/kubernetes-backend/src/index.ts index 67aefbd974..d32dfc24be 100644 --- a/plugins/kubernetes-backend/src/index.ts +++ b/plugins/kubernetes-backend/src/index.ts @@ -20,6 +20,6 @@ * @packageDocumentation */ -export * from './kubernetes-auth-translator'; +export * from './auth'; export * from './service'; export * from './types'; diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index 905ef521a3..02ea54a1d5 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -25,16 +25,16 @@ import { Logger } from 'winston'; import { getCombinedClusterSupplier } from '../cluster-locator'; import { - KubernetesAuthTranslator, - DispatchingKubernetesAuthTranslator, - GoogleKubernetesAuthTranslator, - NoopKubernetesAuthTranslator, - AwsIamKubernetesAuthTranslator, - GoogleServiceAccountAuthTranslator, - AzureIdentityKubernetesAuthTranslator, - OidcKubernetesAuthTranslator, - AksKubernetesAuthTranslator, -} from '../kubernetes-auth-translator'; + AuthenticationStrategy, + DispatchStrategy, + GoogleStrategy, + NoopStrategy, + AwsIamStrategy, + GoogleServiceAccountStrategy, + AzureIdentityStrategy, + OidcStrategy, + AksStrategy, +} from '../auth'; import { addResourceRoutesToRouter } from '../routes/resourcesRoutes'; import { MultiTenantServiceLocator } from '../service-locator/MultiTenantServiceLocator'; @@ -80,7 +80,7 @@ export type KubernetesBuilderReturn = Promise<{ proxy: KubernetesProxy; objectsProvider: KubernetesObjectsProvider; serviceLocator: KubernetesServiceLocator; - authTranslatorMap: { [key: string]: KubernetesAuthTranslator }; + authStrategyMap: { [key: string]: AuthenticationStrategy }; }>; /** @@ -96,7 +96,7 @@ export class KubernetesBuilder { private fetcher?: KubernetesFetcher; private serviceLocator?: KubernetesServiceLocator; private proxy?: KubernetesProxy; - private authTranslatorMap?: { [key: string]: KubernetesAuthTranslator }; + private authStrategyMap?: { [key: string]: AuthenticationStrategy }; static createBuilder(env: KubernetesEnvironment) { return new KubernetesBuilder(env); @@ -128,7 +128,7 @@ export class KubernetesBuilder { const clusterSupplier = this.getClusterSupplier(); - const authTranslatorMap = this.getAuthTranslatorMap(); + const authStrategyMap = this.getAuthStrategyMap(); const proxy = this.getProxy(logger, clusterSupplier); @@ -159,7 +159,7 @@ export class KubernetesBuilder { objectsProvider, router, serviceLocator, - authTranslatorMap, + authStrategyMap, }; } @@ -193,10 +193,10 @@ export class KubernetesBuilder { return this; } - public setAuthTranslatorMap(authTranslatorMap: { - [key: string]: KubernetesAuthTranslator; + public setAuthStrategyMap(authStrategyMap: { + [key: string]: AuthenticationStrategy; }) { - this.authTranslatorMap = authTranslatorMap; + this.authStrategyMap = authStrategyMap; } protected buildCustomResources() { @@ -234,11 +234,11 @@ export class KubernetesBuilder { protected buildObjectsProvider( options: KubernetesObjectsProviderOptions, ): KubernetesObjectsProvider { - const authTranslatorMap = this.getAuthTranslatorMap(); + const authStrategyMap = this.getAuthStrategyMap(); this.objectsProvider = new KubernetesFanOutHandler({ ...options, - authTranslator: new DispatchingKubernetesAuthTranslator({ - authTranslatorMap, + authStrategy: new DispatchStrategy({ + authStrategyMap, }), }); @@ -290,14 +290,14 @@ export class KubernetesBuilder { logger: Logger, clusterSupplier: KubernetesClustersSupplier, ): KubernetesProxy { - const authTranslatorMap = this.getAuthTranslatorMap(); - const authTranslator = new DispatchingKubernetesAuthTranslator({ - authTranslatorMap, + const authStrategyMap = this.getAuthStrategyMap(); + const authStrategy = new DispatchStrategy({ + authStrategyMap, }); this.proxy = new KubernetesProxy({ logger, clusterSupplier, - authTranslator, + authStrategy, }); return this.proxy; } @@ -356,18 +356,18 @@ export class KubernetesBuilder { return router; } - protected buildAuthTranslatorMap() { - this.authTranslatorMap = { - google: new GoogleKubernetesAuthTranslator(), - aks: new AksKubernetesAuthTranslator(), - aws: new AwsIamKubernetesAuthTranslator({ config: this.env.config }), - azure: new AzureIdentityKubernetesAuthTranslator(this.env.logger), - serviceAccount: new NoopKubernetesAuthTranslator(), - googleServiceAccount: new GoogleServiceAccountAuthTranslator(), - oidc: new OidcKubernetesAuthTranslator(), - localKubectlProxy: new NoopKubernetesAuthTranslator(), + protected buildAuthStrategyMap() { + this.authStrategyMap = { + google: new GoogleStrategy(), + aks: new AksStrategy(), + aws: new AwsIamStrategy({ config: this.env.config }), + azure: new AzureIdentityStrategy(this.env.logger), + serviceAccount: new NoopStrategy(), + googleServiceAccount: new GoogleServiceAccountStrategy(), + oidc: new OidcStrategy(), + localKubectlProxy: new NoopStrategy(), }; - return this.authTranslatorMap; + return this.authStrategyMap; } protected async fetchClusterDetails( @@ -450,7 +450,7 @@ export class KubernetesBuilder { return this.proxy ?? this.buildProxy(logger, clusterSupplier); } - protected getAuthTranslatorMap() { - return this.authTranslatorMap ?? this.buildAuthTranslatorMap(); + protected getAuthStrategyMap() { + return this.authStrategyMap ?? this.buildAuthStrategyMap(); } } diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts index e092ac082c..1748beb006 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.test.ts @@ -179,7 +179,7 @@ describe('KubernetesFanOutHandler', () => { getClustersByEntity, }, customResources: customResources, - authTranslator: { + authStrategy: { decorateClusterDetailsWithAuth: async (clusterDetails, _) => { return clusterDetails; }, @@ -1100,7 +1100,7 @@ describe('KubernetesFanOutHandler', () => { objectType: 'services', }, ], - authTranslator: { + authStrategy: { decorateClusterDetailsWithAuth: async (clusterDetails, _) => { return clusterDetails; }, diff --git a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts index 79003ae1ca..98ad41947b 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFanOutHandler.ts @@ -29,7 +29,7 @@ import { KubernetesObjectsByEntity, ServiceLocatorRequestContext, } from '../types/types'; -import { KubernetesAuthTranslator } from '../kubernetes-auth-translator/types'; +import { AuthenticationStrategy } from '../auth/types'; import { ClientContainerStatus, ClientCurrentResourceUsage, @@ -137,7 +137,7 @@ export const DEFAULT_OBJECTS: ObjectToFetch[] = [ export interface KubernetesFanOutHandlerOptions extends KubernetesObjectsProviderOptions { - authTranslator: KubernetesAuthTranslator; + authStrategy: AuthenticationStrategy; } export interface KubernetesRequestBody extends ObjectsByEntityRequest {} @@ -196,7 +196,7 @@ export class KubernetesFanOutHandler { private readonly serviceLocator: KubernetesServiceLocator; private readonly customResources: CustomResource[]; private readonly objectTypesToFetch: Set; - private readonly authTranslator: KubernetesAuthTranslator; + private readonly authStrategy: AuthenticationStrategy; constructor({ logger, @@ -204,14 +204,14 @@ export class KubernetesFanOutHandler { serviceLocator, customResources, objectTypesToFetch = DEFAULT_OBJECTS, - authTranslator, + authStrategy, }: KubernetesFanOutHandlerOptions) { this.logger = logger; this.fetcher = fetcher; this.serviceLocator = serviceLocator; this.customResources = customResources; this.objectTypesToFetch = new Set(objectTypesToFetch); - this.authTranslator = authTranslator; + this.authStrategy = authStrategy; } async getCustomResourcesByEntity({ @@ -317,7 +317,7 @@ export class KubernetesFanOutHandler { // Execute all of these async actions simultaneously/without blocking sequentially as no common object is modified by them const promiseResults = await Promise.allSettled( clusterDetails.map(cd => { - return this.authTranslator.decorateClusterDetailsWithAuth(cd, auth); + return this.authStrategy.decorateClusterDetailsWithAuth(cd, auth); }), ); diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts index 8f25b217ab..6fc5c26620 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts @@ -33,10 +33,7 @@ import request from 'supertest'; import { AddressInfo, WebSocket, WebSocketServer } from 'ws'; import { LocalKubectlProxyClusterLocator } from '../cluster-locator/LocalKubectlProxyLocator'; -import { - KubernetesAuthTranslator, - NoopKubernetesAuthTranslator, -} from '../kubernetes-auth-translator'; +import { AuthenticationStrategy, NoopStrategy } from '../auth'; import { ClusterDetails, KubernetesClustersSupplier } from '../types/types'; import { APPLICATION_JSON, @@ -62,7 +59,7 @@ describe('KubernetesProxy', () => { authorizeConditional: jest.fn(), }; - const authTranslator: jest.Mocked = { + const authStrategy: jest.Mocked = { decorateClusterDetailsWithAuth: jest.fn(), }; @@ -126,7 +123,7 @@ describe('KubernetesProxy', () => { beforeEach(() => { jest.resetAllMocks(); - proxy = new KubernetesProxy({ logger, clusterSupplier, authTranslator }); + proxy = new KubernetesProxy({ logger, clusterSupplier, authStrategy }); permissionApi.authorize.mockResolvedValue([ { result: AuthorizeResult.ALLOW }, ]); @@ -205,7 +202,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'cluster1', url: 'https://localhost:9999', authProvider: 'serviceAccount', @@ -249,7 +246,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'cluster1', url: 'https://localhost:9999', authProvider: 'serviceAccount', @@ -292,7 +289,7 @@ describe('KubernetesProxy', () => { authProvider: '', }, ]); - authTranslator.decorateClusterDetailsWithAuth.mockImplementation( + authStrategy.decorateClusterDetailsWithAuth.mockImplementation( async x => x, ); @@ -308,7 +305,7 @@ describe('KubernetesProxy', () => { expect(response.status).toEqual(200); }); - it('should default to using a authTranslator provided serviceAccountToken as authorization headers to kubeapi when backstage-kubernetes-auth field is not provided', async () => { + it('should default to using an authStrategy-provided serviceAccountToken as authorization headers to kubeapi when backstage-kubernetes-auth field is not provided', async () => { worker.use( rest.get( 'https://localhost:9999/api/v1/namespaces', @@ -319,7 +316,7 @@ describe('KubernetesProxy', () => { if ( req.headers.get('Authorization') !== - 'Bearer translator-provided-token' + 'Bearer strategy-provided-token' ) { return res(ctx.status(403)); } @@ -344,11 +341,11 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'cluster1', url: 'https://localhost:9999', authProvider: 'serviceAccount', - authMetadata: { serviceAccountToken: 'translator-provided-token' }, + authMetadata: { serviceAccountToken: 'strategy-provided-token' }, } as ClusterDetails); const requestPromise = setupProxyPromise({ @@ -363,7 +360,7 @@ describe('KubernetesProxy', () => { expect(response.status).toEqual(200); }); - it('should add a authTranslator provided serviceAccountToken as authorization headers to kubeapi if one isnt provided in request and one isnt set up in cluster details', async () => { + it('should add an authStrategy-provided serviceAccountToken as authorization headers to kubeapi if one isnt provided in request and one isnt set up in cluster details', async () => { worker.use( rest.get('https://localhost:9999/api/v1/namespaces', (req, res, ctx) => { if (!req.headers.get('Authorization')) { @@ -393,7 +390,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'cluster1', url: 'https://localhost:9999', authProvider: 'googleServiceAccount', @@ -447,7 +444,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'cluster1', url: 'https://localhost:9999', authProvider: 'googleServiceAccount', @@ -474,7 +471,7 @@ describe('KubernetesProxy', () => { }); }); - it('should not invoke authTranslator if Backstage-Kubernetes-Authorization field is provided', async () => { + it('should not invoke authStrategy if Backstage-Kubernetes-Authorization field is provided', async () => { worker.use( rest.get('https://localhost:9999/api/v1/namespaces', (req, res, ctx) => { if (!req.headers.get('Authorization')) { @@ -516,7 +513,7 @@ describe('KubernetesProxy', () => { const response = await requestPromise; - expect(authTranslator.decorateClusterDetailsWithAuth).toHaveBeenCalledTimes( + expect(authStrategy.decorateClusterDetailsWithAuth).toHaveBeenCalledTimes( 0, ); expect(response.status).toEqual(200); @@ -531,7 +528,7 @@ describe('KubernetesProxy', () => { proxy = new KubernetesProxy({ logger: getVoidLogger(), clusterSupplier: new LocalKubectlProxyClusterLocator(), - authTranslator: new NoopKubernetesAuthTranslator(), + authStrategy: new NoopStrategy(), }); worker.use( @@ -568,7 +565,7 @@ describe('KubernetesProxy', () => { }); }); - it('returns a 500 error if authTranslator errors out and Backstage-Kubernetes-Authorization field is not provided', async () => { + it('returns a 500 error if authStrategy errors out and Backstage-Kubernetes-Authorization field is not provided', async () => { worker.use( rest.get('https://localhost:9999/api/v1/namespaces', (req, res, ctx) => { if (!req.headers.get('Authorization')) { @@ -599,7 +596,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockRejectedValue( + authStrategy.decorateClusterDetailsWithAuth.mockRejectedValue( Error('some internal error'), ); @@ -642,7 +639,7 @@ describe('KubernetesProxy', () => { }, ]); - authTranslator.decorateClusterDetailsWithAuth.mockImplementation( + authStrategy.decorateClusterDetailsWithAuth.mockImplementation( async x => x, ); @@ -787,7 +784,7 @@ describe('KubernetesProxy', () => { }, ] as ClusterDetails[]); - authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({ + authStrategy.decorateClusterDetailsWithAuth.mockResolvedValue({ name: 'local', url: `http://localhost:${wsPort}`, authProvider: 'serviceAccount', diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index e3fc293436..07753a2517 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -31,7 +31,7 @@ import { bufferFromFileOrString } from '@kubernetes/client-node'; import type { Request, RequestHandler } from 'express'; import { createProxyMiddleware } from 'http-proxy-middleware'; import { Logger } from 'winston'; -import { KubernetesAuthTranslator } from '../kubernetes-auth-translator'; +import { AuthenticationStrategy } from '../auth'; import { ClusterDetails, KubernetesClustersSupplier } from '../types/types'; export const APPLICATION_JSON: string = 'application/json'; @@ -68,7 +68,7 @@ export type KubernetesProxyCreateRequestHandlerOptions = { export type KubernetesProxyOptions = { logger: Logger; clusterSupplier: KubernetesClustersSupplier; - authTranslator: KubernetesAuthTranslator; + authStrategy: AuthenticationStrategy; }; /** @@ -80,12 +80,12 @@ export class KubernetesProxy { private readonly middlewareForClusterName = new Map(); private readonly logger: Logger; private readonly clusterSupplier: KubernetesClustersSupplier; - private readonly authTranslator: KubernetesAuthTranslator; + private readonly authStrategy: AuthenticationStrategy; constructor(options: KubernetesProxyOptions) { this.logger = options.logger; this.clusterSupplier = options.clusterSupplier; - this.authTranslator = options.authTranslator; + this.authStrategy = options.authStrategy; } public createRequestHandler( @@ -113,9 +113,7 @@ export class KubernetesProxy { req.headers.authorization = authHeader; } else { const serviceAccountToken = await this.getClusterForRequest(req) - .then(cd => - this.authTranslator.decorateClusterDetailsWithAuth(cd, {}), - ) + .then(cd => this.authStrategy.decorateClusterDetailsWithAuth(cd, {})) .then(cd => cd?.authMetadata?.serviceAccountToken); if (serviceAccountToken) { req.headers.authorization = `Bearer ${serviceAccountToken}`;