From ef4755a063e5e08af3ebd44c2a866ac804eabcd4 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 8 Oct 2024 15:34:27 +0200 Subject: [PATCH] [EDR Workflows] Deprecate public endpoint/suggestions api endpoint in favour of an internal one (#194832) New internal GET `/internal/api/endpoint/suggestions/{suggestion_type}` route. Current public GET `/api/endpoint/suggestions/{suggestion_type}` route is set to deprecated. UI uses now the internal GET `/internal/api/endpoint/suggestions/{suggestion_type}` api route --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../output/kibana.serverless.staging.yaml | 1 + oas_docs/output/kibana.serverless.yaml | 1 + oas_docs/output/kibana.staging.yaml | 1 + oas_docs/output/kibana.yaml | 1 + .../suggestions/get_suggestions.schema.yaml | 1 + .../common/endpoint/constants.ts | 3 ++ ...agement_api_2023_10_31.bundled.schema.yaml | 1 + ...agement_api_2023_10_31.bundled.schema.yaml | 1 + .../event_filters/service/api_client.test.ts | 44 +++++++++++++++++++ .../pages/event_filters/service/api_client.ts | 6 +-- .../exceptions_list_api_client.test.ts | 4 +- .../endpoint/routes/suggestions/index.test.ts | 9 ++-- .../endpoint/routes/suggestions/index.ts | 27 +++++++++++- 13 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.test.ts diff --git a/oas_docs/output/kibana.serverless.staging.yaml b/oas_docs/output/kibana.serverless.staging.yaml index 8bd9bd198e5e1d..66790ef3f9c178 100644 --- a/oas_docs/output/kibana.serverless.staging.yaml +++ b/oas_docs/output/kibana.serverless.staging.yaml @@ -8096,6 +8096,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index 8bd9bd198e5e1d..66790ef3f9c178 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -8096,6 +8096,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/oas_docs/output/kibana.staging.yaml b/oas_docs/output/kibana.staging.yaml index 1ceeae519da724..7dbb9571f02720 100644 --- a/oas_docs/output/kibana.staging.yaml +++ b/oas_docs/output/kibana.staging.yaml @@ -11468,6 +11468,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 1ceeae519da724..7dbb9571f02720 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -11468,6 +11468,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/x-pack/plugins/security_solution/common/api/endpoint/suggestions/get_suggestions.schema.yaml b/x-pack/plugins/security_solution/common/api/endpoint/suggestions/get_suggestions.schema.yaml index 573f9c0e3992f3..08006d91045ff4 100644 --- a/x-pack/plugins/security_solution/common/api/endpoint/suggestions/get_suggestions.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/endpoint/suggestions/get_suggestions.schema.yaml @@ -5,6 +5,7 @@ info: paths: /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true summary: Get suggestions operationId: GetEndpointSuggestions x-codegen-enabled: true diff --git a/x-pack/plugins/security_solution/common/endpoint/constants.ts b/x-pack/plugins/security_solution/common/endpoint/constants.ts index 276d2fa32da76e..0e7218f0d7d413 100644 --- a/x-pack/plugins/security_solution/common/endpoint/constants.ts +++ b/x-pack/plugins/security_solution/common/endpoint/constants.ts @@ -60,6 +60,7 @@ export const FILE_STORAGE_DATA_INDEX = getFileDataIndexName('endpoint'); // Location from where all Endpoint related APIs are mounted export const BASE_ENDPOINT_ROUTE = '/api/endpoint'; +export const BASE_INTERNAL_ENDPOINT_ROUTE = `/internal${BASE_ENDPOINT_ROUTE}`; // Endpoint API routes export const HOST_METADATA_LIST_ROUTE = `${BASE_ENDPOINT_ROUTE}/metadata`; @@ -72,7 +73,9 @@ export const AGENT_POLICY_SUMMARY_ROUTE = `${BASE_POLICY_ROUTE}/summaries`; export const PROTECTION_UPDATES_NOTE_ROUTE = `${BASE_ENDPOINT_ROUTE}/protection_updates_note/{package_policy_id}`; /** Suggestions routes */ +/** @deprecated public route, use {@link SUGGESTIONS_INTERNAL_ROUTE} internal route */ export const SUGGESTIONS_ROUTE = `${BASE_ENDPOINT_ROUTE}/suggestions/{suggestion_type}`; +export const SUGGESTIONS_INTERNAL_ROUTE = `${BASE_INTERNAL_ENDPOINT_ROUTE}/suggestions/{suggestion_type}`; /** * Action Response Routes diff --git a/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml index ae35a302cbb42b..5d03e10969e14d 100644 --- a/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml @@ -545,6 +545,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml b/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml index df98520fe783f3..f5c2d290af33c3 100644 --- a/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/plugins/security_solution/docs/openapi/serverless/security_solution_endpoint_management_api_2023_10_31.bundled.schema.yaml @@ -495,6 +495,7 @@ paths: - Security Endpoint Management API /api/endpoint/suggestions/{suggestion_type}: post: + deprecated: true operationId: GetEndpointSuggestions parameters: - in: path diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.test.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.test.ts new file mode 100644 index 00000000000000..9810bf6d290605 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { HttpSetup } from '@kbn/core-http-browser'; +import { EventFiltersApiClient } from './api_client'; +import { coreMock } from '@kbn/core/public/mocks'; +import { SUGGESTIONS_INTERNAL_ROUTE } from '../../../../../common/endpoint/constants'; +import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables'; + +describe('EventFiltersApiClient', () => { + let fakeHttpServices: jest.Mocked; + let eventFiltersApiClient: EventFiltersApiClient; + + beforeAll(() => { + fakeHttpServices = coreMock.createStart().http as jest.Mocked; + eventFiltersApiClient = new EventFiltersApiClient(fakeHttpServices); + }); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should call the SUGGESTIONS_INTERNAL_ROUTE with correct URL and body', async () => { + await eventFiltersApiClient.getSuggestions({ + field: 'host.name', + query: 'test', + }); + + expect(fakeHttpServices.post).toHaveBeenCalledWith( + resolvePathVariables(SUGGESTIONS_INTERNAL_ROUTE, { suggestion_type: 'eventFilters' }), + { + version: '1', + body: JSON.stringify({ + field: 'host.name', + query: 'test', + }), + } + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts index e7c5e53e34274c..48bfcb9d848d1f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/service/api_client.ts @@ -12,8 +12,8 @@ import type { UpdateExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; import { removeIdFromExceptionItemsEntries } from '@kbn/securitysolution-list-hooks'; +import { SUGGESTIONS_INTERNAL_ROUTE } from '../../../../../common/endpoint/constants'; import type { EndpointSuggestionsBody } from '../../../../../common/api/endpoint'; -import { SUGGESTIONS_ROUTE } from '../../../../../common/endpoint/constants'; import { resolvePathVariables } from '../../../../common/utils/resolve_path_variables'; import { ExceptionsListApiClient } from '../../../services/exceptions_list/exceptions_list_api_client'; import { EVENT_FILTER_LIST_DEFINITION } from '../constants'; @@ -55,9 +55,9 @@ export class EventFiltersApiClient extends ExceptionsListApiClient { */ async getSuggestions(body: EndpointSuggestionsBody): Promise { const result: string[] = await this.getHttp().post( - resolvePathVariables(SUGGESTIONS_ROUTE, { suggestion_type: 'eventFilters' }), + resolvePathVariables(SUGGESTIONS_INTERNAL_ROUTE, { suggestion_type: 'eventFilters' }), { - version: this.version, + version: '1', body: JSON.stringify(body), } ); diff --git a/x-pack/plugins/security_solution/public/management/services/exceptions_list/exceptions_list_api_client.test.ts b/x-pack/plugins/security_solution/public/management/services/exceptions_list/exceptions_list_api_client.test.ts index 213b8da54dcd00..0424ff8ce6db34 100644 --- a/x-pack/plugins/security_solution/public/management/services/exceptions_list/exceptions_list_api_client.test.ts +++ b/x-pack/plugins/security_solution/public/management/services/exceptions_list/exceptions_list_api_client.test.ts @@ -59,9 +59,9 @@ describe('Exceptions List Api Client', () => { ); }); - describe('Wen getting an instance', () => { + describe('When getting an instance', () => { /** - * ATENTION: Skipping or modifying this test may cause the other test fails because it's creating the initial Singleton instance. + * ATTENTION: Skipping or modifying this test may cause the other test fails because it's creating the initial Singleton instance. * If you want to run tests individually, add this one to the execution with the .only method */ it('New instance is created the first time and the create list method is called', () => { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.test.ts index d8df4fc7131e06..e122367303340d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.test.ts @@ -39,7 +39,10 @@ import { } from '.'; import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; import { getEndpointAuthzInitialStateMock } from '../../../../common/endpoint/service/authz/mocks'; -import { eventsIndexPattern, SUGGESTIONS_ROUTE } from '../../../../common/endpoint/constants'; +import { + eventsIndexPattern, + SUGGESTIONS_INTERNAL_ROUTE, +} from '../../../../common/endpoint/constants'; import { EndpointAppContextService } from '../../endpoint_app_context_services'; jest.mock('@kbn/unified-search-plugin/server/autocomplete/terms_enum', () => { @@ -184,7 +187,7 @@ describe('when calling the Suggestions route handler', () => { routerMock, 'post', routePrefix, - '2023-10-31' + '1' ); await routeHandler(ctx as unknown as RequestHandlerContext, mockRequest, mockResponse); @@ -192,7 +195,7 @@ describe('when calling the Suggestions route handler', () => { }); it('should respond with forbidden', async () => { - await callRoute(SUGGESTIONS_ROUTE, { + await callRoute(SUGGESTIONS_INTERNAL_ROUTE, { params: { suggestion_type: 'eventFilters' }, authz: { canReadEventFilters: true, canWriteEventFilters: false }, }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.ts b/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.ts index 6e84e101d25062..a4853d9772ad7b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/suggestions/index.ts @@ -21,7 +21,11 @@ import type { SecuritySolutionRequestHandlerContext, } from '../../../types'; import type { EndpointAppContext } from '../../types'; -import { eventsIndexPattern, SUGGESTIONS_ROUTE } from '../../../../common/endpoint/constants'; +import { + eventsIndexPattern, + SUGGESTIONS_INTERNAL_ROUTE, + SUGGESTIONS_ROUTE, +} from '../../../../common/endpoint/constants'; import { withEndpointAuthz } from '../with_endpoint_authz'; import { errorHandler } from '../error_handler'; @@ -39,6 +43,7 @@ export function registerEndpointSuggestionsRoutes( access: 'public', path: SUGGESTIONS_ROUTE, options: { authRequired: true, tags: ['access:securitySolution'] }, + deprecated: true, }) .addVersion( { @@ -53,6 +58,26 @@ export function registerEndpointSuggestionsRoutes( getEndpointSuggestionsRequestHandler(config$, getLogger(endpointContext)) ) ); + + router.versioned + .post({ + access: 'internal', + path: SUGGESTIONS_INTERNAL_ROUTE, + options: { authRequired: true, tags: ['access:securitySolution'] }, + }) + .addVersion( + { + version: '1', + validate: { + request: EndpointSuggestionsSchema, + }, + }, + withEndpointAuthz( + { any: ['canWriteEventFilters'] }, + endpointContext.logFactory.get('endpointSuggestions'), + getEndpointSuggestionsRequestHandler(config$, getLogger(endpointContext)) + ) + ); } export const getEndpointSuggestionsRequestHandler = (