From 36242b2348a62699bacd3eea39ce55ae84ab2edc Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 3 Nov 2021 18:56:02 -0400 Subject: [PATCH] [Security Solution][RAC][Cases] Fix RAC "add to case" functionality from alerts table (#116768) (#117426) * Fix add to case functionality * Use appropriate owner when attaching an alert to a case * Use field name constants * Gotta reskip the test * Better error handling * Fix type errors * Fix tests Co-authored-by: Madison Caldwell --- x-pack/plugins/cases/common/ui/types.ts | 9 +++ .../components/user_action_tree/index.tsx | 14 +++- .../field_maps/alerts.ts | 2 +- .../field_maps/field_names.ts | 2 + .../rule_types => common}/field_maps/index.ts | 0 .../rule_types => common}/field_maps/rules.ts | 0 .../detection_alerts/attach_to_case.spec.ts | 1 + .../components/alerts_table/actions.tsx | 80 +++++++++++++------ .../use_add_to_case_actions.tsx | 4 +- .../security_solution/public/helpers.tsx | 28 ++++++- .../rule_types/__mocks__/threshold.ts | 4 +- .../factories/utils/build_alert.test.ts | 8 +- .../rule_types/factories/utils/build_alert.ts | 8 +- .../build_alert_group_from_sequence.test.ts | 10 +-- .../utils/build_alert_group_from_sequence.ts | 4 +- .../utils/generate_building_block_ids.ts | 2 +- .../lib/detection_engine/rule_types/types.ts | 2 +- .../threshold/build_signal_history.test.ts | 2 +- .../signals/threshold/build_signal_history.ts | 4 +- .../security_solution/server/plugin.ts | 3 +- .../timelines/public/hooks/use_add_to_case.ts | 2 +- .../security_and_spaces/tests/create_ml.ts | 2 +- .../tests/create_threat_matching.ts | 4 +- .../tests/generating_signals.ts | 8 +- .../security_and_spaces/tests/timestamps.ts | 2 +- 25 files changed, 140 insertions(+), 65 deletions(-) rename x-pack/plugins/security_solution/{server/lib/detection_engine/rule_types => common}/field_maps/alerts.ts (98%) rename x-pack/plugins/security_solution/{server/lib/detection_engine/rule_types => common}/field_maps/field_names.ts (90%) rename x-pack/plugins/security_solution/{server/lib/detection_engine/rule_types => common}/field_maps/index.ts (100%) rename x-pack/plugins/security_solution/{server/lib/detection_engine/rule_types => common}/field_maps/rules.ts (100%) diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index b4ed4f7db177e..402e44618c7cc 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -255,10 +255,19 @@ export interface SignalEcs { threshold_result?: unknown; } +export type SignalEcsAAD = Exclude & { + rule?: Exclude & { uuid: string[] }; + building_block_type?: string[]; + workflow_status?: string[]; +}; + export interface Ecs { _id: string; _index?: string; signal?: SignalEcs; + kibana?: { + alert: SignalEcsAAD; + }; } export type CaseActionConnector = ActionConnector; diff --git a/x-pack/plugins/cases/public/components/user_action_tree/index.tsx b/x-pack/plugins/cases/public/components/user_action_tree/index.tsx index 92640a34548e8..24fc393715f76 100644 --- a/x-pack/plugins/cases/public/components/user_action_tree/index.tsx +++ b/x-pack/plugins/cases/public/components/user_action_tree/index.tsx @@ -12,8 +12,10 @@ import { EuiCommentList, EuiCommentProps, } from '@elastic/eui'; +import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; + import classNames from 'classnames'; -import { isEmpty } from 'lodash'; +import { get, isEmpty } from 'lodash'; import React, { useCallback, useMemo, useRef, useState, useEffect } from 'react'; import { useParams } from 'react-router-dom'; import styled from 'styled-components'; @@ -421,9 +423,15 @@ export const UserActionTree = React.memo( } const ruleId = - comment?.rule?.id ?? manualAlertsData[alertId]?.signal?.rule?.id?.[0] ?? null; + comment?.rule?.id ?? + manualAlertsData[alertId]?.signal?.rule?.id?.[0] ?? + get(manualAlertsData[alertId], ALERT_RULE_UUID)[0] ?? + null; const ruleName = - comment?.rule?.name ?? manualAlertsData[alertId]?.signal?.rule?.name?.[0] ?? null; + comment?.rule?.name ?? + manualAlertsData[alertId]?.signal?.rule?.name?.[0] ?? + get(manualAlertsData[alertId], ALERT_RULE_NAME)[0] ?? + null; return [ ...comments, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts b/x-pack/plugins/security_solution/common/field_maps/alerts.ts similarity index 98% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts rename to x-pack/plugins/security_solution/common/field_maps/alerts.ts index 5a7ceb83baf8c..08ce8f098f6fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts +++ b/x-pack/plugins/security_solution/common/field_maps/alerts.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FieldMap } from '../../../../../../rule_registry/common/field_map'; +import { FieldMap } from '../../../rule_registry/common/field_map'; export const alertsFieldMap: FieldMap = { 'kibana.alert.ancestors': { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names.ts b/x-pack/plugins/security_solution/common/field_maps/field_names.ts similarity index 90% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names.ts rename to x-pack/plugins/security_solution/common/field_maps/field_names.ts index 62c20217d23f0..1cb40063202d0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names.ts +++ b/x-pack/plugins/security_solution/common/field_maps/field_names.ts @@ -13,6 +13,7 @@ export const ALERT_DEPTH = `${ALERT_NAMESPACE}.depth` as const; export const ALERT_GROUP_ID = `${ALERT_NAMESPACE}.group.id` as const; export const ALERT_GROUP_INDEX = `${ALERT_NAMESPACE}.group.index` as const; export const ALERT_ORIGINAL_TIME = `${ALERT_NAMESPACE}.original_time` as const; +export const ALERT_THRESHOLD_RESULT = `${ALERT_NAMESPACE}.threshold_result` as const; export const ALERT_ORIGINAL_EVENT = `${ALERT_NAMESPACE}.original_event` as const; export const ALERT_ORIGINAL_EVENT_ACTION = `${ALERT_ORIGINAL_EVENT}.action` as const; @@ -24,3 +25,4 @@ export const ALERT_ORIGINAL_EVENT_TYPE = `${ALERT_ORIGINAL_EVENT}.type` as const export const ALERT_RULE_THRESHOLD = `${ALERT_RULE_NAMESPACE}.threshold` as const; export const ALERT_RULE_THRESHOLD_FIELD = `${ALERT_RULE_THRESHOLD}.field` as const; +export const ALERT_RULE_TIMELINE_ID = `${ALERT_RULE_NAMESPACE}.timeline_id` as const; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/index.ts b/x-pack/plugins/security_solution/common/field_maps/index.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/index.ts rename to x-pack/plugins/security_solution/common/field_maps/index.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/rules.ts b/x-pack/plugins/security_solution/common/field_maps/rules.ts similarity index 100% rename from x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/rules.ts rename to x-pack/plugins/security_solution/common/field_maps/rules.ts diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts index 49c2dd4b41717..e5b2c4eed3b00 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts @@ -54,6 +54,7 @@ describe('Alerts timeline', () => { loadDetectionsPage(ROLES.platform_engineer); }); + // Skipping due to alerts not refreshing for platform_engineer despite being returned from API? it.skip('should allow a user with crud privileges to attach alerts to cases', () => { cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); cy.get(ATTACH_ALERT_TO_CASE_BUTTON).first().should('not.be.disabled'); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx index fb958c775e68c..213f8c78e3b8d 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx @@ -7,12 +7,21 @@ /* eslint-disable complexity */ -import dateMath from '@elastic/datemath'; -import { getOr, isEmpty } from 'lodash/fp'; +import { get, getOr, isEmpty } from 'lodash/fp'; import moment from 'moment'; -import { i18n } from '@kbn/i18n'; + +import dateMath from '@elastic/datemath'; import { FilterStateStore, Filter } from '@kbn/es-query'; +import { i18n } from '@kbn/i18n'; +import { ALERT_RULE_FROM, ALERT_RULE_TYPE, ALERT_RULE_NOTE } from '@kbn/rule-data-utils'; + +import { + ALERT_ORIGINAL_TIME, + ALERT_GROUP_ID, + ALERT_RULE_TIMELINE_ID, + ALERT_THRESHOLD_RESULT, +} from '../../../../common/field_maps/field_names'; import { KueryFilterQueryKind, TimelineId, @@ -40,6 +49,7 @@ import { formatTimelineResultToModel, } from '../../../timelines/components/open_timeline/helpers'; import { convertKueryToElasticSearchQuery } from '../../../common/lib/keury'; +import { getField } from '../../../helpers'; import { replaceTemplateFieldFromQuery, replaceTemplateFieldFromMatchFilters, @@ -68,10 +78,18 @@ export const getUpdateAlertsQuery = (eventIds: Readonly) => { export const getFilterAndRuleBounds = ( data: TimelineNonEcsData[][] ): [string[], number, number] => { - const stringFilter = data?.[0].filter((d) => d.field === 'signal.rule.filters')?.[0]?.value ?? []; + const stringFilter = + data?.[0].filter( + (d) => d.field === 'signal.rule.filters' || d.field === 'kibana.alert.rule.filters' + )?.[0]?.value ?? []; const eventTimes = data - .flatMap((alert) => alert.filter((d) => d.field === 'signal.original_time')?.[0]?.value ?? []) + .flatMap( + (alert) => + alert.filter( + (d) => d.field === 'signal.original_time' || d.field === 'kibana.alert.original_time' + )?.[0]?.value ?? [] + ) .map((d) => moment(d)); return [stringFilter, moment.min(eventTimes).valueOf(), moment.max(eventTimes).valueOf()]; @@ -134,10 +152,9 @@ export const determineToAndFrom = ({ ecs }: { ecs: Ecs[] | Ecs }) => { }; } const ecsData = ecs as Ecs; + const ruleFrom = getField(ecsData, ALERT_RULE_FROM); const elapsedTimeRule = moment.duration( - moment().diff( - dateMath.parse(ecsData?.signal?.rule?.from != null ? ecsData.signal?.rule?.from[0] : 'now-0s') - ) + moment().diff(dateMath.parse(ruleFrom != null ? ruleFrom[0] : 'now-0s')) ); const from = moment(ecsData?.timestamp ?? new Date()) .subtract(elapsedTimeRule) @@ -161,6 +178,7 @@ export const getThresholdAggregationData = ( ecsData: Ecs | Ecs[], nonEcsData: TimelineNonEcsData[] ): ThresholdAggregationData => { + // TODO: AAD fields const thresholdEcsData: Ecs[] = Array.isArray(ecsData) ? ecsData : [ecsData]; return thresholdEcsData.reduce( (outerAcc, thresholdData) => { @@ -177,9 +195,14 @@ export const getThresholdAggregationData = ( }; try { - thresholdResult = JSON.parse((thresholdData.signal?.threshold_result as string[])[0]); + try { + thresholdResult = JSON.parse((thresholdData.signal?.threshold_result as string[])[0]); + } catch (err) { + thresholdResult = JSON.parse((get(ALERT_THRESHOLD_RESULT, thresholdData) as string[])[0]); + } aggField = JSON.parse(threshold[0]).field; } catch (err) { + // Legacy support thresholdResult = { terms: [ { @@ -192,13 +215,15 @@ export const getThresholdAggregationData = ( }; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const originalTime = moment(thresholdData.signal?.original_time![0]); - const now = moment(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const ruleFrom = dateMath.parse(thresholdData.signal?.rule?.from![0]!); - const ruleInterval = moment.duration(now.diff(ruleFrom)); + // Legacy support + const ruleFromStr = getField(thresholdData, ALERT_RULE_FROM)[0]; + const ruleFrom = dateMath.parse(ruleFromStr) ?? moment(); // The fallback here will essentially ensure 0 results + const originalTimeStr = getField(thresholdData, ALERT_ORIGINAL_TIME)[0]; + const originalTime = originalTimeStr != null ? moment(originalTimeStr) : ruleFrom; + const ruleInterval = moment.duration(moment().diff(ruleFrom)); const fromOriginalTime = originalTime.clone().subtract(ruleInterval); // This is the default... can overshoot + // End legacy support + const aggregationFields = Array.isArray(aggField) ? aggField : [aggField]; return { @@ -255,16 +280,19 @@ export const getThresholdAggregationData = ( ); }; -export const isEqlRuleWithGroupId = (ecsData: Ecs) => - ecsData.signal?.rule?.type?.length && - ecsData.signal?.rule?.type[0] === 'eql' && - ecsData.signal?.group?.id?.length; +export const isEqlRuleWithGroupId = (ecsData: Ecs) => { + const ruleType = getField(ecsData, ALERT_RULE_TYPE); + const groupId = getField(ecsData, ALERT_GROUP_ID); + return ruleType?.length && ruleType[0] === 'eql' && groupId?.length; +}; -export const isThresholdRule = (ecsData: Ecs) => - ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'threshold'; +export const isThresholdRule = (ecsData: Ecs) => { + const ruleType = getField(ecsData, ALERT_RULE_TYPE); + return Array.isArray(ruleType) && ruleType.length && ruleType[0] === 'threshold'; +}; export const buildAlertsKqlFilter = ( - key: '_id' | 'signal.group.id', + key: '_id' | 'signal.group.id' | 'kibana.alert.group.id', alertIds: string[] ): Filter[] => { return [ @@ -283,7 +311,7 @@ export const buildAlertsKqlFilter = ( negate: false, disabled: false, type: 'phrases', - key, + key: key.replace('signal.', 'kibana.alert.'), value: alertIds.join(), params: alertIds, }, @@ -383,9 +411,11 @@ export const sendAlertToTimelineAction = async ({ */ const ecsData: Ecs = Array.isArray(ecs) && ecs.length > 0 ? ecs[0] : (ecs as Ecs); const alertIds = Array.isArray(ecs) ? ecs.map((d) => d._id) : []; - const noteContent = ecsData.signal?.rule?.note != null ? ecsData.signal?.rule?.note[0] : ''; + const ruleNote = getField(ecsData, ALERT_RULE_NOTE); + const noteContent = Array.isArray(ruleNote) && ruleNote.length > 0 ? ruleNote[0] : ''; + const ruleTimelineId = getField(ecsData, ALERT_RULE_TIMELINE_ID); const timelineId = - ecsData.signal?.rule?.timeline_id != null ? ecsData.signal?.rule?.timeline_id[0] : ''; + Array.isArray(ruleTimelineId) && ruleTimelineId.length > 0 ? ruleTimelineId[0] : ''; const { to, from } = determineToAndFrom({ ecs }); // For now we do not want to populate the template timeline if we have alertIds diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx index e14c3e916a35e..a342b01b038ca 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_to_case_actions.tsx @@ -8,7 +8,7 @@ import { useMemo } from 'react'; import { useGetUserCasesPermissions, useKibana } from '../../../../common/lib/kibana'; import { TimelineId, TimelineNonEcsData } from '../../../../../common'; -import { APP_UI_ID } from '../../../../../common/constants'; +import { APP_ID } from '../../../../../common/constants'; import { useInsertTimeline } from '../../../../cases/components/use_insert_timeline'; import { Ecs } from '../../../../../common/ecs'; @@ -39,7 +39,7 @@ export const useAddToCaseActions = ({ event: { data: nonEcsData ?? [], ecs: ecsData, _id: ecsData?._id }, useInsertTimeline: insertTimelineHook, casePermissions, - appId: APP_UI_ID, + appId: APP_ID, onClose: afterCaseSelection, } : null, diff --git a/x-pack/plugins/security_solution/public/helpers.tsx b/x-pack/plugins/security_solution/public/helpers.tsx index 066e6a4cb4684..f160d293dd475 100644 --- a/x-pack/plugins/security_solution/public/helpers.tsx +++ b/x-pack/plugins/security_solution/public/helpers.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { isEmpty } from 'lodash/fp'; +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { get, isEmpty } from 'lodash/fp'; import React from 'react'; import { matchPath, RouteProps, Redirect } from 'react-router-dom'; @@ -22,6 +23,7 @@ import { OVERVIEW_PATH, CASES_PATH, } from '../common/constants'; +import { Ecs } from '../common/ecs'; import { FactoryQueryTypes, StrategyResponseType, @@ -208,3 +210,27 @@ export const RedirectRoute = React.memo<{ capabilities: Capabilities }>(({ capab return ; }); RedirectRoute.displayName = 'RedirectRoute'; + +const siemSignalsFieldMappings: Record = { + [ALERT_RULE_UUID]: 'signal.rule.id', +}; + +const alertFieldMappings: Record = { + 'signal.rule.id': ALERT_RULE_UUID, +}; + +/* + * Deprecation notice: This functionality should be removed when support for signal.* is no longer + * supported. + * + * Selectively returns the AAD field value (kibana.alert.*) or the legacy field value + * (signal.*), whichever is present. For backwards compatibility. + */ +export const getField = (ecsData: Ecs, field: string) => { + const aadField = (alertFieldMappings[field] ?? field).replace('signal', 'kibana.alert'); + const siemSignalsField = (siemSignalsFieldMappings[field] ?? field).replace( + 'kibana.alert', + 'signal' + ); + return get(aadField, ecsData) ?? get(siemSignalsField, ecsData); +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts index 73029689deb19..e7ab48e807d54 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/__mocks__/threshold.ts @@ -27,12 +27,12 @@ import { TypeOfFieldMap } from '../../../../../../rule_registry/common/field_map import { SERVER_APP_ID } from '../../../../../common/constants'; import { ANCHOR_DATE } from '../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock'; -import { RulesFieldMap } from '../field_maps'; +import { RulesFieldMap } from '../../../../../common/field_maps'; import { ALERT_ANCESTORS, ALERT_ORIGINAL_TIME, ALERT_ORIGINAL_EVENT, -} from '../field_maps/field_names'; +} from '../../../../../common/field_maps/field_names'; import { WrappedRACAlert } from '../types'; export const mockThresholdResults = { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts index 39ee8788d3ee0..d6bad86456493 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts @@ -31,14 +31,14 @@ import { ANCHOR_DATE, } from '../../../../../../common/detection_engine/schemas/response/rules_schema.mocks'; import { getListArrayMock } from '../../../../../../common/detection_engine/schemas/types/lists.mock'; +import { SERVER_APP_ID } from '../../../../../../common/constants'; +import { EVENT_DATASET } from '../../../../../../common/cti/constants'; import { ALERT_ANCESTORS, + ALERT_ORIGINAL_TIME, ALERT_DEPTH, ALERT_ORIGINAL_EVENT, - ALERT_ORIGINAL_TIME, -} from '../../field_maps/field_names'; -import { SERVER_APP_ID } from '../../../../../../common/constants'; -import { EVENT_DATASET } from '../../../../../../common/cti/constants'; +} from '../../../../../../common/field_maps/field_names'; type SignalDoc = SignalSourceHit & { _source: Required['_source'] & { [TIMESTAMP]: string }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts index bfd79d67bb74d..bf07d2bb8515f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.ts @@ -29,14 +29,14 @@ import { isWrappedSignalHit, } from '../../../signals/utils'; import { RACAlert } from '../../types'; +import { SERVER_APP_ID } from '../../../../../../common/constants'; +import { SearchTypes } from '../../../../telemetry/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, - ALERT_ORIGINAL_EVENT, ALERT_ORIGINAL_TIME, -} from '../../field_maps/field_names'; -import { SERVER_APP_ID } from '../../../../../../common/constants'; -import { SearchTypes } from '../../../../telemetry/types'; + ALERT_ORIGINAL_EVENT, +} from '../../../../../../common/field_maps/field_names'; export const generateAlertId = (alert: RACAlert) => { return createHash('sha256') diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts index 3f6d419e6ddd0..86b57b1ed1698 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.test.ts @@ -11,15 +11,15 @@ import { ALERT_RULE_CONSUMER } from '@kbn/rule-data-utils'; import { sampleDocNoSortId, sampleRuleGuid } from '../../../signals/__mocks__/es_results'; import { buildAlertGroupFromSequence } from './build_alert_group_from_sequence'; +import { SERVER_APP_ID } from '../../../../../../common/constants'; +import { getCompleteRuleMock, getQueryRuleParams } from '../../../schemas/rule_schemas.mock'; +import { QueryRuleParams } from '../../../schemas/rule_schemas'; import { ALERT_ANCESTORS, - ALERT_BUILDING_BLOCK_TYPE, ALERT_DEPTH, + ALERT_BUILDING_BLOCK_TYPE, ALERT_GROUP_ID, -} from '../../field_maps/field_names'; -import { SERVER_APP_ID } from '../../../../../../common/constants'; -import { getCompleteRuleMock, getQueryRuleParams } from '../../../schemas/rule_schemas.mock'; -import { QueryRuleParams } from '../../../schemas/rule_schemas'; +} from '../../../../../../common/field_maps/field_names'; const SPACE_ID = 'space'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts index 451f322f72799..23958451800b0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert_group_from_sequence.ts @@ -19,12 +19,12 @@ import { EqlSequence } from '../../../../../../common/detection_engine/types'; import { generateBuildingBlockIds } from './generate_building_block_ids'; import { objectArrayIntersection } from '../../../signals/build_bulk_body'; import { BuildReasonMessage } from '../../../signals/reason_formatters'; +import { CompleteRule, RuleParams } from '../../../schemas/rule_schemas'; import { ALERT_BUILDING_BLOCK_TYPE, ALERT_GROUP_ID, ALERT_GROUP_INDEX, -} from '../../field_maps/field_names'; -import { CompleteRule, RuleParams } from '../../../schemas/rule_schemas'; +} from '../../../../../../common/field_maps/field_names'; /** * Takes N raw documents from ES that form a sequence and builds them into N+1 signals ready to be indexed - diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/generate_building_block_ids.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/generate_building_block_ids.ts index 84e7f9e3ecef2..a603946b03d3b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/generate_building_block_ids.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/generate_building_block_ids.ts @@ -7,8 +7,8 @@ import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { createHash } from 'crypto'; +import { ALERT_ANCESTORS } from '../../../../../../common/field_maps/field_names'; import { Ancestor } from '../../../signals/types'; -import { ALERT_ANCESTORS } from '../../field_maps/field_names'; import { RACAlert } from '../../types'; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts index 89c01f65b4156..d5b4d1f1eec77 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts @@ -33,9 +33,9 @@ import { WrapHits, WrapSequences, } from '../signals/types'; -import { AlertsFieldMap, RulesFieldMap } from './field_maps'; import { ExperimentalFeatures } from '../../../../common/experimental_features'; import { IEventLogService } from '../../../../../event_log/server'; +import { AlertsFieldMap, RulesFieldMap } from '../../../../common/field_maps'; export interface SecurityAlertTypeReturnValue { bulkCreateTimes: string[]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts index 8362942af15b9..dbf2fb7feac2a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ALERT_ORIGINAL_TIME } from '../../rule_types/field_maps/field_names'; +import { ALERT_ORIGINAL_TIME } from '../../../../../common/field_maps/field_names'; import { sampleThresholdAlert } from '../../rule_types/__mocks__/threshold'; import { buildThresholdSignalHistory } from './build_signal_history'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts index e5c21edbc9350..b959f3de47a8a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts @@ -7,9 +7,9 @@ import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { - ALERT_ORIGINAL_TIME, ALERT_RULE_THRESHOLD_FIELD, -} from '../../rule_types/field_maps/field_names'; + ALERT_ORIGINAL_TIME, +} from '../../../../../common/field_maps/field_names'; import { SimpleHit, ThresholdSignalHistory } from '../types'; import { getThresholdTermsHash, isWrappedRACAlert, isWrappedSignalHit } from '../utils'; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 307ccf4cfc977..2725743f76e75 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -64,8 +64,6 @@ import { licenseService } from './lib/license'; import { PolicyWatcher } from './endpoint/lib/policy/license_watch'; import { migrateArtifactsToFleet } from './endpoint/lib/artifacts/migrate_artifacts_to_fleet'; import aadFieldConversion from './lib/detection_engine/routes/index/signal_aad_mapping.json'; -import { alertsFieldMap } from './lib/detection_engine/rule_types/field_maps/alerts'; -import { rulesFieldMap } from './lib/detection_engine/rule_types/field_maps/rules'; import { registerEventLogProvider } from './lib/detection_engine/rule_execution_log/event_log_adapter/register_event_log_provider'; import { getKibanaPrivilegesFeaturePrivileges, getCasesKibanaFeature } from './features'; import { EndpointMetadataService } from './endpoint/services/metadata'; @@ -88,6 +86,7 @@ import type { SecuritySolutionPluginStart, PluginInitializerContext, } from './plugin_contract'; +import { alertsFieldMap, rulesFieldMap } from '../common/field_maps'; export { SetupPlugins, StartPlugins, PluginSetup, PluginStart } from './plugin_contract'; diff --git a/x-pack/plugins/timelines/public/hooks/use_add_to_case.ts b/x-pack/plugins/timelines/public/hooks/use_add_to_case.ts index d15b4e6980767..34622423781f9 100644 --- a/x-pack/plugins/timelines/public/hooks/use_add_to_case.ts +++ b/x-pack/plugins/timelines/public/hooks/use_add_to_case.ts @@ -126,7 +126,7 @@ export const useAddToCase = ({ } }, [event]); const isSecurityAlert = useMemo(() => { - return !isEmpty(event?.ecs.signal?.rule?.id); + return !isEmpty(event?.ecs.signal?.rule?.id ?? event?.ecs.kibana?.alert?.rule?.uuid); }, [event]); const isEventSupported = isSecurityAlert || isAlert; const userCanCrud = casePermissions?.crud ?? false; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts index 6cfc21306d0a6..9e0aff09c84c8 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts @@ -37,7 +37,7 @@ import { ALERT_ANCESTORS, ALERT_DEPTH, ALERT_ORIGINAL_TIME, -} from '../../../../plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names'; +} from '../../../../plugins/security_solution/common/field_maps/field_names'; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts index dcfdfb7bbd9bc..250f6cf1d0b83 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts @@ -41,6 +41,7 @@ import { import { getCreateThreatMatchRulesSchemaMock } from '../../../../plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.mock'; import { getThreatMatchingSchemaPartialMock } from '../../../../plugins/security_solution/common/detection_engine/schemas/response/rules_schema.mocks'; import { ENRICHMENT_TYPES } from '../../../../plugins/security_solution/common/cti/constants'; +import { Ancestor } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, @@ -48,8 +49,7 @@ import { ALERT_ORIGINAL_EVENT_CATEGORY, ALERT_ORIGINAL_EVENT_MODULE, ALERT_ORIGINAL_TIME, -} from '../../../../plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names'; -import { Ancestor } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; +} from '../../../../plugins/security_solution/common/field_maps/field_names'; const format = (value: unknown): string => JSON.stringify(value, null, 2); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts index 2977037a9523f..876a1a9d6dca1 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts @@ -46,15 +46,15 @@ import { waitForRuleSuccessOrStatus, waitForSignalsToBePresent, } from '../../utils'; +import { Ancestor } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; import { ALERT_ANCESTORS, ALERT_DEPTH, - ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, ALERT_ORIGINAL_EVENT, ALERT_ORIGINAL_EVENT_CATEGORY, - ALERT_ORIGINAL_TIME, -} from '../../../../plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names'; -import { Ancestor } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; + ALERT_GROUP_ID, +} from '../../../../plugins/security_solution/common/field_maps/field_names'; /** * Specific _id to use for some of the tests. If the archiver changes and you see errors diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts index f4b91cae36448..01543fc59e47f 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts @@ -11,7 +11,7 @@ import { EqlCreateSchema, QueryCreateSchema, } from '../../../../plugins/security_solution/common/detection_engine/schemas/request'; -import { ALERT_ORIGINAL_TIME } from '../../../../plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/field_names'; +import { ALERT_ORIGINAL_TIME } from '../../../../plugins/security_solution/common/field_maps/field_names'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import {