Reduce scope of branch
This commit is contained in:
parent
a25dde02a2
commit
8c3a1875c3
|
@ -1,6 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { SavedObject } from 'src/core/types';
|
|
||||||
import type { ConfigType } from '../../../../../config';
|
|
||||||
import { buildRuleWithoutOverrides } from '../../../signals/build_rule';
|
|
||||||
import { AlertAttributes, SignalSource } from '../../../signals/types';
|
|
||||||
import { generateId } from '../../../signals/utils';
|
|
||||||
import { RACAlert, WrappedRACAlert } from '../../types';
|
|
||||||
import { buildAlert } from './build_alert';
|
|
||||||
import { buildBulkBody } from './build_bulk_body';
|
|
||||||
import { EqlSequence } from '../../../../../../common/detection_engine/types';
|
|
||||||
import { generateBuildingBlockIds } from './generate_building_block_ids';
|
|
||||||
import { objectArrayIntersection } from '../../../signals/build_bulk_body';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes N raw documents from ES that form a sequence and builds them into N+1 signals ready to be indexed -
|
|
||||||
* one signal for each event in the sequence, and a "shell" signal that ties them all together. All N+1 signals
|
|
||||||
* share the same signal.group.id to make it easy to query them.
|
|
||||||
* @param sequence The raw ES documents that make up the sequence
|
|
||||||
* @param ruleSO SavedObject representing the rule that found the sequence
|
|
||||||
*/
|
|
||||||
export const buildAlertGroupFromSequence = (
|
|
||||||
sequence: EqlSequence<SignalSource>,
|
|
||||||
ruleSO: SavedObject<AlertAttributes>,
|
|
||||||
mergeStrategy: ConfigType['alertMergeStrategy']
|
|
||||||
): WrappedRACAlert[] => {
|
|
||||||
const ancestors = sequence.events.flatMap((event) => event._source.signal?.ancestors ?? []);
|
|
||||||
if (ancestors.some((ancestor) => ancestor.rule === ruleSO.id)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildingBlocks: RACAlert[] = sequence.events.map((event) => ({
|
|
||||||
...buildBulkBody(ruleSO, event, mergeStrategy, false),
|
|
||||||
'kibana.alert.rule.building_block_type': 'default',
|
|
||||||
}));
|
|
||||||
const buildingBlockIds = generateBuildingBlockIds(buildingBlocks);
|
|
||||||
const wrappedBuildingBlocks: WrappedRACAlert[] = buildingBlocks.map((block, i) => ({
|
|
||||||
_id: buildingBlockIds[i],
|
|
||||||
_index: '',
|
|
||||||
_source: {
|
|
||||||
...block,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Now that we have an array of building blocks for the events in the sequence,
|
|
||||||
// we can build the signal that links the building blocks together
|
|
||||||
// and also insert the group id (which is also the "shell" signal _id) in each building block
|
|
||||||
const doc = buildAlertFromSequence(wrappedBuildingBlocks, ruleSO);
|
|
||||||
const sequenceAlert = {
|
|
||||||
_id: generateId(
|
|
||||||
'', // TODO: get index?
|
|
||||||
doc['kibana.alert.id'] as string,
|
|
||||||
'', // TODO: version?
|
|
||||||
ruleSO.attributes.params.ruleId ?? doc['kibana.alert.rule.id'] ?? ''
|
|
||||||
),
|
|
||||||
_index: '',
|
|
||||||
_source: doc,
|
|
||||||
};
|
|
||||||
|
|
||||||
wrappedBuildingBlocks.forEach((block) => {
|
|
||||||
block._source['kibana.alert.group'] = {
|
|
||||||
id: sequenceAlert._id,
|
|
||||||
index: '',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return [...wrappedBuildingBlocks, sequenceAlert];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const buildAlertFromSequence = (
|
|
||||||
alerts: WrappedRACAlert[],
|
|
||||||
ruleSO: SavedObject<AlertAttributes>
|
|
||||||
): RACAlert => {
|
|
||||||
const rule = buildRuleWithoutOverrides(ruleSO);
|
|
||||||
const doc = buildAlert(alerts, rule);
|
|
||||||
const mergedAlerts = objectArrayIntersection(alerts.map((alert) => alert._source));
|
|
||||||
return {
|
|
||||||
...mergedAlerts,
|
|
||||||
event: {
|
|
||||||
kind: 'signal',
|
|
||||||
},
|
|
||||||
...doc,
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,6 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { createHash } from 'crypto';
|
|
||||||
import { Ancestor } from '../../../signals/types';
|
|
||||||
import { RACAlert } from '../../types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates unique doc ids for each building block signal within a sequence. The id of each building block
|
|
||||||
* depends on the parents of every building block, so that a signal which appears in multiple different sequences
|
|
||||||
* (e.g. if multiple rules build sequences that share a common event/signal) will get a unique id per sequence.
|
|
||||||
* @param buildingBlocks The full list of building blocks in the sequence.
|
|
||||||
*/
|
|
||||||
export const generateBuildingBlockIds = (buildingBlocks: RACAlert[]): string[] => {
|
|
||||||
const baseHashString = buildingBlocks.reduce(
|
|
||||||
(baseString, block) =>
|
|
||||||
baseString
|
|
||||||
.concat(
|
|
||||||
(block['kibana.alert.ancestors'] as Ancestor[]).reduce(
|
|
||||||
(acc, ancestor) => acc.concat(ancestor.id, ancestor.index),
|
|
||||||
''
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.concat(block['kibana.alert.rule.id'] as string),
|
|
||||||
''
|
|
||||||
);
|
|
||||||
return buildingBlocks.map((block, idx) =>
|
|
||||||
createHash('sha256').update(baseHashString).update(String(idx)).digest('hex')
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { SearchAfterAndBulkCreateParams, WrapSequences } from '../../signals/types';
|
|
||||||
import { buildAlertGroupFromSequence } from './utils/build_alert_group_from_sequence';
|
|
||||||
import { ConfigType } from '../../../../config';
|
|
||||||
import { WrappedRACAlert } from '../types';
|
|
||||||
|
|
||||||
export const wrapSequencesFactory = ({
|
|
||||||
ruleSO,
|
|
||||||
mergeStrategy,
|
|
||||||
}: {
|
|
||||||
ruleSO: SearchAfterAndBulkCreateParams['ruleSO'];
|
|
||||||
mergeStrategy: ConfigType['alertMergeStrategy'];
|
|
||||||
}): WrapSequences => (sequences) =>
|
|
||||||
sequences.reduce(
|
|
||||||
(acc: WrappedRACAlert[], sequence) => [
|
|
||||||
...acc,
|
|
||||||
...buildAlertGroupFromSequence(sequence, ruleSO, mergeStrategy),
|
|
||||||
],
|
|
||||||
[]
|
|
||||||
);
|
|
Loading…
Reference in a new issue