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