Skip to content
Merged
2 changes: 2 additions & 0 deletions x-pack/plugins/data_enhanced/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ import { DataEnhancedPlugin, DataEnhancedSetup, DataEnhancedStart } from './plug
export const plugin = () => new DataEnhancedPlugin();

export { DataEnhancedSetup, DataEnhancedStart };

export { ENHANCED_ES_SEARCH_STRATEGY, EQL_SEARCH_STRATEGY } from '../common';
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@ describe('EQL search strategy', () => {
})
);
});

it('passes transport options for an existing request', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, { id: 'my-search-id', options: { ignore: [400] } });
const [[, requestOptions]] = mockEqlGet.mock.calls;

expect(mockEqlSearch).not.toHaveBeenCalled();
expect(requestOptions).toEqual(expect.objectContaining({ ignore: [400] }));
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ export const eqlSearchStrategyProvider = (
const eqlClient = context.core.elasticsearch.client.asCurrentUser.eql;
const uiSettingsClient = await context.core.uiSettings.client;
const asyncOptions = getAsyncOptions();
const searchOptions = toSnakeCase({ ...request.options });

if (request.id) {
promise = eqlClient.get({
id: request.id,
...toSnakeCase(asyncOptions),
});
promise = eqlClient.get(
{
id: request.id,
...toSnakeCase(asyncOptions),
},
searchOptions
);
} else {
const { ignoreThrottled, ignoreUnavailable } = await getDefaultSearchParams(
uiSettingsClient
Expand All @@ -48,11 +52,10 @@ export const eqlSearchStrategyProvider = (
...asyncOptions,
...request.params,
});
const searchOptions = toSnakeCase({ ...request.options });

promise = eqlClient.search(
searchParams as EqlSearchStrategyRequest['params'],
searchOptions as EqlSearchStrategyRequest['options']
searchOptions
);
}

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ export const DETECTION_ENGINE_PREPACKAGED_URL = `${DETECTION_ENGINE_RULES_URL}/p
export const DETECTION_ENGINE_PRIVILEGES_URL = `${DETECTION_ENGINE_URL}/privileges`;
export const DETECTION_ENGINE_INDEX_URL = `${DETECTION_ENGINE_URL}/index`;
export const DETECTION_ENGINE_TAGS_URL = `${DETECTION_ENGINE_URL}/tags`;
export const DETECTION_ENGINE_EQL_VALIDATION_URL = `${DETECTION_ENGINE_URL}/validate_eql`;
export const DETECTION_ENGINE_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/_find_statuses`;
export const DETECTION_ENGINE_PREPACKAGED_RULES_STATUS_URL = `${DETECTION_ENGINE_RULES_URL}/prepackaged/_status`;

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as t from 'io-ts';

export const eqlValidationSchema = t.exact(
t.type({
valid: t.boolean,
errors: t.array(t.string),
})
);

export type EqlValidationSchema = t.TypeOf<typeof eqlValidationSchema>;
export * from './validation';
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import get from 'lodash/get';
import has from 'lodash/has';
import { get, has } from 'lodash';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For posterity, we're going back to named imports from defaults:

#74539 -> #78156


const PARSING_ERROR_TYPE = 'parsing_exception';
const VERIFICATION_ERROR_TYPE = 'verification_exception';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EqlValidationSchema } from './eql_validation_schema';

export const getEqlValidationSchemaMock = (): EqlValidationSchema => ({
index: ['index-123'],
query: 'process where process.name == "regsvr32.exe"',
});
export * from './helpers';
56 changes: 39 additions & 17 deletions x-pack/plugins/security_solution/public/common/hooks/eql/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,50 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { HttpStart } from '../../../../../../../src/core/public';
import { DETECTION_ENGINE_EQL_VALIDATION_URL } from '../../../../common/constants';
import { EqlValidationSchema as EqlValidationRequest } from '../../../../common/detection_engine/schemas/request/eql_validation_schema';
import { EqlValidationSchema as EqlValidationResponse } from '../../../../common/detection_engine/schemas/response/eql_validation_schema';
import { DataPublicPluginStart } from '../../../../../../../src/plugins/data/public';
import {
EqlSearchStrategyRequest,
EqlSearchStrategyResponse,
} from '../../../../../data_enhanced/common';
import { EQL_SEARCH_STRATEGY } from '../../../../../data_enhanced/public';
import {
getValidationErrors,
isErrorResponse,
isValidationErrorResponse,
} from '../../../../common/search_strategy/eql';

