diff --git a/x-pack/plugins/security_solution/common/api/search_strategy/endpoint_fields/endpoint_fields.ts b/x-pack/plugins/security_solution/common/api/search_strategy/endpoint_fields/endpoint_fields.ts new file mode 100644 index 0000000000000..d4e9ce80710ca --- /dev/null +++ b/x-pack/plugins/security_solution/common/api/search_strategy/endpoint_fields/endpoint_fields.ts @@ -0,0 +1,15 @@ +/* + * 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 { z } from 'zod'; + +export const endpointFieldsRequestSchema = z.object({ + indices: z.array(z.string()), + onlyCheckIfIndicesExist: z.boolean(), +}); + +export type EndpointFieldsRequestSchema = z.infer; diff --git a/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.test.ts index 785d833e1fafc..72225c2fe77d2 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.test.ts @@ -16,6 +16,7 @@ import { createMockEndpointAppContextService } from '../../endpoint/mocks'; import { getEndpointAuthzInitialStateMock } from '../../../common/endpoint/service/authz/mocks'; import { eventsIndexPattern, METADATA_UNITED_INDEX } from '../../../common/endpoint/constants'; import { EndpointAuthorizationError } from '../../endpoint/errors'; +import type { IndexFieldsStrategyRequestByIndices } from '@kbn/timelines-plugin/common/search_strategy'; describe('Endpoint fields', () => { const getFieldsForWildcardMock = jest.fn(); @@ -161,6 +162,20 @@ describe('Endpoint fields', () => { expect(response.indicesExist).toEqual(indices); }); + it('should throw when request body is invalid', async () => { + const request = {}; + + await expect(async () => { + await requestEndpointFieldsSearch( + endpointAppContextService, + request as unknown as IndexFieldsStrategyRequestByIndices, + deps, + beatFields, + IndexPatterns + ); + }).rejects.toThrowError(/invalid_type/); + }); + it('should throw when invalid index', async () => { const indices = ['invalid']; const request = { diff --git a/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts index ce7270912b077..cdea82d680698 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/index.ts @@ -22,6 +22,7 @@ import type { } from '../../../common/search_strategy'; import type { EndpointAppContextService } from '../../endpoint/endpoint_app_context_services'; import { EndpointAuthorizationError } from '../../endpoint/errors'; +import { parseRequest } from './parse_request'; /** * EndpointFieldProvider mimics indexField provider from timeline plugin: x-pack/plugins/timelines/server/search_strategy/index_fields/index.ts @@ -51,9 +52,12 @@ export const requestEndpointFieldsSearch = async ( beatFields: BeatFields, indexPatterns: DataViewsServerPluginStart ): Promise => { + const parsedRequest = parseRequest(request); + if ( - request.indices.length > 1 || - (request.indices[0] !== eventsIndexPattern && request.indices[0] !== METADATA_UNITED_INDEX) + parsedRequest.indices.length > 1 || + (parsedRequest.indices[0] !== eventsIndexPattern && + parsedRequest.indices[0] !== METADATA_UNITED_INDEX) ) { throw new Error(`Invalid indices request ${request.indices.join(', ')}`); } @@ -63,11 +67,11 @@ export const requestEndpointFieldsSearch = async ( ); if ( - (!canWriteEventFilters && request.indices[0] === eventsIndexPattern) || - (!canReadEndpointList && request.indices[0] === METADATA_UNITED_INDEX) + (!canWriteEventFilters && parsedRequest.indices[0] === eventsIndexPattern) || + (!canReadEndpointList && parsedRequest.indices[0] === METADATA_UNITED_INDEX) ) { throw new EndpointAuthorizationError(); } - return requestIndexFieldSearch(request, deps, beatFields, indexPatterns, true); + return requestIndexFieldSearch(parsedRequest, deps, beatFields, indexPatterns, true); }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/parse_request.ts b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/parse_request.ts new file mode 100644 index 0000000000000..754d342e16c18 --- /dev/null +++ b/x-pack/plugins/security_solution/server/search_strategy/endpoint_fields/parse_request.ts @@ -0,0 +1,10 @@ +/* + * 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 { endpointFieldsRequestSchema } from '../../../common/api/search_strategy/endpoint_fields/endpoint_fields'; + +export const parseRequest = (request: unknown) => endpointFieldsRequestSchema.parse(request);