diff --git a/src/config.ts b/src/config.ts index 482a12a85c..2545fe9a67 100644 --- a/src/config.ts +++ b/src/config.ts @@ -65,6 +65,15 @@ export class KubeConfig implements SecurityAuthentication { new OpenIDConnectAuth(), ]; + // List of custom authenticators that can be added by the user + private custom_authenticators: Authenticator[] = []; + + // Optionally add additional external authenticators, you must do this + // before you load a kubeconfig file that references them. + public addAuthenticator(authenticator: Authenticator): void { + this.custom_authenticators.push(authenticator); + } + /** * The list of all known clusters */ @@ -577,10 +586,16 @@ export class KubeConfig implements SecurityAuthentication { if (!user) { return; } - const authenticator = KubeConfig.authenticators.find((elt: Authenticator) => { + let authenticator = KubeConfig.authenticators.find((elt: Authenticator) => { return elt.isAuthProvider(user); }); + if (!authenticator) { + authenticator = this.custom_authenticators.find((elt: Authenticator) => { + return elt.isAuthProvider(user); + }); + } + if (!opts.headers) { opts.headers = {}; } diff --git a/src/config_test.ts b/src/config_test.ts index 5e082ee8bb..9992937aeb 100644 --- a/src/config_test.ts +++ b/src/config_test.ts @@ -9,6 +9,7 @@ import { mock } from 'node:test'; import mockfs from 'mock-fs'; +import { Authenticator } from './auth.js'; import { Headers } from 'node-fetch'; import { HttpMethod } from './index.js'; import { assertRequestAgentsEqual, assertRequestOptionsEqual } from './test/match-buffer.js'; @@ -1703,5 +1704,45 @@ describe('KubeConfig', () => { } validateFileLoad(kc); }); + + it('should inject a custom Authenticator', async () => { + class CustomAuthenticator implements Authenticator { + public isAuthProvider(user: User): boolean { + return user.authProvider === 'custom'; + } + + public async applyAuthentication(user: User, opts: RequestOptions): Promise { + if (user.authProvider === 'custom') { + // Simulate token retrieval + const token = 'test-token'; + opts.headers = opts.headers || {}; + opts.headers.Authorization = `Bearer ${token}`; + } else { + throw new Error('No custom configuration found'); + } + } + } + + const customAuthenticator = new CustomAuthenticator(); + const kc = new KubeConfig(); + kc.addAuthenticator(customAuthenticator); + + const cluster: Cluster = { + name: 'test-cluster', + server: 'https://localhost:6443', + skipTLSVerify: false, + }; + const user: User = { + name: 'test-user', + authProvider: 'custom', + }; + + kc.loadFromClusterAndUser(cluster, user); + + const opts: RequestOptions = {}; + await kc.applyToHTTPSOptions(opts); + + strictEqual(opts.headers!.Authorization, 'Bearer test-token'); + }); }); });