[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>
This commit is contained in:
Konrad Szwarc 2024-10-08 15:34:27 +02:00 committed by GitHub
parent ca1d375348
commit ef4755a063
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 91 additions and 9 deletions

View file

@ -8096,6 +8096,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -8096,6 +8096,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -11468,6 +11468,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -11468,6 +11468,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -5,6 +5,7 @@ info:
paths:
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
summary: Get suggestions
operationId: GetEndpointSuggestions
x-codegen-enabled: true

View file

@ -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

View file

@ -545,6 +545,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -495,6 +495,7 @@ paths:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path

View file

@ -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<HttpSetup>;
let eventFiltersApiClient: EventFiltersApiClient;
beforeAll(() => {
fakeHttpServices = coreMock.createStart().http as jest.Mocked<HttpSetup>;
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',
}),
}
);
});
});

View file

@ -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<string[]> {
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),
}
);

View file

@ -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', () => {

View file

@ -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 },
});

View file

@ -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 = (