Skip to content

Commit 7b4f7ad

Browse files
Merge branch '7.x' into backport/7.x/pr-85871
2 parents 729d31f + 4b57ac5 commit 7b4f7ad

21 files changed

Lines changed: 273 additions & 104 deletions

x-pack/plugins/security_solution/common/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export const ENDPOINT_METADATA_INDEX = 'metrics-endpoint.metadata-*';
4242
export const DEFAULT_RULE_REFRESH_INTERVAL_ON = true;
4343
export const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000; // ms
4444
export const DEFAULT_RULE_REFRESH_IDLE_VALUE = 2700000; // ms
45+
export const DEFAULT_RULE_NOTIFICATION_QUERY_SIZE = 100;
4546

4647
export enum SecurityPageName {
4748
detections = 'detections',

x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ export const getActionMessageParams = memoizeOne(
382382
description: 'context.results_link',
383383
useWithTripleBracesInTemplates: true,
384384
},
385+
{ name: 'alerts', description: 'context.alerts' },
385386
...actionMessageRuleParams.map((param) => {
386387
const extendedParam = `rule.${param}`;
387388
return { name: extendedParam, description: `context.${extendedParam}` };

x-pack/plugins/security_solution/server/lib/detection_engine/notifications/build_signals_query.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,19 @@ interface BuildSignalsSearchQuery {
99
index: string;
1010
from: string;
1111
to: string;
12+
size?: number;
1213
}
1314

14-
export const buildSignalsSearchQuery = ({ ruleId, index, from, to }: BuildSignalsSearchQuery) => ({
15+
export const buildSignalsSearchQuery = ({
16+
ruleId,
17+
index,
18+
from,
19+
to,
20+
size,
21+
}: BuildSignalsSearchQuery) => ({
1522
index,
1623
body: {
24+
size,
1725
query: {
1826
bool: {
1927
filter: [
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { AlertServices } from '../../../../../alerts/server';
8+
import { SignalSearchResponse } from '../signals/types';
9+
import { buildSignalsSearchQuery } from './build_signals_query';
10+
11+
interface GetSignalsParams {
12+
from?: string;
13+
to?: string;
14+
size?: number;
15+
ruleId: string;
16+
index: string;
17+
callCluster: AlertServices['callCluster'];
18+
}
19+
20+
export const getSignals = async ({
21+
from,
22+
to,
23+
size,
24+
ruleId,
25+
index,
26+
callCluster,
27+
}: GetSignalsParams): Promise<SignalSearchResponse> => {
28+
if (from == null || to == null) {
29+
throw Error('"from" or "to" was not provided to signals query');
30+
}
31+
32+
const query = buildSignalsSearchQuery({
33+
index,
34+
ruleId,
35+
to,
36+
from,
37+
size,
38+
});
39+
40+
const result: SignalSearchResponse = await callCluster('search', query);
41+
42+
return result;
43+
};

x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.test.ts

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import { rulesNotificationAlertType } from './rules_notification_alert_type';
1010
import { buildSignalsSearchQuery } from './build_signals_query';
1111
import { alertsMock, AlertServicesMock } from '../../../../../alerts/server/mocks';
1212
import { NotificationExecutorOptions } from './types';
13+
import {
14+
sampleDocSearchResultsNoSortIdNoVersion,
15+
sampleDocSearchResultsWithSortId,
16+
sampleEmptyDocSearchResults,
17+
} from '../signals/__mocks__/es_results';
18+
import { DEFAULT_RULE_NOTIFICATION_QUERY_SIZE } from '../../../../common/constants';
1319
jest.mock('./build_signals_query');
1420

1521
describe('rules_notification_alert_type', () => {
@@ -63,9 +69,7 @@ describe('rules_notification_alert_type', () => {
6369
references: [],
6470
attributes: ruleAlert,
6571
});
66-
alertServices.callCluster.mockResolvedValue({
67-
count: 0,
68-
});
72+
alertServices.callCluster.mockResolvedValue(sampleDocSearchResultsWithSortId());
6973

7074
await alert.executor(payload);
7175

@@ -75,6 +79,7 @@ describe('rules_notification_alert_type', () => {
7579
index: '.siem-signals',
7680
ruleId: 'rule-1',
7781
to: '1576341633400',
82+
size: DEFAULT_RULE_NOTIFICATION_QUERY_SIZE,
7883
})
7984
);
8085
});
@@ -88,9 +93,7 @@ describe('rules_notification_alert_type', () => {
8893
references: [],
8994
attributes: ruleAlert,
9095
});
91-
alertServices.callCluster.mockResolvedValue({
92-
count: 10,
93-
});
96+
alertServices.callCluster.mockResolvedValue(sampleDocSearchResultsWithSortId());
9497

9598
await alert.executor(payload);
9699
expect(alertServices.alertInstanceFactory).toHaveBeenCalled();
@@ -114,9 +117,7 @@ describe('rules_notification_alert_type', () => {
114117
references: [],
115118
attributes: ruleAlert,
116119
});
117-
alertServices.callCluster.mockResolvedValue({
118-
count: 10,
119-
});
120+
alertServices.callCluster.mockResolvedValue(sampleDocSearchResultsWithSortId());
120121
await alert.executor(payload);
121122
expect(alertServices.alertInstanceFactory).toHaveBeenCalled();
122123

@@ -141,9 +142,7 @@ describe('rules_notification_alert_type', () => {
141142
references: [],
142143
attributes: ruleAlert,
143144
});
144-
alertServices.callCluster.mockResolvedValue({
145-
count: 10,
146-
});
145+
alertServices.callCluster.mockResolvedValue(sampleDocSearchResultsWithSortId());
147146
await alert.executor(payload);
148147
expect(alertServices.alertInstanceFactory).toHaveBeenCalled();
149148

@@ -165,9 +164,7 @@ describe('rules_notification_alert_type', () => {
165164
references: [],
166165
attributes: ruleAlert,
167166
});
168-
alertServices.callCluster.mockResolvedValue({
169-
count: 0,
170-
});
167+
alertServices.callCluster.mockResolvedValue(sampleEmptyDocSearchResults());
171168

172169
await alert.executor(payload);
173170

@@ -182,17 +179,15 @@ describe('rules_notification_alert_type', () => {
182179
references: [],
183180
attributes: ruleAlert,
184181
});
185-
alertServices.callCluster.mockResolvedValue({
186-
count: 10,
187-
});
182+
alertServices.callCluster.mockResolvedValue(sampleDocSearchResultsNoSortIdNoVersion());
188183

189184
await alert.executor(payload);
190185

191186
expect(alertServices.alertInstanceFactory).toHaveBeenCalled();
192187

193188
const [{ value: alertInstanceMock }] = alertServices.alertInstanceFactory.mock.results;
194189
expect(alertInstanceMock.replaceState).toHaveBeenCalledWith(
195-
expect.objectContaining({ signals_count: 10 })
190+
expect.objectContaining({ signals_count: 100 })
196191
);
197192
expect(alertInstanceMock.scheduleActions).toHaveBeenCalledWith(
198193
'default',

x-pack/plugins/security_solution/server/lib/detection_engine/notifications/rules_notification_alert_type.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@
66

77
import { Logger } from 'src/core/server';
88
import { schema } from '@kbn/config-schema';
9-
import { NOTIFICATIONS_ID, SERVER_APP_ID } from '../../../../common/constants';
9+
import {
10+
DEFAULT_RULE_NOTIFICATION_QUERY_SIZE,
11+
NOTIFICATIONS_ID,
12+
SERVER_APP_ID,
13+
} from '../../../../common/constants';
1014

1115
import { NotificationAlertTypeDefinition } from './types';
12-
import { getSignalsCount } from './get_signals_count';
1316
import { RuleAlertAttributes } from '../signals/types';
1417
import { siemRuleActionGroups } from '../signals/siem_rule_action_groups';
1518
import { scheduleNotificationActions } from './schedule_notification_actions';
1619
import { getNotificationResultsLink } from './utils';
1720
import { parseScheduleDates } from '../../../../common/detection_engine/parse_schedule_dates';
21+
import { getSignals } from './get_signals';
1822

1923
export const rulesNotificationAlertType = ({
2024
logger,
@@ -52,14 +56,20 @@ export const rulesNotificationAlertType = ({
5256
)?.format('x');
5357
const toInMs = parseScheduleDates(startedAt.toISOString())?.format('x');
5458

55-
const signalsCount = await getSignalsCount({
59+
const results = await getSignals({
5660
from: fromInMs,
5761
to: toInMs,
62+
size: DEFAULT_RULE_NOTIFICATION_QUERY_SIZE,
5863
index: ruleParams.outputIndex,
5964
ruleId: ruleParams.ruleId,
6065
callCluster: services.callCluster,
6166
});
6267

68+
const signals = results.hits.hits.map((hit) => hit._source);
69+
70+
const signalsCount =
71+
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total.value;
72+
6373
const resultsLink = getNotificationResultsLink({
6474
from: fromInMs,
6575
to: toInMs,
@@ -74,7 +84,13 @@ export const rulesNotificationAlertType = ({
7484

7585
if (signalsCount !== 0) {
7686
const alertInstance = services.alertInstanceFactory(alertId);
77-
scheduleNotificationActions({ alertInstance, signalsCount, resultsLink, ruleParams });
87+
scheduleNotificationActions({
88+
alertInstance,
89+
signalsCount,
90+
resultsLink,
91+
ruleParams,
92+
signals,
93+
});
7894
}
7995
},
8096
});

x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { mapKeys, snakeCase } from 'lodash/fp';
88
import { AlertInstance } from '../../../../../alerts/server';
9+
import { SignalSource } from '../signals/types';
910
import { RuleTypeParams } from '../types';
1011

1112
export type NotificationRuleTypeParams = RuleTypeParams & {
@@ -18,13 +19,15 @@ interface ScheduleNotificationActions {
1819
signalsCount: number;
1920
resultsLink: string;
2021
ruleParams: NotificationRuleTypeParams;
22+
signals: SignalSource[];
2123
}
2224

2325
export const scheduleNotificationActions = ({
2426
alertInstance,
2527
signalsCount,
2628
resultsLink = '',
2729
ruleParams,
30+
signals,
2831
}: ScheduleNotificationActions): AlertInstance =>
2932
alertInstance
3033
.replaceState({
@@ -33,4 +36,5 @@ export const scheduleNotificationActions = ({
3336
.scheduleActions('default', {
3437
results_link: resultsLink,
3538
rule: mapKeys(snakeCase, ruleParams),
39+
alerts: signals,
3640
});

x-pack/plugins/security_solution/server/lib/detection_engine/signals/__mocks__/es_results.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
BulkItem,
1313
RuleAlertAttributes,
1414
SignalHit,
15+
WrappedSignalHit,
1516
} from '../types';
1617
import {
1718
Logger,
@@ -240,6 +241,14 @@ export const sampleEmptyDocSearchResults = (): SignalSearchResponse => ({
240241
},
241242
});
242243

244+
export const sampleWrappedSignalHit = (): WrappedSignalHit => {
245+
return {
246+
_index: 'myFakeSignalIndex',
247+
_id: sampleIdGuid,
248+
_source: sampleSignalHit(),
249+
};
250+
};
251+
243252
export const sampleDocWithAncestors = (): SignalSearchResponse => {
244253
const sampleDoc = sampleDocNoSortId();
245254
delete sampleDoc.sort;

0 commit comments

Comments
 (0)