diff --git a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx index 9ac56b96171c1..c0f30b7b640fc 100644 --- a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx @@ -60,7 +60,11 @@ describe('When using the `ResponseActionFileDownloadLink` component', () => { expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); }); - expect(renderResult.getByTestId('test-downloadButton')).not.toBeNull(); + const downlaodButton = renderResult.getByTestId('test-downloadButton'); + + expect(downlaodButton.getAttribute('href')).toEqual( + '/api/endpoint/action/123/file/123.agent-a/download?apiVersion=2023-10-31' + ); expect(renderResult.getByTestId('test-passcodeMessage')).toHaveTextContent( FILE_PASSCODE_INFO_MESSAGE ); diff --git a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx index 7f86c96fcefae..2d679d4b3479e 100644 --- a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx +++ b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx @@ -134,10 +134,10 @@ export const ResponseActionFileDownloadLink = memo { - return resolvePathVariables(ACTION_AGENT_FILE_DOWNLOAD_ROUTE, { + return `${resolvePathVariables(ACTION_AGENT_FILE_DOWNLOAD_ROUTE, { action_id: action.id, file_id: getFileDownloadId(action, agentId), - }); + })}?apiVersion=2023-10-31`; }, [action, agentId]); const { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts index 1e771f9f7ed33..24245d81dde75 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts @@ -50,7 +50,11 @@ describe('Response Actions file download API', () => { it('should register the route', () => { expect( - apiTestSetup.getRegisteredRouteHandler('get', ACTION_AGENT_FILE_DOWNLOAD_ROUTE) + apiTestSetup.getRegisteredVersionedRoute( + 'get', + ACTION_AGENT_FILE_DOWNLOAD_ROUTE, + '2023-10-31' + ) ).toBeDefined(); }); @@ -59,11 +63,9 @@ describe('Response Actions file download API', () => { (await httpHandlerContextMock.securitySolution).getEndpointAuthz as jest.Mock ).mockResolvedValue(getEndpointAuthzInitialStateMock({ canWriteFileOperations: false })); - await apiTestSetup.getRegisteredRouteHandler('get', ACTION_AGENT_FILE_DOWNLOAD_ROUTE)( - httpHandlerContextMock, - httpRequestMock, - httpResponseMock - ); + await apiTestSetup + .getRegisteredVersionedRoute('get', ACTION_AGENT_FILE_DOWNLOAD_ROUTE, '2023-10-31') + .routeHandler(httpHandlerContextMock, httpRequestMock, httpResponseMock); expect(httpResponseMock.forbidden).toHaveBeenCalledWith({ body: expect.any(EndpointAuthorizationError), diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts index 5a0ee82942bd5..8b510e3d8d845 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts @@ -25,22 +25,29 @@ export const registerActionFileDownloadRoutes = ( ) => { const logger = endpointContext.logFactory.get('actionFileDownload'); - // NOTE: - // This API (as of today - 2023-06-21) can not be versioned because it is used - // to download files from the UI, where its used as part of a `` anchor, which - // has no way to define the version header. - router.get( - { + router.versioned + .get({ + access: 'public', + // NOTE: + // Because this API is used in the browser via `href` (ex. on link to download a file), + // we need to enable setting the version number via query params + enableQueryVersion: true, path: ACTION_AGENT_FILE_DOWNLOAD_ROUTE, - validate: EndpointActionFileDownloadSchema, options: { authRequired: true, tags: ['access:securitySolution'] }, - }, - withEndpointAuthz( - { all: ['canWriteFileOperations'] }, - logger, - getActionFileDownloadRouteHandler(endpointContext) - ) - ); + }) + .addVersion( + { + version: '2023-10-31', + validate: { + request: EndpointActionFileDownloadSchema, + }, + }, + withEndpointAuthz( + { all: ['canWriteFileOperations'] }, + logger, + getActionFileDownloadRouteHandler(endpointContext) + ) + ); }; export const getActionFileDownloadRouteHandler = (