diff --git a/.changeset/polite-shrimps-confess.md b/.changeset/polite-shrimps-confess.md new file mode 100644 index 0000000000..05981c9461 --- /dev/null +++ b/.changeset/polite-shrimps-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Proxy endpoint supports cluster URLs with subpath diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts index 038a3d4bad..1bd79e9401 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.test.ts @@ -638,4 +638,46 @@ describe('KubernetesProxy', () => { expect(response.status).toEqual(500); }); + + it('should get res through proxy with cluster url has sub path', async () => { + worker.use( + rest.get( + 'http://localhost:9999/subpath/api/v1/namespaces', + (_req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + kind: 'NamespaceList', + apiVersion: 'v1', + items: [], + }), + ); + }, + ), + ); + permissionApi.authorize.mockResolvedValue([ + { result: AuthorizeResult.ALLOW }, + ]); + clusterSupplier.getClusters.mockResolvedValue([ + { + name: 'cluster1', + url: 'http://localhost:9999/subpath', + authProvider: '', + }, + ]); + authTranslator.decorateClusterDetailsWithAuth.mockImplementation( + async x => x, + ); + const app = express().use( + Router().use('/mountpath', proxy.createRequestHandler({ permissionApi })), + ); + + const requestPromise = request(app) + .get('/mountpath/api/v1/namespaces') + .set(HEADER_KUBERNETES_CLUSTER, 'cluster1'); + worker.use(rest.all(requestPromise.url, (req: any) => req.passthrough())); + const response = await requestPromise; + + expect(response.status).toEqual(200); + }); }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts index 36617bbbad..21c381b73e 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesProxy.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesProxy.ts @@ -138,7 +138,15 @@ export class KubernetesProxy { ws: true, secure: !originalCluster.skipTLSVerify, changeOrigin: true, - pathRewrite: { [`^${originalReq.baseUrl}`]: '' }, + pathRewrite: async (path, req) => { + // Re-evaluate the cluster on each request, in case it has changed + const cluster = await this.getClusterForRequest(req); + const url = new URL(cluster.url); + return path.replace( + new RegExp(`^${originalReq.baseUrl}`), + url.pathname || '', + ); + }, router: async req => { // Re-evaluate the cluster on each request, in case it has changed const cluster = await this.getClusterForRequest(req);