interface ApiParams {
http: HttpStart;
interface Params {
index: string[];
query: string;
data: DataPublicPluginStart;
signal: AbortSignal;
}

export const validateEql = async ({
http,
query,
data,
index,
query,
signal,
}: ApiParams & EqlValidationRequest) => {
return http.fetch<EqlValidationResponse>(DETECTION_ENGINE_EQL_VALIDATION_URL, {
method: 'POST',
body: JSON.stringify({
query,
index,
}),
signal,
});
}: Params): Promise<{ valid: boolean; errors: string[] }> => {
const { rawResponse: response } = await data.search
.search<EqlSearchStrategyRequest, EqlSearchStrategyResponse>(
{
// @ts-expect-error allow_no_indices is missing on EqlSearch
params: { allow_no_indices: true, index: index.join(), body: { query, size: 0 } },
options: { ignore: [400] },
},
{
strategy: EQL_SEARCH_STRATEGY,
abortSignal: signal,
}
)
.toPromise();

if (isValidationErrorResponse(response.body)) {
return { valid: false, errors: getValidationErrors(response.body) };
} else if (isErrorResponse(response.body)) {
throw new Error(JSON.stringify(response.body));
} else {
return { valid: true, errors: [] };
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
*/

import { CoreStart } from '../../../../../../../src/core/public';
import { StartPlugins } from '../../../types';

type GlobalServices = Pick<CoreStart, 'http' | 'uiSettings'>;
type GlobalServices = Pick<CoreStart, 'http' | 'uiSettings'> & Pick<StartPlugins, 'data'>;

export class KibanaServices {
private static kibanaVersion?: string;
private static services?: GlobalServices;

public static init({
http,
data,
kibanaVersion,
uiSettings,
}: GlobalServices & { kibanaVersion: string }) {
this.services = { http, uiSettings };
this.services = { data, http, uiSettings };
this.kibanaVersion = kibanaVersion;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ export const eqlValidator = async (
}

try {
const { http } = KibanaServices.get();
const { data } = KibanaServices.get();
const signal = new AbortController().signal;
const response = await validateEql({ query, http, signal, index });
const response = await validateEql({ data, query, signal, index });

if (response?.valid === false) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
INTERNAL_RULE_ID_KEY,
INTERNAL_IMMUTABLE_KEY,
DETECTION_ENGINE_PREPACKAGED_URL,
DETECTION_ENGINE_EQL_VALIDATION_URL,
} from '../../../../../common/constants';
import { EqlSearchResponse, ShardsResponse } from '../../../types';
import {
Expand All @@ -29,7 +28,6 @@ import { QuerySignalsSchemaDecoded } from '../../../../../common/detection_engin
import { SetSignalsStatusSchemaDecoded } from '../../../../../common/detection_engine/schemas/request/set_signal_status_schema';
import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/create_rules_schema.mock';
import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock';
import { getEqlValidationSchemaMock } from '../../../../../common/detection_engine/schemas/request/eql_validation_schema.mock';

export const typicalSetStatusSignalByIdsPayload = (): SetSignalsStatusSchemaDecoded => ({
signal_ids: ['somefakeid1', 'somefakeid2'],
Expand Down Expand Up @@ -147,13 +145,6 @@ export const getPrepackagedRulesStatusRequest = () =>
path: `${DETECTION_ENGINE_PREPACKAGED_URL}/_status`,
});

export const eqlValidationRequest = () =>
requestMock.create({
method: 'post',
path: DETECTION_ENGINE_EQL_VALIDATION_URL,
body: getEqlValidationSchemaMock(),
});

export interface FindHit<T = RuleAlertType> {
page: number;
perPage: number;
Expand Down
Loading