caFile configuration is used when the Middleware is created on KubernetesProxy

Signed-off-by: Andres Mauricio Gomez P <andmagom@outlook.com>
This commit is contained in:
Andres Mauricio Gomez P
2023-09-07 09:52:07 -05:00
parent f4e1ea3c99
commit 024b2b66a3
3 changed files with 86 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-kubernetes-backend': patch
---
cluster.caFile configuration is used when the Middleware is created on KubernetesProxy
@@ -44,6 +44,7 @@ import {
KubernetesProxy,
} from './KubernetesProxy';
import fetch from 'cross-fetch';
import mockFs from 'mock-fs';
import type { Request } from 'express';
@@ -664,6 +665,82 @@ describe('KubernetesProxy', () => {
expect(response.status).toEqual(200);
});
describe('when server uses TLS', () => {
let httpsRequest: jest.SpyInstance;
beforeAll(() => {
httpsRequest = jest.spyOn(
// this is pretty egregious reverse engineering of msw.
// If the SetupServerApi constructor was exported, we wouldn't need
// to be quite so hacky here
(worker as any).interceptor.interceptors[0].modules.get('https'),
'request',
);
});
beforeEach(() => {
httpsRequest.mockClear();
});
describe('should pass the exact response from Kubernetes using the CA file', () => {
afterEach(() => {
mockFs.restore();
});
it('should trust contents of specified caFile', async () => {
mockFs({
'/path/to/ca.crt': 'MOCKCA',
});
const apiResponse = {
kind: 'APIVersions',
versions: ['v1'],
serverAddressByClientCIDRs: [
{
clientCIDR: '0.0.0.0/0',
serverAddress: '192.168.0.1:3333',
},
],
};
clusterSupplier.getClusters.mockResolvedValue([
{
name: 'cluster1',
url: 'https://localhost:9999',
serviceAccountToken: '',
authProvider: 'serviceAccount',
caFile: '/path/to/ca.crt',
},
] as ClusterDetails[]);
authTranslator.decorateClusterDetailsWithAuth.mockResolvedValue({
name: 'cluster1',
url: 'https://localhost:9999',
serviceAccountToken: '',
authProvider: 'serviceAccount',
} as ClusterDetails);
worker.use(
rest.get('https://localhost:9999/api', (_: any, res: any, ctx: any) =>
res(ctx.status(299), ctx.json(apiResponse)),
),
);
const requestPromise = setupProxyPromise({
proxyPath: '/mountpath',
requestPath: '/api',
headers: { [HEADER_KUBERNETES_CLUSTER]: 'cluster1' },
});
const response = await requestPromise;
expect(response.status).toEqual(299);
expect(response.body).toStrictEqual(apiResponse);
expect(httpsRequest).toHaveBeenCalledTimes(1);
const [[{ ca }]] = httpsRequest.mock.calls;
expect(ca).toEqual('MOCKCA');
});
});
});
describe('WebSocket', () => {
const proxyPath = '/proxy';
const wsPath = '/ws';
@@ -158,7 +158,10 @@ export class KubernetesProxy {
protocol: url.protocol,
host: url.hostname,
port: url.port,
ca: bufferFromFileOrString('', cluster.caData)?.toString(),
ca: bufferFromFileOrString(
cluster.caFile,
cluster.caData,
)?.toString(),
};
},
onError: (error, req, res) => {