diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts index 3c8b96976792d7..55f8eecf72935a 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts @@ -49,6 +49,11 @@ export const technicalRuleFieldMap = { array: false, required: false, }, + [Fields.ALERT_RISK_SCORE]: { + type: 'float', + array: false, + required: false, + }, [Fields.ALERT_WORKFLOW_STATUS]: { type: 'keyword', array: false, diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index e80dd9ab8bf31d..8e0ee7d6c58ada 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -8,6 +8,7 @@ import type { TransformConfigSchema } from './transforms/types'; import { ENABLE_CASE_CONNECTOR } from '../../cases/common'; import { metadataTransformPattern } from './endpoint/constants'; +import { ALERT_RULE_THREAT_TACTIC_NAME } from '../../timelines/common/alerts'; export const APP_ID = 'securitySolution'; export const SERVER_APP_ID = 'siem'; @@ -299,7 +300,7 @@ export const showAllOthersBucket: string[] = [ 'event.category', 'event.dataset', 'event.module', - 'signal.rule.threat.tactic.name', + ALERT_RULE_THREAT_TACTIC_NAME, 'source.ip', 'destination.ip', 'user.name', diff --git a/x-pack/plugins/security_solution/common/ecs/ecs_fields/index.ts b/x-pack/plugins/security_solution/common/ecs/ecs_fields/index.ts index 292822019fc9ca..7557b0393f3679 100644 --- a/x-pack/plugins/security_solution/common/ecs/ecs_fields/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/ecs_fields/index.ts @@ -5,6 +5,43 @@ * 2.0. */ +import { + ALERT_RULE_CREATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_NAME, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_TAGS, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_RISK_SCORE, + ALERT_SEVERITY, +} from '@kbn/rule-data-utils'; +import { + ALERT_ORIGINAL_TIME, + ALERT_RULE_EXCEPTIONS_LIST, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_QUERY, + ALERT_RULE_SAVED_ID, + ALERT_RULE_SIZE, + ALERT_RULE_THREAT, + ALERT_RULE_THRESHOLD, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, +} from '../../../../timelines/common/alerts'; import { extendMap } from './extend_map'; export const auditdMap: Readonly> = { @@ -290,41 +327,40 @@ export const systemFieldsMap: Readonly> = { 'system.auth.ssh.method': 'system.auth.ssh.method', }; -export const signalFieldsMap: Readonly> = { - 'signal.original_time': 'signal.original_time', - 'signal.rule.id': 'signal.rule.id', - 'signal.rule.saved_id': 'signal.rule.saved_id', - 'signal.rule.timeline_id': 'signal.rule.timeline_id', - 'signal.rule.timeline_title': 'signal.rule.timeline_title', - 'signal.rule.output_index': 'signal.rule.output_index', - 'signal.rule.from': 'signal.rule.from', - 'signal.rule.index': 'signal.rule.index', - 'signal.rule.language': 'signal.rule.language', - 'signal.rule.query': 'signal.rule.query', - 'signal.rule.to': 'signal.rule.to', - 'signal.rule.filters': 'signal.rule.filters', - 'signal.rule.rule_id': 'signal.rule.rule_id', - 'signal.rule.false_positives': 'signal.rule.false_positives', - 'signal.rule.max_signals': 'signal.rule.max_signals', - 'signal.rule.risk_score': 'signal.rule.risk_score', - 'signal.rule.description': 'signal.rule.description', - 'signal.rule.name': 'signal.rule.name', - 'signal.rule.immutable': 'signal.rule.immutable', - 'signal.rule.references': 'signal.rule.references', - 'signal.rule.severity': 'signal.rule.severity', - 'signal.rule.tags': 'signal.rule.tags', - 'signal.rule.threat': 'signal.rule.threat', - 'signal.rule.type': 'signal.rule.type', - 'signal.rule.size': 'signal.rule.size', - 'signal.rule.enabled': 'signal.rule.enabled', - 'signal.rule.created_at': 'signal.rule.created_at', - 'signal.rule.updated_at': 'signal.rule.updated_at', - 'signal.rule.created_by': 'signal.rule.created_by', - 'signal.rule.updated_by': 'signal.rule.updated_by', - 'signal.rule.version': 'signal.rule.version', - 'signal.rule.note': 'signal.rule.note', - 'signal.rule.threshold': 'signal.rule.threshold', - 'signal.rule.exceptions_list': 'signal.rule.exceptions_list', +export const alertFieldsMap: Readonly> = { + [ALERT_ORIGINAL_TIME]: ALERT_ORIGINAL_TIME, + [ALERT_RULE_UUID]: ALERT_RULE_UUID, + [ALERT_RULE_SAVED_ID]: ALERT_RULE_SAVED_ID, + [ALERT_RULE_TIMELINE_ID]: ALERT_RULE_TIMELINE_ID, + [ALERT_RULE_TIMELINE_TITLE]: ALERT_RULE_TIMELINE_TITLE, + [ALERT_RULE_FROM]: ALERT_RULE_FROM, + [ALERT_RULE_INDEX]: ALERT_RULE_INDEX, + [ALERT_RULE_LANGUAGE]: ALERT_RULE_LANGUAGE, + [ALERT_RULE_QUERY]: ALERT_RULE_QUERY, + [ALERT_RULE_TO]: ALERT_RULE_TO, + [ALERT_RULE_FILTERS]: ALERT_RULE_FILTERS, + [ALERT_RULE_RULE_ID]: ALERT_RULE_RULE_ID, + [ALERT_RULE_FALSE_POSITIVES]: ALERT_RULE_FALSE_POSITIVES, + [ALERT_RULE_MAX_SIGNALS]: ALERT_RULE_MAX_SIGNALS, + [ALERT_RULE_DESCRIPTION]: ALERT_RULE_DESCRIPTION, + [ALERT_RULE_NAME]: ALERT_RULE_NAME, + [ALERT_RULE_IMMUTABLE]: ALERT_RULE_IMMUTABLE, + [ALERT_RULE_REFERENCES]: ALERT_RULE_REFERENCES, + [ALERT_RULE_TAGS]: ALERT_RULE_TAGS, + [ALERT_RULE_THREAT]: ALERT_RULE_THREAT, + [ALERT_RULE_TYPE]: ALERT_RULE_TYPE, + [ALERT_RULE_SIZE]: ALERT_RULE_SIZE, + [ALERT_RULE_ENABLED]: ALERT_RULE_ENABLED, + [ALERT_RULE_CREATED_AT]: ALERT_RULE_CREATED_AT, + [ALERT_RULE_UPDATED_AT]: ALERT_RULE_UPDATED_AT, + [ALERT_RULE_CREATED_BY]: ALERT_RULE_CREATED_BY, + [ALERT_RULE_UPDATED_BY]: ALERT_RULE_UPDATED_BY, + [ALERT_RULE_VERSION]: ALERT_RULE_VERSION, + [ALERT_RULE_NOTE]: ALERT_RULE_NOTE, + [ALERT_RULE_THRESHOLD]: ALERT_RULE_THRESHOLD, + [ALERT_RULE_EXCEPTIONS_LIST]: ALERT_RULE_EXCEPTIONS_LIST, + [ALERT_SEVERITY]: ALERT_SEVERITY, + [ALERT_RISK_SCORE]: ALERT_RISK_SCORE, }; export const ruleFieldsMap: Readonly> = { @@ -336,6 +372,7 @@ export const eventFieldsMap: Readonly> = { '@timestamp': '@timestamp', message: 'message', ...{ ...agentFieldsMap }, + ...{ ...alertFieldsMap }, ...{ ...auditdMap }, ...{ ...destinationFieldsMap }, ...{ ...dnsFieldsMap }, @@ -346,7 +383,6 @@ export const eventFieldsMap: Readonly> = { ...{ ...hostFieldsMap }, ...{ ...networkFieldsMap }, ...{ ...ruleFieldsMap }, - ...{ ...signalFieldsMap }, ...{ ...sourceFieldsMap }, ...{ ...suricataFieldsMap }, ...{ ...systemFieldsMap }, diff --git a/x-pack/plugins/security_solution/common/ecs/index.ts b/x-pack/plugins/security_solution/common/ecs/index.ts index fbeb3231573671..4bcdeebd2fcb6a 100644 --- a/x-pack/plugins/security_solution/common/ecs/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/index.ts @@ -15,6 +15,7 @@ import { EventEcs } from './event'; import { FileEcs } from './file'; import { GeoEcs } from './geo'; import { HostEcs } from './host'; +import { KibanaEcs } from './kibana'; import { NetworkEcs } from './network'; import { RegistryEcs } from './registry'; import { RuleEcs } from './rule'; @@ -45,6 +46,7 @@ export interface Ecs { event?: EventEcs; geo?: GeoEcs; host?: HostEcs; + kibana?: KibanaEcs; network?: NetworkEcs; registry?: RegistryEcs; rule?: RuleEcs; diff --git a/x-pack/plugins/security_solution/common/ecs/kibana/index.ts b/x-pack/plugins/security_solution/common/ecs/kibana/index.ts new file mode 100644 index 00000000000000..95fba085d43e61 --- /dev/null +++ b/x-pack/plugins/security_solution/common/ecs/kibana/index.ts @@ -0,0 +1,23 @@ +/* + * 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 { RuleEcs } from '../rule'; + +export interface KibanaEcs { + alert?: { + risk_score?: string[]; + severity?: string[]; + rule?: RuleEcs; + original_time?: string[]; + status?: string[]; + group?: { + id?: string[]; + }; + threshold_result?: unknown; + workflow_status?: string[]; + }; +} diff --git a/x-pack/plugins/security_solution/common/ecs/rule/index.ts b/x-pack/plugins/security_solution/common/ecs/rule/index.ts index ae7e5064a8eced..d8003b7b0cc2be 100644 --- a/x-pack/plugins/security_solution/common/ecs/rule/index.ts +++ b/x-pack/plugins/security_solution/common/ecs/rule/index.ts @@ -6,8 +6,8 @@ */ export interface RuleEcs { - id?: string[]; rule_id?: string[]; + uuid?: string[]; name?: string[]; false_positives?: string[]; saved_id?: string[]; diff --git a/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts b/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts index 64d4f2986903a1..f72bab0440514f 100644 --- a/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts +++ b/x-pack/plugins/security_solution/common/utils/field_formatters.test.ts @@ -5,9 +5,10 @@ * 2.0. */ +import { eventDetailsFormattedFields, eventHit } from '@kbn/securitysolution-t-grid'; +import { ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { EventHit, EventSource } from '../search_strategy'; import { getDataFromFieldsHits, getDataFromSourceHits, getDataSafety } from './field_formatters'; -import { eventDetailsFormattedFields, eventHit } from '@kbn/securitysolution-t-grid'; describe('Events Details Helpers', () => { const fields: EventHit['fields'] = eventHit.fields; @@ -135,8 +136,8 @@ describe('Events Details Helpers', () => { it('#getDataFromSourceHits', () => { const _source: EventSource = { '@timestamp': '2021-02-24T00:41:06.527Z', - 'signal.status': 'open', - 'signal.rule.name': 'Rawr', + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_NAME]: 'Rawr', 'threat.indicator': [ { provider: 'yourself', @@ -161,15 +162,15 @@ describe('Events Details Helpers', () => { isObjectArray: false, }, { - category: 'signal', - field: 'signal.status', + category: 'kibana', + field: ALERT_WORKFLOW_STATUS, values: ['open'], originalValue: ['open'], isObjectArray: false, }, { - category: 'signal', - field: 'signal.rule.name', + category: 'kibana', + field: ALERT_RULE_NAME, values: ['Rawr'], originalValue: ['Rawr'], isObjectArray: false, diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts index 9ee80636fab2e9..6c5becdd7092df 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts @@ -13,7 +13,13 @@ import { getEditedRule, getNewOverrideRule, } from '../../objects/rule'; -import { ALERT_GRID_CELL, NUMBER_OF_ALERTS } from '../../screens/alerts'; +import { + ALERT_GRID_CELL, + ALERT_RISK_SCORE, + ALERT_RULE_NAME, + ALERT_SEVERITY, + NUMBER_OF_ALERTS, +} from '../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -215,9 +221,9 @@ describe('Custom detection rules creation', () => { waitForAlertsToPopulate(); cy.get(NUMBER_OF_ALERTS).should(($count) => expect(+$count.text().split(' ')[0]).to.be.gte(1)); - cy.get(ALERT_GRID_CELL).eq(3).contains(this.rule.name); - cy.get(ALERT_GRID_CELL).eq(4).contains(this.rule.severity.toLowerCase()); - cy.get(ALERT_GRID_CELL).eq(5).contains(this.rule.riskScore); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RULE_NAME}`).contains(this.rule.name); + cy.get(`${ALERT_GRID_CELL} ${ALERT_SEVERITY}`).contains(this.rule.severity.toLowerCase()); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RISK_SCORE}`).contains(this.rule.riskScore); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts index f8b3b426580b29..3aebf87aa3fafb 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts @@ -14,8 +14,8 @@ import { import { ALERT_RULE_NAME, - ALERT_RULE_RISK_SCORE, - ALERT_RULE_SEVERITY, + ALERT_RISK_SCORE, + ALERT_SEVERITY, NUMBER_OF_ALERTS, } from '../../screens/alerts'; import { @@ -480,12 +480,10 @@ describe('indicator match', () => { cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts); cy.get(ALERT_RULE_NAME).first().should('have.text', getNewThreatIndicatorRule().name); - cy.get(ALERT_RULE_SEVERITY) + cy.get(ALERT_SEVERITY) .first() .should('have.text', getNewThreatIndicatorRule().severity.toLowerCase()); - cy.get(ALERT_RULE_RISK_SCORE) - .first() - .should('have.text', getNewThreatIndicatorRule().riskScore); + cy.get(ALERT_RISK_SCORE).first().should('have.text', getNewThreatIndicatorRule().riskScore); }); it('Investigate alert in timeline', () => { diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts index cd3f645a8f5ed0..94e713e1af5d54 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { formatMitreAttackDescription } from '../../helpers/rules'; import { getIndexPatterns, @@ -13,7 +14,13 @@ import { OverrideRule, } from '../../objects/rule'; -import { NUMBER_OF_ALERTS, ALERT_GRID_CELL } from '../../screens/alerts'; +import { + NUMBER_OF_ALERTS, + ALERT_GRID_CELL, + ALERT_RISK_SCORE as ALERT_RISK_SCORE_FIELD, + ALERT_RULE_NAME, + ALERT_SEVERITY, +} from '../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -139,7 +146,7 @@ describe('Detection rules, override', () => { getDetails(RISK_SCORE_DETAILS).should('have.text', this.rule.riskScore); getDetails(RISK_SCORE_OVERRIDE_DETAILS).should( 'have.text', - `${this.rule.riskOverride}signal.rule.risk_score` + `${this.rule.riskOverride}${ALERT_RISK_SCORE}` ); getDetails(RULE_NAME_OVERRIDE_DETAILS).should('have.text', this.rule.nameOverride); getDetails(REFERENCE_URLS_DETAILS).should((details) => { @@ -187,12 +194,8 @@ describe('Detection rules, override', () => { waitForAlertsToPopulate(); cy.get(NUMBER_OF_ALERTS).should(($count) => expect(+$count.text().split(' ')[0]).to.be.gte(1)); - cy.get(ALERT_GRID_CELL).eq(3).contains('auditbeat'); - cy.get(ALERT_GRID_CELL).eq(4).contains('critical'); - - // TODO: Is this necessary? - // sortRiskScore(); - - cy.get(ALERT_GRID_CELL).eq(5).contains('80'); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RULE_NAME}`).contains('auditbeat'); + cy.get(`${ALERT_GRID_CELL} ${ALERT_SEVERITY}`).contains('critical'); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RISK_SCORE_FIELD}`).contains('80'); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts index 7bfc9631f7269d..1b991bfe4e2a3f 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts @@ -13,7 +13,13 @@ import { ThresholdRule, } from '../../objects/rule'; -import { ALERT_GRID_CELL, NUMBER_OF_ALERTS } from '../../screens/alerts'; +import { + ALERT_GRID_CELL, + ALERT_RISK_SCORE, + ALERT_RULE_NAME, + ALERT_SEVERITY, + NUMBER_OF_ALERTS, +} from '../../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -171,9 +177,9 @@ describe('Detection rules, threshold', () => { waitForAlertsToPopulate(); cy.get(NUMBER_OF_ALERTS).should(($count) => expect(+$count.text().split(' ')[0]).to.be.lt(100)); - cy.get(ALERT_GRID_CELL).eq(3).contains(rule.name); - cy.get(ALERT_GRID_CELL).eq(4).contains(rule.severity.toLowerCase()); - cy.get(ALERT_GRID_CELL).eq(5).contains(rule.riskScore); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RULE_NAME}`).contains(rule.name); + cy.get(`${ALERT_GRID_CELL} ${ALERT_SEVERITY}`).contains(rule.severity.toLowerCase()); + cy.get(`${ALERT_GRID_CELL} ${ALERT_RISK_SCORE}`).contains(rule.riskScore); }); it('Preview results of keyword using "host.name"', () => { diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index 675a25641a2bd2..5df416e5b6556c 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -19,13 +19,18 @@ export const ALERT_GRID_CELL = '[data-test-subj="dataGridRowCell"]'; export const ALERT_ID = '[data-test-subj="draggable-content-_id"]'; export const ALERT_RISK_SCORE_HEADER = - '[data-test-subj="dataGridHeaderCell-signal.rule.risk_score"]'; + '[data-test-subj="dataGridHeaderCell-kibana.alert.risk_score"]'; -export const ALERT_RULE_NAME = '[data-test-subj="formatted-field-signal.rule.name"]'; +export const ALERT_RULE_NAME = '[data-test-subj="formatted-field-kibana.alert.rule.name"]'; -export const ALERT_RULE_RISK_SCORE = '[data-test-subj="formatted-field-signal.rule.risk_score"]'; +export const ALERT_RULE_RISK_SCORE = + '[data-test-subj="formatted-field-kibana.alert.rule.risk_score"]'; -export const ALERT_RULE_SEVERITY = '[data-test-subj="formatted-field-signal.rule.severity"]'; +export const ALERT_RULE_SEVERITY = '[data-test-subj="formatted-field-kibana.alert.rule.severity"]'; + +export const ALERT_RISK_SCORE = '[data-test-subj="formatted-field-kibana.alert.risk_score"]'; + +export const ALERT_SEVERITY = '[data-test-subj="formatted-field-kibana.alert.severity"]'; export const ALERT_DATA_GRID = '[data-test-subj="dataGridWrapper"]'; diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.test.ts b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.test.ts index ad83f2762c0f0d..baca6b62e71a41 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { omit } from 'lodash/fp'; import { DropResult } from 'react-beautiful-dnd'; import { getTimelineIdFromColumnDroppableId } from '../../../../../timelines/public'; @@ -664,7 +665,7 @@ describe('helpers', () => { expect( allowTopN({ browserField: undefined, - fieldName: 'signal.rule.name', + fieldName: ALERT_RULE_NAME, hideTopN: false, }) ).toBe(true); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts index bca6c15d861408..a4d34299875f36 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/helpers.ts @@ -9,11 +9,78 @@ import { Dispatch } from 'redux'; import { ActionCreator } from 'typescript-fsa'; import { getProviderIdFromDraggable } from '@kbn/securitysolution-t-grid'; +import { + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_INTERVAL, + ALERT_RULE_NAME, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_TAGS, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; import { BrowserField } from '../../containers/source'; import { dragAndDropActions } from '../../store/actions'; import { IdToDataProvider } from '../../store/drag_and_drop/model'; import { addContentToTimeline } from '../../../timelines/components/timeline/data_providers/helpers'; import { DataProvider } from '../../../timelines/components/timeline/data_providers/data_provider'; +import { + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_SEVERITY, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_TIME, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_QUERY, + ALERT_RULE_SAVED_ID, + ALERT_RULE_SIZE, + ALERT_RULE_THREAT, + ALERT_RULE_THREAT_TACTIC_ID, + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TACTIC_REFERENCE, + ALERT_RULE_THREAT_TECHNIQUE_ID, + ALERT_RULE_THREAT_TECHNIQUE_NAME, + ALERT_RULE_THREAT_TECHNIQUE_REFERENCE, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, +} from '../../../../../timelines/common/alerts'; export { draggableIdPrefix, @@ -112,76 +179,71 @@ export const allowTopN = ({ ].includes(fieldType); // TODO: remove this explicit allowlist when the ECS documentation includes alerts - const isAllowlistedNonBrowserField = [ - 'signal.ancestors.depth', - 'signal.ancestors.id', - 'signal.ancestors.rule', - 'signal.ancestors.type', - 'signal.original_event.action', - 'signal.original_event.category', - 'signal.original_event.code', - 'signal.original_event.created', - 'signal.original_event.dataset', - 'signal.original_event.duration', - 'signal.original_event.end', - 'signal.original_event.hash', - 'signal.original_event.id', - 'signal.original_event.kind', - 'signal.original_event.module', - 'signal.original_event.original', - 'signal.original_event.outcome', - 'signal.original_event.provider', - 'signal.original_event.risk_score', - 'signal.original_event.risk_score_norm', - 'signal.original_event.sequence', - 'signal.original_event.severity', - 'signal.original_event.start', - 'signal.original_event.timezone', - 'signal.original_event.type', - 'signal.original_time', - 'signal.parent.depth', - 'signal.parent.id', - 'signal.parent.index', - 'signal.parent.rule', - 'signal.parent.type', - 'signal.rule.created_by', - 'signal.rule.description', - 'signal.rule.enabled', - 'signal.rule.false_positives', - 'signal.rule.filters', - 'signal.rule.from', - 'signal.rule.id', - 'signal.rule.immutable', - 'signal.rule.index', - 'signal.rule.interval', - 'signal.rule.language', - 'signal.rule.max_signals', - 'signal.rule.name', - 'signal.rule.note', - 'signal.rule.output_index', - 'signal.rule.query', - 'signal.rule.references', - 'signal.rule.risk_score', - 'signal.rule.rule_id', - 'signal.rule.saved_id', - 'signal.rule.severity', - 'signal.rule.size', - 'signal.rule.tags', - 'signal.rule.threat', - 'signal.rule.threat.tactic.id', - 'signal.rule.threat.tactic.name', - 'signal.rule.threat.tactic.reference', - 'signal.rule.threat.technique.id', - 'signal.rule.threat.technique.name', - 'signal.rule.threat.technique.reference', - 'signal.rule.timeline_id', - 'signal.rule.timeline_title', - 'signal.rule.to', - 'signal.rule.type', - 'signal.rule.updated_by', - 'signal.rule.version', - 'signal.status', - ].includes(fieldName); + const isAllowlistedNonBrowserField = ([ + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_SEVERITY, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_TIME, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_INTERVAL, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_NAME, + ALERT_RULE_NOTE, + ALERT_RULE_QUERY, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_SAVED_ID, + ALERT_RULE_SIZE, + ALERT_RULE_TAGS, + ALERT_RULE_THREAT, + ALERT_RULE_THREAT_TACTIC_ID, + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TACTIC_REFERENCE, + ALERT_RULE_THREAT_TECHNIQUE_ID, + ALERT_RULE_THREAT_TECHNIQUE_NAME, + ALERT_RULE_THREAT_TECHNIQUE_REFERENCE, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_WORKFLOW_STATUS, + ] as string[]).includes(fieldName); if (hideTopN) { return false; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts b/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts index 9dd5a611352f40..e8809cdeb848b4 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/__mocks__/index.ts @@ -5,6 +5,58 @@ * 2.0. */ +import { + ALERT_RULE_AUTHOR, + ALERT_RULE_CREATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_INTERVAL, + ALERT_RULE_LICENSE, + ALERT_RULE_NAME, + ALERT_RULE_REFERENCES, + ALERT_RISK_SCORE, + ALERT_RULE_RISK_SCORE_MAPPING, + ALERT_RULE_RULE_ID, + ALERT_SEVERITY, + ALERT_RULE_SEVERITY_MAPPING, + ALERT_RULE_TAGS, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; +import { + ALERT_ANCESTORS, + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_TYPE, + ALERT_DEPTH, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_INGESTED, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_TIME, + ALERT_RULE_EXCEPTIONS_LIST, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_QUERY, + ALERT_RULE_THREAT, +} from '../../../../../../timelines/common/alerts'; + export const mockAlertDetailsData = [ { category: 'process', field: 'process.name', values: ['-'], originalValue: '-' }, { category: 'process', field: 'process.pid', values: [0], originalValue: 0 }, @@ -333,8 +385,8 @@ export const mockAlertDetailsData = [ }, { category: 'user', field: 'user.id', values: ['S-1-0-0'], originalValue: 'S-1-0-0' }, { - category: 'signal', - field: 'signal.parents', + category: 'kibana', + field: ALERT_ANCESTORS, values: [ '{"id":"688MAHYB7WTwW_Glsi_d","type":"event","index":"winlogbeat-7.10.0-2020.11.12-000001","depth":0}', ], @@ -347,37 +399,22 @@ export const mockAlertDetailsData = [ }, ], }, + { category: 'kibana', field: ALERT_WORKFLOW_STATUS, values: ['open'], originalValue: 'open' }, { - category: 'signal', - field: 'signal.ancestors', - values: [ - '{"id":"688MAHYB7WTwW_Glsi_d","type":"event","index":"winlogbeat-7.10.0-2020.11.12-000001","depth":0}', - ], - originalValue: [ - { - id: '688MAHYB7WTwW_Glsi_d', - type: 'event', - index: 'winlogbeat-7.10.0-2020.11.12-000001', - depth: 0, - }, - ], - }, - { category: 'signal', field: 'signal.status', values: ['open'], originalValue: 'open' }, - { - category: 'signal', - field: 'signal.rule.id', + category: 'kibana', + field: ALERT_RULE_UUID, values: ['b69d086c-325a-4f46-b17b-fb6d227006ba'], originalValue: 'b69d086c-325a-4f46-b17b-fb6d227006ba', }, { - category: 'signal', - field: 'signal.rule.rule_id', + category: 'kibana', + field: ALERT_RULE_RULE_ID, values: ['e7cd9a53-ac62-44b5-bdec-9c94d85bb1a5'], originalValue: 'e7cd9a53-ac62-44b5-bdec-9c94d85bb1a5', }, { category: 'signal', field: 'signal.rule.actions', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.author', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.false_positives', values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_AUTHOR, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_FALSE_POSITIVES, values: [], originalValue: [] }, { category: 'signal', field: 'signal.rule.meta.from', values: ['1m'], originalValue: '1m' }, { category: 'signal', @@ -385,25 +422,19 @@ export const mockAlertDetailsData = [ values: ['http://localhost:5601/app/security'], originalValue: 'http://localhost:5601/app/security', }, - { category: 'signal', field: 'signal.rule.max_signals', values: [100], originalValue: 100 }, - { category: 'signal', field: 'signal.rule.risk_score', values: [21], originalValue: 21 }, - { category: 'signal', field: 'signal.rule.risk_score_mapping', values: [], originalValue: [] }, - { - category: 'signal', - field: 'signal.rule.output_index', - values: ['.siem-signals-angelachuang-default'], - originalValue: '.siem-signals-angelachuang-default', - }, - { category: 'signal', field: 'signal.rule.description', values: ['xxx'], originalValue: 'xxx' }, + { category: 'kibana', field: ALERT_RULE_MAX_SIGNALS, values: [100], originalValue: 100 }, + { category: 'kibana', field: ALERT_RISK_SCORE, values: [21], originalValue: 21 }, + { category: 'kibana', field: ALERT_RULE_RISK_SCORE_MAPPING, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_DESCRIPTION, values: ['xxx'], originalValue: 'xxx' }, { - category: 'signal', - field: 'signal.rule.from', + category: 'kibana', + field: ALERT_RULE_FROM, values: ['now-360s'], originalValue: 'now-360s', }, { - category: 'signal', - field: 'signal.rule.index', + category: 'kibana', + field: ALERT_RULE_INDEX, values: [ 'apm-*-transaction*', 'traces-apm*', @@ -425,25 +456,25 @@ export const mockAlertDetailsData = [ 'winlogbeat-*', ], }, - { category: 'signal', field: 'signal.rule.interval', values: ['5m'], originalValue: '5m' }, - { category: 'signal', field: 'signal.rule.language', values: ['kuery'], originalValue: 'kuery' }, - { category: 'signal', field: 'signal.rule.license', values: [''], originalValue: '' }, - { category: 'signal', field: 'signal.rule.name', values: ['xxx'], originalValue: 'xxx' }, + { category: 'kibana', field: ALERT_RULE_INTERVAL, values: ['5m'], originalValue: '5m' }, + { category: 'kibana', field: ALERT_RULE_LANGUAGE, values: ['kuery'], originalValue: 'kuery' }, + { category: 'kibana', field: ALERT_RULE_LICENSE, values: [''], originalValue: '' }, + { category: 'kibana', field: ALERT_RULE_NAME, values: ['xxx'], originalValue: 'xxx' }, { - category: 'signal', - field: 'signal.rule.query', + category: 'kibana', + field: ALERT_RULE_QUERY, values: ['@timestamp : * '], originalValue: '@timestamp : * ', }, - { category: 'signal', field: 'signal.rule.references', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.severity', values: ['low'], originalValue: 'low' }, - { category: 'signal', field: 'signal.rule.severity_mapping', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.tags', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.type', values: ['query'], originalValue: 'query' }, - { category: 'signal', field: 'signal.rule.to', values: ['now'], originalValue: 'now' }, + { category: 'kibana', field: ALERT_RULE_REFERENCES, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_SEVERITY, values: ['low'], originalValue: 'low' }, + { category: 'kibana', field: ALERT_RULE_SEVERITY_MAPPING, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_TAGS, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_TYPE, values: ['query'], originalValue: 'query' }, + { category: 'kibana', field: ALERT_RULE_TO, values: ['now'], originalValue: 'now' }, { - category: 'signal', - field: 'signal.rule.filters', + category: 'kibana', + field: ALERT_RULE_FILTERS, values: [ '{"meta":{"alias":null,"negate":false,"disabled":false,"type":"exists","key":"message","value":"exists"},"exists":{"field":"message"},"$state":{"store":"appState"}}', ], @@ -463,60 +494,60 @@ export const mockAlertDetailsData = [ ], }, { - category: 'signal', - field: 'signal.rule.created_by', + category: 'kibana', + field: ALERT_RULE_CREATED_BY, values: ['angela'], originalValue: 'angela', }, { - category: 'signal', - field: 'signal.rule.updated_by', + category: 'kibana', + field: ALERT_RULE_UPDATED_BY, values: ['angela'], originalValue: 'angela', }, - { category: 'signal', field: 'signal.rule.threat', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.rule.version', values: [2], originalValue: 2 }, + { category: 'kibana', field: ALERT_RULE_THREAT, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_RULE_VERSION, values: [2], originalValue: 2 }, { - category: 'signal', - field: 'signal.rule.created_at', + category: 'kibana', + field: ALERT_RULE_CREATED_AT, values: ['2020-11-24T10:30:33.660Z'], originalValue: '2020-11-24T10:30:33.660Z', }, { - category: 'signal', - field: 'signal.rule.updated_at', + category: 'kibana', + field: ALERT_RULE_UPDATED_AT, values: ['2020-11-25T15:37:40.939Z'], originalValue: '2020-11-25T15:37:40.939Z', }, - { category: 'signal', field: 'signal.rule.exceptions_list', values: [], originalValue: [] }, - { category: 'signal', field: 'signal.depth', values: [1], originalValue: 1 }, + { category: 'kibana', field: ALERT_RULE_EXCEPTIONS_LIST, values: [], originalValue: [] }, + { category: 'kibana', field: ALERT_DEPTH, values: [1], originalValue: 1 }, { - category: 'signal', - field: 'signal.parent.id', + category: 'kibana', + field: ALERT_ANCESTORS_ID, values: ['688MAHYB7WTwW_Glsi_d'], originalValue: '688MAHYB7WTwW_Glsi_d', }, - { category: 'signal', field: 'signal.parent.type', values: ['event'], originalValue: 'event' }, + { category: 'kibana', field: ALERT_ANCESTORS_TYPE, values: ['event'], originalValue: 'event' }, { - category: 'signal', - field: 'signal.parent.index', + category: 'kibana', + field: ALERT_ANCESTORS_INDEX, values: ['winlogbeat-7.10.0-2020.11.12-000001'], originalValue: 'winlogbeat-7.10.0-2020.11.12-000001', }, - { category: 'signal', field: 'signal.parent.depth', values: [0], originalValue: 0 }, + { category: 'kibana', field: ALERT_ANCESTORS_DEPTH, values: [0], originalValue: 0 }, { - category: 'signal', - field: 'signal.original_time', + category: 'kibana', + field: ALERT_ORIGINAL_TIME, values: ['2020-11-25T15:36:38.847Z'], originalValue: '2020-11-25T15:36:38.847Z', }, { - category: 'signal', - field: 'signal.original_event.ingested', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_INGESTED, values: ['2020-11-25T15:36:40.924914552Z'], originalValue: '2020-11-25T15:36:40.924914552Z', }, - { category: 'signal', field: 'signal.original_event.code', values: [4625], originalValue: 4625 }, + { category: 'kibana', field: ALERT_ORIGINAL_EVENT_CODE, values: [4625], originalValue: 4625 }, { category: 'signal', field: 'signal.original_event.lag.total', @@ -536,50 +567,50 @@ export const mockAlertDetailsData = [ originalValue: 1002, }, { - category: 'signal', - field: 'signal.original_event.provider', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_PROVIDER, values: ['Microsoft-Windows-Security-Auditing'], originalValue: 'Microsoft-Windows-Security-Auditing', }, { - category: 'signal', - field: 'signal.original_event.created', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_CREATED, values: ['2020-11-25T15:36:39.922Z'], originalValue: '2020-11-25T15:36:39.922Z', }, { - category: 'signal', - field: 'signal.original_event.kind', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_KIND, values: ['event'], originalValue: 'event', }, { - category: 'signal', - field: 'signal.original_event.module', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_MODULE, values: ['security'], originalValue: 'security', }, { - category: 'signal', - field: 'signal.original_event.action', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_ACTION, values: ['logon-failed'], originalValue: 'logon-failed', }, { - category: 'signal', - field: 'signal.original_event.type', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_TYPE, values: ['start'], originalValue: 'start', }, { - category: 'signal', - field: 'signal.original_event.category', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_CATEGORY, values: ['authentication'], originalValue: 'authentication', }, { - category: 'signal', - field: 'signal.original_event.outcome', + category: 'kibana', + field: ALERT_ORIGINAL_EVENT_OUTCOME, values: ['failure'], originalValue: 'failure', }, diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap index f11150908375f6..a045bf3f5163c1 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap @@ -157,7 +157,7 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1`

- You are in a dialog, containing options for field signal.status. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.workflow_status. Press tab to navigate options. Press escape to exit.

@@ -289,7 +289,7 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1`

- You are in a dialog, containing options for field signal.rule.name. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.rule.name. Press tab to navigate options. Press escape to exit.

@@ -353,7 +353,7 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1`

- You are in a dialog, containing options for field signal.rule.severity. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.severity. Press tab to navigate options. Press escape to exit.

@@ -417,7 +417,7 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1`

- You are in a dialog, containing options for field signal.rule.risk_score. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.risk_score. Press tab to navigate options. Press escape to exit.

@@ -962,7 +962,7 @@ exports[`AlertSummaryView Memory event code renders additional summary rows 1`]

- You are in a dialog, containing options for field signal.status. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.workflow_status. Press tab to navigate options. Press escape to exit.

@@ -1094,7 +1094,7 @@ exports[`AlertSummaryView Memory event code renders additional summary rows 1`]

- You are in a dialog, containing options for field signal.rule.name. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.rule.name. Press tab to navigate options. Press escape to exit.

@@ -1158,7 +1158,7 @@ exports[`AlertSummaryView Memory event code renders additional summary rows 1`]

- You are in a dialog, containing options for field signal.rule.severity. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.severity. Press tab to navigate options. Press escape to exit.

@@ -1222,7 +1222,7 @@ exports[`AlertSummaryView Memory event code renders additional summary rows 1`]

- You are in a dialog, containing options for field signal.rule.risk_score. Press tab to navigate options. Press escape to exit. + You are in a dialog, containing options for field kibana.alert.risk_score. Press tab to navigate options. Press escape to exit.

diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx index 03c420914d1704..f71c6295b95e6b 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx @@ -10,6 +10,13 @@ import { get, getOr, find, isEmpty } from 'lodash/fp'; import React, { useMemo } from 'react'; import styled from 'styled-components'; +import { + ALERT_RULE_UUID, + ALERT_RULE_NAME, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; import * as i18n from './translations'; import { BrowserFields } from '../../../../common/search_strategy/index_fields'; import { @@ -28,7 +35,6 @@ import { import { AGENT_STATUS_FIELD_NAME, IP_FIELD_TYPE, - SIGNAL_RULE_NAME_FIELD_NAME, } from '../../../timelines/components/timeline/body/renderers/constants'; import { DESTINATION_IP_FIELD_NAME, SOURCE_IP_FIELD_NAME } from '../../../network/components/ip'; import { SummaryView } from './summary_view'; @@ -41,6 +47,11 @@ import { getEmptyValue } from '../empty_value'; import { ActionCell } from './table/action_cell'; import { FieldValueCell } from './table/field_value_cell'; import { TimelineEventsDetailsItem } from '../../../../common'; +import { + ALERT_THRESHOLD_RESULT_COUNT, + ALERT_THRESHOLD_RESULT_TERMS, + ALERT_THRESHOLD_RESULT_CARDINALITY, +} from '../../../../../timelines/common/alerts'; import { EventCode } from '../../../../common/ecs/event'; export const Indent = styled.div` @@ -61,23 +72,23 @@ interface EventSummaryField { } const defaultDisplayFields: EventSummaryField[] = [ - { id: 'signal.status', label: SIGNAL_STATUS }, + { id: ALERT_WORKFLOW_STATUS, label: SIGNAL_STATUS }, { id: '@timestamp', label: TIMESTAMP }, { - id: SIGNAL_RULE_NAME_FIELD_NAME, - linkField: 'signal.rule.id', + id: ALERT_RULE_NAME, + linkField: ALERT_RULE_UUID, label: ALERTS_HEADERS_RULE, }, - { id: 'signal.rule.severity', label: ALERTS_HEADERS_SEVERITY }, - { id: 'signal.rule.risk_score', label: ALERTS_HEADERS_RISK_SCORE }, + { id: ALERT_SEVERITY, label: ALERTS_HEADERS_SEVERITY }, + { id: ALERT_RISK_SCORE, label: ALERTS_HEADERS_RISK_SCORE }, { id: 'host.name' }, { id: 'agent.id', overrideField: AGENT_STATUS_FIELD_NAME, label: i18n.AGENT_STATUS }, { id: 'user.name' }, { id: SOURCE_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, { id: DESTINATION_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, - { id: 'signal.threshold_result.count', label: ALERTS_HEADERS_THRESHOLD_COUNT }, - { id: 'signal.threshold_result.terms', label: ALERTS_HEADERS_THRESHOLD_TERMS }, - { id: 'signal.threshold_result.cardinality', label: ALERTS_HEADERS_THRESHOLD_CARDINALITY }, + { id: ALERT_THRESHOLD_RESULT_COUNT, label: ALERTS_HEADERS_THRESHOLD_COUNT }, + { id: ALERT_THRESHOLD_RESULT_TERMS, label: ALERTS_HEADERS_THRESHOLD_TERMS }, + { id: ALERT_THRESHOLD_RESULT_CARDINALITY, label: ALERTS_HEADERS_THRESHOLD_CARDINALITY }, ]; const processCategoryFields: EventSummaryField[] = [ @@ -248,7 +259,7 @@ export const getSummaryRows = ({ return acc; } - if (item.id === 'signal.threshold_result.terms') { + if (item.id === ALERT_THRESHOLD_RESULT_TERMS) { try { const terms = getOr(null, 'originalValue', field); const parsedValue = terms.map((term: string) => JSON.parse(term)); @@ -269,7 +280,7 @@ export const getSummaryRows = ({ } } - if (item.id === 'signal.threshold_result.cardinality') { + if (item.id === ALERT_THRESHOLD_RESULT_CARDINALITY) { try { const parsedValue = JSON.parse(value); return [ @@ -315,7 +326,7 @@ const AlertSummaryViewComponent: React.FC<{ ]); const ruleId = useMemo(() => { - const item = data.find((d) => d.field === 'signal.rule.id'); + const item = data.find((d) => d.field === ALERT_RULE_UUID); return Array.isArray(item?.originalValue) ? item?.originalValue[0] : item?.originalValue ?? null; diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/reason.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/reason.tsx index aab0e866817838..6502d7709f37ab 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/reason.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/reason.tsx @@ -9,6 +9,7 @@ import { EuiTextColor, EuiFlexItem, EuiSpacer, EuiHorizontalRule, EuiTitle } fro import React, { useMemo } from 'react'; import styled from 'styled-components'; +import { ALERT_REASON, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { getRuleDetailsUrl, useFormatUrl } from '../link_to'; import * as i18n from './translations'; import { TimelineEventsDetailsItem } from '../../../../common'; @@ -33,13 +34,12 @@ export const ReasonComponent: React.FC = ({ eventId, data }) => { const { navigateToApp } = useKibana().services.application; const { formatUrl } = useFormatUrl(SecurityPageName.rules); - const reason = useMemo( - () => getFieldValue({ category: 'signal', field: 'signal.reason' }, data), - [data] - ); + const reason = useMemo(() => getFieldValue({ category: 'kibana', field: ALERT_REASON }, data), [ + data, + ]); const ruleId = useMemo( - () => getFieldValue({ category: 'signal', field: 'signal.rule.id' }, data), + () => getFieldValue({ category: 'kibana', field: ALERT_RULE_UUID }, data), [data] ); diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts b/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts index 76ca5dfe53f4e9..705641b8fd6ec2 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts +++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/use_action_cell_data_provider.ts @@ -10,6 +10,7 @@ import { escapeDataProviderId } from '@kbn/securitysolution-t-grid'; import { isArray, isEmpty, isString } from 'lodash/fp'; import { useMemo } from 'react'; +import { ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { AGENT_STATUS_FIELD_NAME, EVENT_MODULE_FIELD_NAME, @@ -20,8 +21,6 @@ import { MESSAGE_FIELD_NAME, REFERENCE_URL_FIELD_NAME, RULE_REFERENCE_FIELD_NAME, - SIGNAL_RULE_NAME_FIELD_NAME, - SIGNAL_STATUS_FIELD_NAME, } from '../../../../timelines/components/timeline/body/renderers/constants'; import { BYTES_FORMAT } from '../../../../timelines/components/timeline/body/renderers/bytes'; import { EVENT_DURATION_FIELD_NAME } from '../../../../timelines/components/duration'; @@ -112,11 +111,11 @@ export const useActionCellDataProvider = ({ id = `event-details-value-default-draggable-${appendedUniqueId}`; } else if (fieldFormat === BYTES_FORMAT) { id = `bytes-default-draggable-${appendedUniqueId}`; - } else if (field === SIGNAL_RULE_NAME_FIELD_NAME) { + } else if (field === ALERT_RULE_NAME) { id = `event-details-value-default-draggable-${appendedUniqueId}-${linkValue}`; } else if (field === EVENT_MODULE_FIELD_NAME) { id = `event-details-value-default-draggable-${appendedUniqueId}-${value}`; - } else if (field === SIGNAL_STATUS_FIELD_NAME) { + } else if (field === ALERT_WORKFLOW_STATUS) { id = `alert-details-value-default-draggable-${appendedUniqueId}`; } else if (field === AGENT_STATUS_FIELD_NAME) { const valueToUse = typeof value === 'string' ? value : ''; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx index 9d4626fba313f8..72a0b999e6ceec 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx @@ -171,8 +171,8 @@ export const AddExceptionModal = memo(function AddExceptionModal({ onConfirm(shouldCloseAlert, shouldBulkCloseAlert); if (conflicts > 0) { addWarning({ - title: i18nCommon.UPDATE_ALERT_STATUS_FAILED(conflicts), - text: i18nCommon.UPDATE_ALERT_STATUS_FAILED_DETAILED(updated, conflicts), + title: i18nCommon.UPDATE_ALERT_WORKFLOW_STATUS_FAILED(conflicts), + text: i18nCommon.UPDATE_ALERT_WORKFLOW_STATUS_FAILED_DETAILED(updated, conflicts), }); } }, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx index 209d7d8fa273b9..9743de9373c30a 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx @@ -43,6 +43,10 @@ import { fields } from '../../../../../../../src/plugins/data/common/index_patte import { ENTRIES, OLD_DATE_RELATIVE_TO_DATE_NOW } from '../../../../../lists/common/constants.mock'; import { CodeSignature } from '../../../../common/ecs/file'; import { IndexPatternBase } from '@kbn/es-query'; +import { + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, +} from '../../../../../timelines/common/alerts'; jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('123'), @@ -432,7 +436,7 @@ describe('Exception helpers', () => { entries: [ { ...getEntryMatchMock(), - field: 'signal.original_event.kind', + field: ALERT_ORIGINAL_EVENT_KIND, }, getEntryMatchMock(), ], @@ -442,7 +446,7 @@ describe('Exception helpers', () => { entries: [ { ...getEntryMatchMock(), - field: 'signal.original_event.module', + field: ALERT_ORIGINAL_EVENT_MODULE, }, ], }, @@ -1183,7 +1187,7 @@ describe('Exception helpers', () => { const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', { _id: '123', rule: { - id: '123', + uuid: '123', }, process: { command_line: 'command_line', @@ -1370,7 +1374,7 @@ describe('Exception helpers', () => { const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', { _id: '123', rule: { - id: '123', + uuid: '123', }, process: { // command_line: 'command_line', intentionally left commented diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx index 58da977fcb8f0a..df1c28d1677d27 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx @@ -44,6 +44,7 @@ import exceptionableLinuxFields from './exceptionable_linux_fields.json'; import exceptionableWindowsMacFields from './exceptionable_windows_mac_fields.json'; import exceptionableEndpointFields from './exceptionable_endpoint_fields.json'; import exceptionableEndpointEventFields from './exceptionable_endpoint_event_fields.json'; +import { ALERT_ORIGINAL_EVENT } from '../../../../../timelines/common/alerts'; export const filterIndexPatterns = ( patterns: IndexPatternBase, @@ -131,7 +132,7 @@ export const formatExceptionItemForUpdate = ( }; /** - * Maps "event." fields to "signal.original_event.". This is because when a rule is created + * Maps "event." fields to "kibana.alert.original_event.". This is because when a rule is created * the "event" field is copied over to "original_event". When the user creates an exception, * they expect it to match against the original_event's fields, not the signal event's. * @param exceptionItems new or existing ExceptionItem[] @@ -145,7 +146,7 @@ export const prepareExceptionItemsForBulkClose = ( return { ...itemEntry, field: itemEntry.field.startsWith('event.') - ? itemEntry.field.replace(/^event./, 'signal.original_event.') + ? itemEntry.field.replace(/^event./, `${ALERT_ORIGINAL_EVENT}.`) : itemEntry.field, }; }); @@ -636,7 +637,7 @@ export const getPrepopulatedBehaviorException = ({ field: 'rule.id', operator: 'included' as const, type: 'match' as const, - value: alertEcsData.rule?.id ?? '', + value: alertEcsData.rule?.uuid ?? '', }, { field: 'process.executable.caseless', diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx index 345f79521aa990..aeb672c3fd2e23 100644 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx @@ -6,6 +6,7 @@ */ import { useRef } from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; +import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { useHoverActionItems, UseHoverActionItemsProps } from './use_hover_action_items'; import { useDeepEqualSelector } from '../../hooks/use_selector'; import { DataProvider } from '../../../../common/types/timeline'; @@ -20,7 +21,7 @@ describe('useHoverActionItems', () => { const defaultProps: UseHoverActionItemsProps = ({ dataProvider: [{} as DataProvider], defaultFocusedButtonRef: null, - field: 'signal.rule.name', + field: ALERT_RULE_NAME, handleHoverActionClicked: jest.fn(), hideTopN: false, isCaseView: false, @@ -97,7 +98,7 @@ describe('useHoverActionItems', () => { 'hover-actions-filter-out' ); expect(result.current.overflowActionItems[2].props['data-test-subj']).toEqual( - 'more-actions-signal.rule.name' + `more-actions-${ALERT_RULE_NAME}` ); expect(result.current.overflowActionItems[2].props.items[0].props['data-test-subj']).toEqual( 'hover-actions-toggle-column' diff --git a/x-pack/plugins/security_solution/public/common/mock/mock_detection_alerts.ts b/x-pack/plugins/security_solution/public/common/mock/mock_detection_alerts.ts index cfa73da6368cda..ec9dbe894c322b 100644 --- a/x-pack/plugins/security_solution/public/common/mock/mock_detection_alerts.ts +++ b/x-pack/plugins/security_solution/public/common/mock/mock_detection_alerts.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { Ecs } from '../../../common/ecs'; import { TimelineNonEcsData } from '../../../common/search_strategy'; @@ -38,38 +39,41 @@ export const mockEcsDataWithAlert: Ecs = { region_name: ['xx'], country_iso_code: ['xx'], }, - signal: { - rule: { - created_at: ['2020-01-10T21:11:45.839Z'], - updated_at: ['2020-01-10T21:11:45.839Z'], - created_by: ['elastic'], - description: ['24/7'], - enabled: [true], - false_positives: ['test-1'], - filters: [], - from: ['now-300s'], - id: ['b5ba41ab-aaf3-4f43-971b-bdf9434ce0ea'], - immutable: [false], - index: ['auditbeat-*'], - interval: ['5m'], - rule_id: ['rule-id-1'], - language: ['kuery'], - output_index: ['.siem-signals-default'], - max_signals: [100], + kibana: { + alert: { risk_score: ['21'], - query: ['user.name: root or user.name: admin'], - references: ['www.test.co'], - saved_id: ["Garrett's IP"], - timeline_id: ['1234-2136-11ea-9864-ebc8cc1cb8c2'], - timeline_title: ['Untitled timeline'], severity: ['low'], - updated_by: ['elastic'], - tags: [], - to: ['now'], - type: ['saved_query'], - threat: [], - note: ['# this is some markdown documentation'], - version: ['1'], + rule: { + created_at: ['2020-01-10T21:11:45.839Z'], + updated_at: ['2020-01-10T21:11:45.839Z'], + created_by: ['elastic'], + description: ['24/7'], + enabled: [true], + false_positives: ['test-1'], + filters: [], + from: ['now-300s'], + immutable: [false], + index: ['auditbeat-*'], + interval: ['5m'], + rule_id: ['rule-id-1'], + language: ['kuery'], + output_index: ['.siem-signals-default'], + max_signals: [100], + risk_score: ['21'], + query: ['user.name: root or user.name: admin'], + references: ['www.test.co'], + saved_id: ["Garrett's IP"], + timeline_id: ['1234-2136-11ea-9864-ebc8cc1cb8c2'], + timeline_title: ['Untitled timeline'], + severity: ['low'], + updated_by: ['elastic'], + tags: [], + to: ['now'], + type: ['saved_query'], + threat: [], + note: ['# this is some markdown documentation'], + version: ['1'], + }, }, }, }; @@ -81,12 +85,15 @@ export const getDetectionAlertMock = (overrides: Partial = {}): Ecs => ({ export const getThreatMatchDetectionAlert = (overrides: Partial = {}): Ecs => ({ ...mockEcsDataWithAlert, - signal: { - ...mockEcsDataWithAlert.signal, - rule: { - ...mockEcsDataWithAlert.rule, - name: ['mock threat_match rule'], - type: ['threat_match'], + kibana: { + ...mockEcsDataWithAlert.kibana, + alert: { + ...mockEcsDataWithAlert.kibana?.alert, + rule: { + ...mockEcsDataWithAlert.kibana?.alert?.rule, + name: ['mock threat_match rule'], + type: ['threat_match'], + }, }, }, threat: { @@ -107,6 +114,6 @@ export const getDetectionAlertFieldsMock = ( fields: TimelineNonEcsData[] = [] ): TimelineNonEcsData[] => [ { field: '@timestamp', value: ['2021-03-27T06:28:47.292Z'] }, - { field: 'signal.rule.type', value: ['threat_match'] }, + { field: ALERT_RULE_TYPE, value: ['threat_match'] }, ...fields, ]; diff --git a/x-pack/plugins/security_solution/public/common/translations.ts b/x-pack/plugins/security_solution/public/common/translations.ts index 1eefd69d57eb73..066e19dfd69a35 100644 --- a/x-pack/plugins/security_solution/public/common/translations.ts +++ b/x-pack/plugins/security_solution/public/common/translations.ts @@ -63,14 +63,14 @@ export const EMPTY_ACTION_ENDPOINT_DESCRIPTION = i18n.translate( } ); -export const UPDATE_ALERT_STATUS_FAILED = (conflicts: number) => +export const UPDATE_ALERT_WORKFLOW_STATUS_FAILED = (conflicts: number) => i18n.translate('xpack.securitySolution.pages.common.updateAlertStatusFailed', { values: { conflicts }, defaultMessage: 'Failed to update { conflicts } {conflicts, plural, =1 {alert} other {alerts}}.', }); -export const UPDATE_ALERT_STATUS_FAILED_DETAILED = (updated: number, conflicts: number) => +export const UPDATE_ALERT_WORKFLOW_STATUS_FAILED_DETAILED = (updated: number, conflicts: number) => i18n.translate('xpack.securitySolution.pages.common.updateAlertStatusFailedDetailed', { values: { updated, conflicts }, defaultMessage: `{ updated } {updated, plural, =1 {alert was} other {alerts were}} updated successfully, but { conflicts } failed to update diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts index d0a03d62a682be..1ccc93c594a341 100644 --- a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts +++ b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts @@ -5,7 +5,12 @@ * 2.0. */ +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import _ from 'lodash'; +import { + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, +} from '../../../../timelines/common'; import { Ecs } from '../../../common/ecs'; import { generateMockDetailItemData } from '../mock'; import { isAlertFromEndpointAlert, isAlertFromEndpointEvent } from './endpoint_alert_check'; @@ -22,8 +27,8 @@ describe('isAlertFromEndpointEvent', () => { mockDetailItemData.push( // Must be an Alert { - field: 'signal.rule.id', - category: 'signal', + field: ALERT_RULE_UUID, + category: 'kibana', originalValue: 'endpoint', values: ['endpoint'], isObjectArray: false, @@ -43,7 +48,7 @@ describe('isAlertFromEndpointEvent', () => { }); it('should return false if it is not an Alert (ex. maybe an event)', () => { - _.remove(mockDetailItemData, { field: 'signal.rule.id' }); + _.remove(mockDetailItemData, { field: ALERT_RULE_UUID }); expect(isAlertFromEndpointEvent({ data: mockDetailItemData })).toBeFalsy(); }); @@ -57,8 +62,8 @@ describe('isAlertFromEndpointAlert', () => { it('should return true if detections data comes from an endpoint rule', () => { const mockEcsData = { _id: 'mockId', - 'signal.original_event.module': ['endpoint'], - 'signal.original_event.kind': ['alert'], + [ALERT_ORIGINAL_EVENT_MODULE]: ['endpoint'], + [ALERT_ORIGINAL_EVENT_KIND]: ['alert'], } as Ecs; expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBe(true); }); @@ -70,7 +75,7 @@ describe('isAlertFromEndpointAlert', () => { it('should return false if it is not an Alert', () => { const mockEcsData = { _id: 'mockId', - 'signal.original_event.module': ['endpoint'], + [ALERT_ORIGINAL_EVENT_MODULE]: ['endpoint'], } as Ecs; expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBeFalsy(); }); @@ -78,7 +83,7 @@ describe('isAlertFromEndpointAlert', () => { it('should return false if it is not an endpoint module', () => { const mockEcsData = { _id: 'mockId', - 'signal.original_event.kind': ['alert'], + [ALERT_ORIGINAL_EVENT_KIND]: ['alert'], } as Ecs; expect(isAlertFromEndpointAlert({ ecsData: mockEcsData })).toBeFalsy(); }); diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts index 7e7e7a6bcdd1f8..d08ded90191402 100644 --- a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts +++ b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts @@ -5,8 +5,13 @@ * 2.0. */ +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { find, getOr, some } from 'lodash/fp'; -import { TimelineEventsDetailsItem } from '../../../../timelines/common'; +import { + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + TimelineEventsDetailsItem, +} from '../../../../timelines/common'; import { Ecs } from '../../../common/ecs'; /** @@ -19,7 +24,7 @@ export const isAlertFromEndpointEvent = ({ }: { data: TimelineEventsDetailsItem[]; }): boolean => { - const isAlert = some({ category: 'signal', field: 'signal.rule.id' }, data); + const isAlert = some({ category: 'kibana', field: ALERT_RULE_UUID }, data); if (!isAlert) { return false; @@ -38,8 +43,8 @@ export const isAlertFromEndpointAlert = ({ return false; } - const eventModules = getOr([], 'signal.original_event.module', ecsData); - const kinds = getOr([], 'signal.original_event.kind', ecsData); + const eventModules = getOr([], ALERT_ORIGINAL_EVENT_MODULE, ecsData); + const kinds = getOr([], ALERT_ORIGINAL_EVENT_KIND, ecsData); return eventModules.includes('endpoint') && kinds.includes('alert'); }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_info/query.dsl.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_info/query.dsl.ts index 4b8a911bf1cd8c..41a3af7e6bef72 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_info/query.dsl.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_info/query.dsl.ts @@ -5,10 +5,12 @@ * 2.0. */ +import { ALERT_RULE_UUID, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; + export const buildLastAlertsQuery = (ruleId: string | undefined | null) => { const queryFilter = [ { - bool: { should: [{ match: { 'signal.status': 'open' } }], minimum_should_match: 1 }, + bool: { should: [{ match: { [ALERT_WORKFLOW_STATUS]: 'open' } }], minimum_should_match: 1 }, }, ]; @@ -24,7 +26,7 @@ export const buildLastAlertsQuery = (ruleId: string | undefined | null) => { ...queryFilter, { bool: { - should: [{ match: { 'signal.rule.id': ruleId } }], + should: [{ match: { [ALERT_RULE_UUID]: ruleId } }], minimum_should_match: 1, }, }, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx index 484cd66575005b..c3ea4586e233c2 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { waitFor, act } from '@testing-library/react'; import { mount } from 'enzyme'; +import { ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { esQuery, Filter } from '../../../../../../../../src/plugins/data/public'; import { TestProviders } from '../../../../common/mock'; import { SecurityPageName } from '../../../../app/types'; @@ -170,7 +171,7 @@ describe('AlertsHistogramPanel', () => { await waitFor(() => { expect(mockGetAlertsHistogramQuery.mock.calls[0]).toEqual([ - 'signal.rule.name', + ALERT_RULE_NAME, '2020-07-07T08:20:18.966Z', '2020-07-08T08:20:18.966Z', [ @@ -196,7 +197,7 @@ describe('AlertsHistogramPanel', () => { meta: { alias: null, disabled: false, - key: 'signal.status', + key: ALERT_WORKFLOW_STATUS, negate: false, params: { query: 'open', @@ -205,7 +206,7 @@ describe('AlertsHistogramPanel', () => { }, query: { term: { - 'signal.status': 'open', + [ALERT_WORKFLOW_STATUS]: 'open', }, }, }; @@ -223,13 +224,13 @@ describe('AlertsHistogramPanel', () => { await waitFor(() => { expect(mockGetAlertsHistogramQuery.mock.calls[1]).toEqual([ - 'signal.rule.name', + ALERT_RULE_NAME, '2020-07-07T08:20:18.966Z', '2020-07-08T08:20:18.966Z', [ { bool: { - filter: [{ term: { 'signal.status': 'open' } }], + filter: [{ term: { [ALERT_WORKFLOW_STATUS]: 'open' } }], must: [], must_not: [], should: [], diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/config.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/config.ts index cb5a23e7119742..0f3062d5fec203 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/config.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/config.ts @@ -5,23 +5,30 @@ * 2.0. */ +import { + ALERT_RULE_NAME, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_RULE_TYPE, +} from '@kbn/rule-data-utils'; import type { AlertsStackByOption } from './types'; +import { ALERT_RULE_THREAT_TACTIC_NAME } from '../../../../../../timelines/common/alerts'; export const alertsStackByOptions: AlertsStackByOption[] = [ - { text: 'signal.rule.risk_score', value: 'signal.rule.risk_score' }, - { text: 'signal.rule.severity', value: 'signal.rule.severity' }, - { text: 'signal.rule.threat.tactic.name', value: 'signal.rule.threat.tactic.name' }, + { text: ALERT_RISK_SCORE, value: ALERT_RISK_SCORE }, + { text: ALERT_SEVERITY, value: ALERT_SEVERITY }, + { text: ALERT_RULE_THREAT_TACTIC_NAME, value: ALERT_RULE_THREAT_TACTIC_NAME }, { text: 'destination.ip', value: 'destination.ip' }, { text: 'event.action', value: 'event.action' }, { text: 'event.category', value: 'event.category' }, { text: 'host.name', value: 'host.name' }, - { text: 'signal.rule.type', value: 'signal.rule.type' }, - { text: 'signal.rule.name', value: 'signal.rule.name' }, + { text: ALERT_RULE_TYPE, value: ALERT_RULE_TYPE }, + { text: ALERT_RULE_NAME, value: ALERT_RULE_NAME }, { text: 'source.ip', value: 'source.ip' }, { text: 'user.name', value: 'user.name' }, ]; -export const DEFAULT_STACK_BY_FIELD = 'signal.rule.name'; +export const DEFAULT_STACK_BY_FIELD = ALERT_RULE_NAME; export const PANEL_HEIGHT = 300; export const MOBILE_PANEL_HEIGHT = 500; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/types.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/types.ts index 833c05bfc7a79b..615fc53a8dfc3a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/types.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/types.ts @@ -5,20 +5,28 @@ * 2.0. */ +import { + ALERT_RULE_NAME, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_RULE_TYPE, +} from '@kbn/rule-data-utils'; +import { ALERT_RULE_THREAT_TACTIC_NAME } from '../../../../../../timelines/common/alerts'; + export interface AlertsStackByOption { text: AlertsStackByField; value: AlertsStackByField; } export type AlertsStackByField = - | 'signal.rule.risk_score' - | 'signal.rule.severity' - | 'signal.rule.threat.tactic.name' + | typeof ALERT_RISK_SCORE + | typeof ALERT_SEVERITY + | typeof ALERT_RULE_THREAT_TACTIC_NAME | 'destination.ip' | 'event.action' | 'event.category' | 'host.name' - | 'signal.rule.type' - | 'signal.rule.name' + | typeof ALERT_RULE_TYPE + | typeof ALERT_RULE_NAME | 'source.ip' | 'user.name'; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx index e7a8ba91cff8f3..0784cb0a12c67f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.test.tsx @@ -27,6 +27,7 @@ import { ISearchStart } from '../../../../../../../src/plugins/data/public'; import { dataPluginMock } from '../../../../../../../src/plugins/data/public/mocks'; import { getTimelineTemplate } from '../../../timelines/containers/api'; import { defaultHeaders } from '../../../timelines/components/timeline/body/column_headers/default_headers'; +import { ALERT_GROUP_ID } from '../../../../../timelines/common/alerts'; jest.mock('../../../timelines/containers/api', () => ({ getTimelineTemplate: jest.fn(), @@ -288,11 +289,13 @@ describe('alert actions', () => { test('it invokes createTimeline with timelineDefaults', async () => { const ecsDataMock: Ecs = { ...mockEcsDataWithAlert, - signal: { - rule: { - ...mockEcsDataWithAlert.signal?.rule!, - // @ts-expect-error - timeline_id: null, + kibana: { + alert: { + rule: { + ...mockEcsDataWithAlert.kibana?.alert?.rule!, + // @ts-expect-error + timeline_id: null, + }, }, }, }; @@ -315,10 +318,12 @@ describe('alert actions', () => { test('it invokes createTimeline with timelineDefaults', async () => { const ecsDataMock: Ecs = { ...mockEcsDataWithAlert, - signal: { - rule: { - ...mockEcsDataWithAlert.signal?.rule!, - timeline_id: [''], + kibana: { + alert: { + rule: { + ...mockEcsDataWithAlert.kibana?.alert?.rule!, + timeline_id: [''], + }, }, }, }; @@ -338,17 +343,19 @@ describe('alert actions', () => { }); describe('Eql', () => { - test(' with signal.group.id', async () => { + test(`with ${ALERT_GROUP_ID}`, async () => { const ecsDataMock: Ecs = { ...mockEcsDataWithAlert, - signal: { - rule: { - ...mockEcsDataWithAlert.signal?.rule!, - type: ['eql'], - timeline_id: [''], - }, - group: { - id: ['my-group-id'], + kibana: { + alert: { + rule: { + ...mockEcsDataWithAlert.kibana?.alert?.rule!, + type: ['eql'], + timeline_id: [''], + }, + group: { + id: ['my-group-id'], + }, }, }, }; @@ -376,21 +383,23 @@ describe('alert actions', () => { 'send-alert-to-timeline-action-default-draggable-event-details-value-formatted-field-value-timeline-1-alert-id-my-group-id', kqlQuery: '', name: '1', - queryMatch: { field: 'signal.group.id', operator: ':', value: 'my-group-id' }, + queryMatch: { field: ALERT_GROUP_ID, operator: ':', value: 'my-group-id' }, }, ], }, }); }); - test(' with NO signal.group.id', async () => { + test(`with NO ${ALERT_GROUP_ID}`, async () => { const ecsDataMock: Ecs = { ...mockEcsDataWithAlert, - signal: { - rule: { - ...mockEcsDataWithAlert.signal?.rule!, - type: ['eql'], - timeline_id: [''], + kibana: { + alert: { + rule: { + ...mockEcsDataWithAlert.kibana?.alert?.rule!, + type: ['eql'], + timeline_id: [''], + }, }, }, }; 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 d48bc95f5d480a..8a90ae7dfb12eb 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 @@ -50,6 +50,11 @@ import { QueryOperator, } from '../../../timelines/components/timeline/data_providers/data_provider'; import { getTimelineTemplate } from '../../../timelines/containers/api'; +import { + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_RULE_FILTERS, +} from '../../../../../timelines/common/alerts'; export const getUpdateAlertsQuery = (eventIds: Readonly) => { return { @@ -68,10 +73,10 @@ 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 === 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 === ALERT_ORIGINAL_TIME)?.[0]?.value ?? []) .map((d) => moment(d)); return [stringFilter, moment.min(eventTimes).valueOf(), moment.max(eventTimes).valueOf()]; @@ -136,7 +141,9 @@ export const determineToAndFrom = ({ ecs }: { ecs: Ecs[] | Ecs }) => { const ecsData = ecs as Ecs; const elapsedTimeRule = moment.duration( moment().diff( - dateMath.parse(ecsData?.signal?.rule?.from != null ? ecsData.signal?.rule?.from[0] : 'now-0s') + dateMath.parse( + ecsData?.kibana?.alert?.rule?.from != null ? ecsData.kibana?.alert?.rule?.from[0] : 'now-0s' + ) ) ); const from = moment(ecsData?.timestamp ?? new Date()) @@ -164,7 +171,7 @@ export const getThresholdAggregationData = ( const thresholdEcsData: Ecs[] = Array.isArray(ecsData) ? ecsData : [ecsData]; return thresholdEcsData.reduce( (outerAcc, thresholdData) => { - const threshold = thresholdData.signal?.rule?.threshold as string[]; + const threshold = thresholdData.kibana?.alert?.rule?.threshold as string[]; let aggField: string[] = []; let thresholdResult: { @@ -177,24 +184,26 @@ export const getThresholdAggregationData = ( }; try { - thresholdResult = JSON.parse((thresholdData.signal?.threshold_result as string[])[0]); + thresholdResult = JSON.parse( + (thresholdData.kibana?.alert?.threshold_result as string[])[0] + ); aggField = JSON.parse(threshold[0]).field; } catch (err) { thresholdResult = { terms: [ { field: (thresholdData.rule?.threshold as { field: string }).field, - value: (thresholdData.signal?.threshold_result as { value: string }).value, + value: (thresholdData.kibana?.alert?.threshold_result as { value: string }).value, }, ], - count: (thresholdData.signal?.threshold_result as { count: number }).count, - from: (thresholdData.signal?.threshold_result as { from: string }).from, + count: (thresholdData.kibana?.alert?.threshold_result as { count: number }).count, + from: (thresholdData.kibana?.alert?.threshold_result as { from: string }).from, }; } - const originalTime = moment(thresholdData.signal?.original_time![0]); + const originalTime = moment(thresholdData.kibana?.alert?.original_time![0]); const now = moment(); - const ruleFrom = dateMath.parse(thresholdData.signal?.rule?.from![0]!); + const ruleFrom = dateMath.parse(thresholdData.kibana?.alert?.rule?.from![0]!); const ruleInterval = moment.duration(now.diff(ruleFrom)); const fromOriginalTime = originalTime.clone().subtract(ruleInterval); // This is the default... can overshoot const aggregationFields = Array.isArray(aggField) ? aggField : [aggField]; @@ -254,15 +263,15 @@ export const getThresholdAggregationData = ( }; export const isEqlRuleWithGroupId = (ecsData: Ecs) => - ecsData.signal?.rule?.type?.length && - ecsData.signal?.rule?.type[0] === 'eql' && - ecsData.signal?.group?.id?.length; + ecsData.kibana?.alert?.rule?.type?.length && + ecsData.kibana?.alert?.rule?.type[0] === 'eql' && + ecsData.kibana?.alert?.group?.id?.length; export const isThresholdRule = (ecsData: Ecs) => - ecsData.signal?.rule?.type?.length && ecsData.signal?.rule?.type[0] === 'threshold'; + ecsData.kibana?.alert?.rule?.type?.length && ecsData.kibana?.alert?.rule?.type[0] === 'threshold'; export const buildAlertsKqlFilter = ( - key: '_id' | 'signal.group.id', + key: '_id' | typeof ALERT_GROUP_ID, alertIds: string[] ): Filter[] => { return [ @@ -330,10 +339,10 @@ export const buildEqlDataProviderOrFilter = ( return { dataProviders: [], filters: buildAlertsKqlFilter( - 'signal.group.id', + ALERT_GROUP_ID, ecs.reduce((acc, ecsData) => { - const signalGroupId = ecsData.signal?.group?.id?.length - ? ecsData.signal?.group?.id[0] + const signalGroupId = ecsData.kibana?.alert?.group?.id?.length + ? ecsData.kibana?.alert?.group?.id[0] : 'unknown-signal-group-id'; if (!acc.includes(signalGroupId)) { return [...acc, signalGroupId]; @@ -343,8 +352,8 @@ export const buildEqlDataProviderOrFilter = ( ), }; } else if (!Array.isArray(ecs)) { - const signalGroupId = ecs.signal?.group?.id?.length - ? ecs.signal?.group?.id[0] + const signalGroupId = ecs.kibana?.alert?.group?.id?.length + ? ecs.kibana?.alert?.group?.id[0] : 'unknown-signal-group-id'; return { dataProviders: [ @@ -356,7 +365,7 @@ export const buildEqlDataProviderOrFilter = ( excluded: false, kqlQuery: '', queryMatch: { - field: 'signal.group.id', + field: ALERT_GROUP_ID, value: signalGroupId, operator: ':' as const, }, @@ -381,9 +390,12 @@ 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 noteContent = + ecsData.kibana?.alert?.rule?.note != null ? ecsData.kibana?.alert?.rule?.note[0] : ''; const timelineId = - ecsData.signal?.rule?.timeline_id != null ? ecsData.signal?.rule?.timeline_id[0] : ''; + ecsData.kibana?.alert?.rule?.timeline_id != null + ? ecsData.kibana?.alert?.rule?.timeline_id[0] + : ''; const { to, from } = determineToAndFrom({ ecs }); // For now we do not want to populate the template timeline if we have alertIds @@ -477,7 +489,7 @@ export const sendAlertToTimelineAction = async ({ timeline: { ...timelineDefaults, description: `_id: ${ecsData._id}`, - filters: getFiltersFromRule(ecsData.signal?.rule?.filters as string[]), + filters: getFiltersFromRule(ecsData.kibana?.alert?.rule?.filters as string[]), dataProviders, id: TimelineId.active, indexNames: [], @@ -489,13 +501,15 @@ export const sendAlertToTimelineAction = async ({ kqlQuery: { filterQuery: { kuery: { - kind: ecsData.signal?.rule?.language?.length - ? (ecsData.signal?.rule?.language[0] as KueryFilterQueryKind) + kind: ecsData.kibana?.alert?.rule?.language?.length + ? (ecsData.kibana?.alert?.rule?.language[0] as KueryFilterQueryKind) : 'kuery', - expression: ecsData.signal?.rule?.query?.length ? ecsData.signal?.rule?.query[0] : '', + expression: ecsData.kibana?.alert?.rule?.query?.length + ? ecsData.kibana?.alert?.rule?.query[0] + : '', }, - serializedQuery: ecsData.signal?.rule?.query?.length - ? ecsData.signal?.rule?.query[0] + serializedQuery: ecsData.kibana?.alert?.rule?.query?.length + ? ecsData.kibana?.alert?.rule?.query[0] : '', }, }, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx index 9c6954a6898a6c..259ab24e9038de 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_UUID, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { ExistsFilter, Filter } from '@kbn/es-query'; import { buildAlertsRuleIdFilter, @@ -25,14 +26,14 @@ describe('alerts default_config', () => { negate: false, disabled: false, type: 'phrase', - key: 'signal.rule.id', + key: ALERT_RULE_UUID, params: { query: 'rule-id-1', }, }, query: { match_phrase: { - 'signal.rule.id': 'rule-id-1', + [ALERT_RULE_UUID]: 'rule-id-1', }, }, }; @@ -73,7 +74,7 @@ describe('alerts default_config', () => { meta: { alias: null, disabled: false, - key: 'signal.status', + key: ALERT_WORKFLOW_STATUS, negate: false, params: { query: 'acknowledged', @@ -85,12 +86,12 @@ describe('alerts default_config', () => { should: [ { term: { - 'signal.status': 'acknowledged', + [ALERT_WORKFLOW_STATUS]: 'acknowledged', }, }, { term: { - 'signal.status': 'in-progress', + [ALERT_WORKFLOW_STATUS]: 'in-progress', }, }, ], @@ -107,7 +108,7 @@ describe('alerts default_config', () => { meta: { alias: null, disabled: false, - key: 'signal.status', + key: ALERT_WORKFLOW_STATUS, negate: false, params: { query: 'open', @@ -116,7 +117,7 @@ describe('alerts default_config', () => { }, query: { term: { - 'signal.status': 'open', + [ALERT_WORKFLOW_STATUS]: 'open', }, }, }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx index 3bc229273bc837..b1c6dccbe9b552 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx @@ -8,23 +8,34 @@ import { ALERT_DURATION, ALERT_INSTANCE_ID, + ALERT_RULE_TO, + ALERT_RULE_TYPE, ALERT_RULE_PRODUCER, ALERT_START, - ALERT_WORKFLOW_STATUS, ALERT_UUID, ALERT_RULE_UUID, ALERT_RULE_NAME, ALERT_RULE_CATEGORY, + ALERT_WORKFLOW_STATUS, } from '@kbn/rule-data-utils'; - import { defaultColumnHeaderType } from '../../../timelines/components/timeline/body/column_headers/default_headers'; import { ColumnHeaderOptions, RowRendererId } from '../../../../common/types/timeline'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; import { Filter } from '../../../../../../../src/plugins/data/common/es_query'; - import { SubsetTimelineModel } from '../../../timelines/store/timeline/model'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; import { columns } from '../../configurations/security_solution_detections/columns'; +import { + ALERT_GROUP_ID, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_TIME, + ALERT_RULE_BUILDING_BLOCK_TYPE, + ALERT_RULE_FILTERS, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, +} from '../../../../../timelines/common/alerts'; export const buildAlertStatusFilter = (status: Status): Filter[] => { const combinedQuery = @@ -34,12 +45,12 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { should: [ { term: { - 'signal.status': status, + [ALERT_WORKFLOW_STATUS]: status, }, }, { term: { - 'signal.status': 'in-progress', + [ALERT_WORKFLOW_STATUS]: 'in-progress', }, }, ], @@ -47,7 +58,7 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { } : { term: { - 'signal.status': status, + [ALERT_WORKFLOW_STATUS]: status, }, }; @@ -58,7 +69,7 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { negate: false, disabled: false, type: 'phrase', - key: 'signal.status', + key: ALERT_WORKFLOW_STATUS, params: { query: status, }, @@ -103,14 +114,14 @@ export const buildAlertsRuleIdFilter = (ruleId: string | null): Filter[] => negate: false, disabled: false, type: 'phrase', - key: 'signal.rule.id', + key: ALERT_RULE_UUID, params: { query: ruleId, }, }, query: { match_phrase: { - 'signal.rule.id': ruleId, + [ALERT_RULE_UUID]: ruleId, }, }, }, @@ -127,11 +138,11 @@ export const buildShowBuildingBlockFilter = (showBuildingBlockAlerts: boolean): negate: true, disabled: false, type: 'exists', - key: 'signal.rule.building_block_type', + key: ALERT_RULE_BUILDING_BLOCK_TYPE, value: 'exists', }, // @ts-expect-error TODO: Rework parent typings to support ExistsFilter[] - exists: { field: 'signal.rule.building_block_type' }, + exists: { field: ALERT_RULE_BUILDING_BLOCK_TYPE }, }, ]; @@ -143,12 +154,12 @@ export const buildThreatMatchFilter = (showOnlyThreatIndicatorAlerts: boolean): alias: null, disabled: false, negate: false, - key: 'signal.rule.threat_mapping', + key: 'signal.rule.threat_mapping', // TODO: Not updating to kibana.alert per: https://github.com/elastic/kibana/pull/107713/files#r692438231 type: 'exists', value: 'exists', }, // @ts-expect-error TODO: Rework parent typings to support ExistsFilter[] - exists: { field: 'signal.rule.threat_mapping' }, + exists: { field: 'signal.rule.threat_mapping' }, // TODO: Not updating to kibana.alert per: https://github.com/elastic/kibana/pull/107713/files#r692438231 }, ] : []; @@ -162,21 +173,20 @@ export const alertsDefaultModel: SubsetTimelineModel = { export const requiredFieldsForActions = [ '@timestamp', - 'signal.status', - 'signal.group.id', - 'signal.original_time', - 'signal.rule.building_block_type', - 'signal.rule.filters', - 'signal.rule.from', - 'signal.rule.language', - 'signal.rule.query', - 'signal.rule.name', - 'signal.rule.to', - 'signal.rule.id', - 'signal.rule.index', - 'signal.rule.type', - 'signal.original_event.kind', - 'signal.original_event.module', + ALERT_WORKFLOW_STATUS, + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_RULE_BUILDING_BLOCK_TYPE, + ALERT_RULE_FILTERS, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_NAME, + ALERT_RULE_TO, + ALERT_RULE_UUID, + ALERT_RULE_INDEX, + ALERT_RULE_TYPE, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, // Endpoint exception fields 'file.path', 'file.Ext.code_signature.subject_name', @@ -265,11 +275,11 @@ export const buildShowBuildingBlockFilterRuleRegistry = ( negate: true, disabled: false, type: 'exists', - key: 'kibana.rule.building_block_type', + key: ALERT_RULE_BUILDING_BLOCK_TYPE, value: 'exists', }, // @ts-expect-error TODO: Rework parent typings to support ExistsFilter[] - exists: { field: 'kibana.rule.building_block_type' }, + exists: { field: ALERT_RULE_BUILDING_BLOCK_TYPE }, }, ]; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index 3c277d1d4019b2..cea29297ce4306 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -159,8 +159,8 @@ export const AlertsTableComponent: React.FC = ({ if (conflicts > 0) { // Partial failure addWarning({ - title: i18nCommon.UPDATE_ALERT_STATUS_FAILED(conflicts), - text: i18nCommon.UPDATE_ALERT_STATUS_FAILED_DETAILED(updated, conflicts), + title: i18nCommon.UPDATE_ALERT_WORKFLOW_STATUS_FAILED(conflicts), + text: i18nCommon.UPDATE_ALERT_WORKFLOW_STATUS_FAILED_DETAILED(updated, conflicts), }); } else { let title = ''; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx index f2297b7d567bca..f088adf16e9031 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/alert_context_menu.tsx @@ -11,7 +11,8 @@ import { EuiButtonIcon, EuiContextMenuPanel, EuiPopover, EuiToolTip } from '@ela import { indexOf } from 'lodash'; import { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types'; -import { get } from 'lodash/fp'; +import { get, getOr } from 'lodash/fp'; +import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { buildGetAlertByIdQuery } from '../../../../common/components/exceptions/helpers'; import { EventsTdContent } from '../../../../timelines/components/timeline/styles'; import { DEFAULT_ICON_BUTTON_WIDTH } from '../../../../timelines/components/timeline/helpers'; @@ -64,8 +65,8 @@ const AlertContextMenuComponent: React.FC = ({ const afterItemSelection = useCallback(() => { setPopover(false); }, []); - const ruleId = get(0, ecsRowData?.signal?.rule?.id); - const ruleName = get(0, ecsRowData?.signal?.rule?.name); + const ruleId = getOr([], ALERT_RULE_UUID, ecsRowData); + const ruleName = getOr([], ALERT_RULE_NAME, ecsRowData); const { timelines: timelinesUi } = useKibana().services; const { addToCaseActionProps, addToCaseActionItems } = useAddToCaseActions({ @@ -75,7 +76,7 @@ const AlertContextMenuComponent: React.FC = ({ ariaLabel: ATTACH_ALERT_TO_CASE_FOR_ROW({ ariaRowindex, columnValues }), }); - const alertStatus = get(0, ecsRowData?.signal?.status) as Status; + const alertStatus = get(0, ecsRowData?.kibana?.alert?.workflow_status) as Status; const isEvent = useMemo(() => indexOf(ecsRowData.event?.kind, 'event') !== -1, [ecsRowData]); @@ -109,7 +110,7 @@ const AlertContextMenuComponent: React.FC = ({ onAddExceptionTypeClick, ruleIndices, } = useExceptionModal({ - ruleIndex: ecsRowData?.signal?.rule?.index, + ruleIndex: ecsRowData?.kibana?.alert?.rule?.index, refetch, timelineId, }); diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/description_step/helpers.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/description_step/helpers.tsx index 17162a2206fc35..1a4a4642d0825b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/description_step/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/description_step/helpers.tsx @@ -23,6 +23,7 @@ import React from 'react'; import styled from 'styled-components'; import { ThreatMapping, Type } from '@kbn/securitysolution-io-ts-alerting-types'; +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { MATCHES, AND, OR } from '../../../../common/components/threat_match/translations'; import { assertUnreachable } from '../../../../../common/utility_types'; import * as i18nSeverity from '../severity_mapping/translations'; @@ -350,7 +351,7 @@ export const buildRiskScoreDescription = (riskScore: AboutStepRiskScore): ListIt - {'signal.rule.risk_score'} + {`${ALERT_RISK_SCORE}`} ), }; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/translations.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/translations.tsx index 5e88b44b9e1920..6d8ea92861df9f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/translations.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/risk_score_mapping/translations.tsx @@ -24,7 +24,7 @@ export const DEFAULT_RISK_SCORE = i18n.translate( export const RISK_SCORE_FIELD = i18n.translate( 'xpack.securitySolution.alerts.riskScoreMapping.riskScoreFieldTitle', { - defaultMessage: 'signal.rule.risk_score', + defaultMessage: 'kibana.alert.rule.risk_score', } ); diff --git a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx index 0432e7d353086d..d97fee889b675a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/take_action_dropdown/index.tsx @@ -8,6 +8,8 @@ import React, { useState, useCallback, useMemo } from 'react'; import { EuiContextMenuPanel, EuiButton, EuiPopover } from '@elastic/eui'; import type { ExceptionListType } from '@kbn/securitysolution-io-ts-list-types'; + +import { ALERT_RULE_UUID, ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash/fp'; import { TimelineEventsDetailsItem } from '../../../../common'; import { TAKE_ACTION } from '../alerts_table/alerts_utility_bar/translations'; @@ -67,9 +69,9 @@ export const TakeActionDropdown = React.memo( const actionsData = useMemo( () => [ - { category: 'signal', field: 'signal.rule.id', name: 'ruleId' }, - { category: 'signal', field: 'signal.rule.name', name: 'ruleName' }, - { category: 'signal', field: 'signal.status', name: 'alertStatus' }, + { category: 'kibana', field: ALERT_RULE_UUID, name: 'ruleId' }, + { category: 'kibana', field: ALERT_RULE_NAME, name: 'ruleName' }, + { category: 'kibana', field: ALERT_WORKFLOW_STATUS, name: 'alertStatus' }, { category: 'event', field: 'event.kind', name: 'eventKind' }, { category: '_id', field: '_id', name: 'eventId' }, ].reduce( diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts index ae9285f85501b0..e4914233209278 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts @@ -6,7 +6,12 @@ */ import { EuiDataGridColumn } from '@elastic/eui'; -import { ALERT_DURATION, ALERT_STATUS } from '@kbn/rule-data-utils'; +import { + ALERT_DURATION, + ALERT_REASON, + ALERT_SEVERITY, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; import { ColumnHeaderOptions } from '../../../../../common'; import { defaultColumnHeaderType } from '../../../../timelines/components/timeline/body/column_headers/default_headers'; @@ -24,7 +29,7 @@ export const columns: Array< { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.STATUS, - id: ALERT_STATUS, + id: ALERT_WORKFLOW_STATUS, initialWidth: 74, }, { @@ -42,12 +47,12 @@ export const columns: Array< { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_SEVERITY, - id: 'signal.rule.severity', + id: ALERT_SEVERITY, initialWidth: 102, }, { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_REASON, - id: 'signal.reason', + id: ALERT_REASON, }, ]; diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.test.tsx b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.test.tsx index a4826445b23cf3..dddb7108f607ec 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.test.tsx @@ -8,9 +8,7 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; - -import { ALERT_DURATION, ALERT_STATUS } from '@kbn/rule-data-utils'; - +import { ALERT_DURATION, ALERT_REASON, ALERT_SEVERITY, ALERT_STATUS } from '@kbn/rule-data-utils'; import { mockBrowserFields } from '../../../../common/containers/source/mock'; import { DragDropContextWrapper } from '../../../../common/components/drag_and_drop/drag_drop_context_wrapper'; import { defaultHeaders, mockTimelineData, TestProviders } from '../../../../common/mock'; @@ -81,7 +79,7 @@ describe('RenderCellValue', () => { const wrapper = mount( - + ); @@ -93,7 +91,7 @@ describe('RenderCellValue', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx index 684680ea2e8523..07581e4c94d3b5 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx @@ -9,7 +9,7 @@ import moment from 'moment'; import React from 'react'; import { EuiDataGridCellValueElementProps, EuiLink } from '@elastic/eui'; -import { ALERT_DURATION, ALERT_STATUS } from '@kbn/rule-data-utils'; +import { ALERT_DURATION, ALERT_REASON, ALERT_SEVERITY, ALERT_STATUS } from '@kbn/rule-data-utils'; import { TruncatableText } from '../../../../common/components/truncatable_text'; import { Severity } from '../../../components/severity'; @@ -55,9 +55,9 @@ export const RenderCellValue: React.FC< ); case ALERT_DURATION: return {moment().fromNow(true)}; - case 'signal.rule.severity': + case ALERT_SEVERITY: return ; - case 'signal.reason': + case ALERT_REASON: return ( {reason} diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts index bf0801f276bdf1..e238d73e3aff58 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts @@ -6,6 +6,12 @@ */ import { EuiDataGridColumn } from '@elastic/eui'; +import { + ALERT_REASON, + ALERT_RULE_UUID, + ALERT_RULE_NAME, + ALERT_SEVERITY, +} from '@kbn/rule-data-utils'; import { ColumnHeaderOptions } from '../../../../../common'; import { defaultColumnHeaderType } from '../../../../timelines/components/timeline/body/column_headers/default_headers'; import { DEFAULT_DATE_COLUMN_MIN_WIDTH } from '../../../../timelines/components/timeline/body/constants'; @@ -26,20 +32,20 @@ export const columns: Array< }, { columnHeaderType: defaultColumnHeaderType, - id: 'signal.rule.name', + id: ALERT_RULE_NAME, displayAsText: i18n.ALERTS_HEADERS_RULE_NAME, - linkField: 'signal.rule.id', + linkField: ALERT_RULE_UUID, initialWidth: 212, }, { columnHeaderType: defaultColumnHeaderType, - id: 'signal.rule.severity', + id: ALERT_SEVERITY, displayAsText: i18n.ALERTS_HEADERS_SEVERITY, initialWidth: 104, }, { columnHeaderType: defaultColumnHeaderType, - id: 'signal.reason', + id: ALERT_REASON, displayAsText: i18n.ALERTS_HEADERS_REASON, }, ]; diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.test.tsx b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.test.tsx index ccd71404a22161..542883796eb0f7 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.test.tsx @@ -9,6 +9,7 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; +import { ALERT_REASON, ALERT_SEVERITY } from '@kbn/rule-data-utils'; import { mockBrowserFields } from '../../../../common/containers/source/mock'; import { DragDropContextWrapper } from '../../../../common/components/drag_and_drop/drag_drop_context_wrapper'; import { defaultHeaders, mockTimelineData, TestProviders } from '../../../../common/mock'; @@ -55,7 +56,7 @@ describe('RenderCellValue', () => { const wrapper = mount( - + ); @@ -67,7 +68,7 @@ describe('RenderCellValue', () => { const wrapper = mount( - + ); diff --git a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.tsx b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.tsx index 879712c85327ec..db83eda337a1f6 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/render_cell_value.tsx @@ -8,6 +8,7 @@ import { EuiDataGridCellValueElementProps } from '@elastic/eui'; import React from 'react'; +import { ALERT_REASON, ALERT_SEVERITY } from '@kbn/rule-data-utils'; import { DefaultDraggable } from '../../../../common/components/draggables'; import { TruncatableText } from '../../../../common/components/truncatable_text'; import { Severity } from '../../../components/severity'; @@ -46,7 +47,7 @@ export const RenderCellValue: React.FC< const draggableId = `${timelineId}-${eventId}-${columnId}-${value}`; switch (columnId) { - case 'signal.rule.severity': + case ALERT_SEVERITY: return ( ); - case 'signal.reason': + case ALERT_REASON: return {reason}; default: return ( diff --git a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts index beeed344c31ef0..3efa81f5b9f53c 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts +++ b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/columns.ts @@ -6,6 +6,15 @@ */ import { EuiDataGridColumn } from '@elastic/eui'; +import { + ALERT_RULE_UUID, + ALERT_RULE_NAME, + ALERT_RISK_SCORE, + ALERT_SEVERITY, + ALERT_RULE_TYPE, + ALERT_RULE_VERSION, + ALERT_REASON, +} from '@kbn/rule-data-utils'; import { ColumnHeaderOptions } from '../../../../common'; import { defaultColumnHeaderType } from '../../../timelines/components/timeline/body/column_headers/default_headers'; @@ -31,26 +40,38 @@ export const columns: Array< { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_RULE, - id: 'signal.rule.name', + id: ALERT_RULE_NAME, initialWidth: DEFAULT_COLUMN_MIN_WIDTH, - linkField: 'signal.rule.id', + linkField: ALERT_RULE_UUID, + }, + { + columnHeaderType: defaultColumnHeaderType, + displayAsText: i18n.ALERTS_HEADERS_VERSION, + id: ALERT_RULE_VERSION, + initialWidth: 95, + }, + { + columnHeaderType: defaultColumnHeaderType, + displayAsText: i18n.ALERTS_HEADERS_METHOD, + id: ALERT_RULE_TYPE, + initialWidth: 100, }, { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_SEVERITY, - id: 'signal.rule.severity', + id: ALERT_SEVERITY, initialWidth: 105, }, { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_RISK_SCORE, - id: 'signal.rule.risk_score', + id: ALERT_RISK_SCORE, initialWidth: 100, }, { columnHeaderType: defaultColumnHeaderType, displayAsText: i18n.ALERTS_HEADERS_REASON, - id: 'signal.reason', + id: ALERT_REASON, initialWidth: 450, }, { diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.test.ts index b944cb640b7199..af345dd5a66ac5 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { KibanaServices } from '../../../../common/lib/kibana'; import { alertsMock, @@ -42,8 +43,7 @@ describe('Detections Alerts API', () => { test('check parameter url, body', async () => { await fetchQueryAlerts({ query: mockAlertsQuery, signal: abortCtrl.signal }); expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/signals/search', { - body: - '{"aggs":{"alertsByGrouping":{"terms":{"field":"signal.rule.risk_score","missing":"All others","order":{"_count":"desc"},"size":10},"aggs":{"alerts":{"date_histogram":{"field":"@timestamp","fixed_interval":"81000000ms","min_doc_count":0,"extended_bounds":{"min":1579644343954,"max":1582236343955}}}}}},"query":{"bool":{"filter":[{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}},{"range":{"@timestamp":{"gte":1579644343954,"lte":1582236343955}}}]}}}', + body: `{"aggs":{"alertsByGrouping":{"terms":{"field":"${ALERT_RISK_SCORE}","missing":"All others","order":{"_count":"desc"},"size":10},"aggs":{"alerts":{"date_histogram":{"field":"@timestamp","fixed_interval":"81000000ms","min_doc_count":0,"extended_bounds":{"min":1579644343954,"max":1582236343955}}}}}},"query":{"bool":{"filter":[{"bool":{"must":[],"filter":[{"match_all":{}}],"should":[],"must_not":[]}},{"range":{"@timestamp":{"gte":1579644343954,"lte":1582236343955}}}]}}}`, method: 'POST', signal: abortCtrl.signal, }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts index 7aba8fa4ac10f1..aaff381aa3c9e8 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/mock.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { HostIsolationResponse } from '../../../../../common/endpoint/types/actions'; import { AlertSearchResponse, AlertsIndex, Privilege, CasesFromAlertsResponse } from './types'; @@ -949,7 +950,7 @@ export const mockAlertsQuery: object = { aggs: { alertsByGrouping: { terms: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, missing: 'All others', order: { _count: 'desc' }, size: 10, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_with_fallback.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_with_fallback.tsx index da56275280f654..8271fddd0b0ad2 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_with_fallback.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_with_fallback.tsx @@ -8,6 +8,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { isNotFoundError } from '@kbn/securitysolution-t-grid'; import { useAsync, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; +import { ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { useQueryAlerts } from '../alerts/use_query'; import { fetchRuleById } from './api'; @@ -28,9 +29,14 @@ interface AlertHit { _index: string; _source: { '@timestamp': string; - signal: { + signal?: { rule: Rule; }; + kibana?: { + alert: { + rule: Rule; + }; + }; }; } @@ -41,7 +47,7 @@ const useFetchRule = () => useAsync(fetchWithOptionslSignal); const buildLastAlertQuery = (ruleId: string) => ({ query: { bool: { - filter: [{ match: { 'signal.rule.id': ruleId } }], + filter: [{ match: { [ALERT_RULE_UUID]: ruleId } }], }, }, size: 1, @@ -54,7 +60,6 @@ const buildLastAlertQuery = (ruleId: string) => ({ export const useRuleWithFallback = (ruleId: string): UseRuleWithFallback => { const { start, loading: ruleLoading, result: ruleData, error } = useFetchRule(); const { addError } = useAppToasts(); - const fetch = useCallback(() => { start({ id: ruleId }); }, [ruleId, start]); @@ -77,7 +82,12 @@ export const useRuleWithFallback = (ruleId: string): UseRuleWithFallback => { }, [addError, error]); const rule = useMemo(() => { - const result = isExistingRule ? ruleData : alertsData?.hits.hits[0]?._source.signal.rule; + let result = isExistingRule ? ruleData : null; + if (result === null) { + result = alertsData?.hits.hits[0]?._source.signal + ? alertsData?.hits.hits[0]?._source.signal.rule + : alertsData?.hits.hits[0]?._source.kibana?.alert.rule; + } if (result) { return transformInput(result); } diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 93fa70ddd9bfbe..cd167dbc409c72 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -351,7 +351,7 @@ export class Plugin implements IPlugin { const ruleIndex = useMemo( - () => find({ category: 'signal', field: 'signal.rule.index' }, detailsData)?.values, + () => find({ category: 'kibana', field: ALERT_RULE_INDEX }, detailsData)?.values, [detailsData] ); const addExceptionModalWrapperData = useMemo( () => [ - { category: 'signal', field: 'signal.rule.id', name: 'ruleId' }, - { category: 'signal', field: 'signal.rule.name', name: 'ruleName' }, - { category: 'signal', field: 'signal.status', name: 'alertStatus' }, + { category: 'kibana', field: ALERT_RULE_UUID, name: 'ruleId' }, + { category: 'kibana', field: ALERT_RULE_NAME, name: 'ruleName' }, + { category: 'kibana', field: ALERT_WORKFLOW_STATUS, name: 'alertStatus' }, { category: '_id', field: '_id', name: 'eventId' }, ].reduce( (acc, curr) => ({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx index 0866a927182f5a..3ed9f39d06ee47 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx @@ -17,6 +17,7 @@ import { import React, { useState, useCallback, useMemo } from 'react'; import styled from 'styled-components'; import deepEqual from 'fast-deep-equal'; +import { ALERT_RULE_UUID, ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { BrowserFields, DocValueFields } from '../../../../common/containers/source'; import { ExpandableEvent, ExpandableEventTitle } from './expandable_event'; import { useTimelineEventsDetails } from '../../../containers/details'; @@ -106,10 +107,10 @@ const EventDetailsPanelComponent: React.FC = ({ } }, []); - const isAlert = some({ category: 'signal', field: 'signal.rule.id' }, detailsData); + const isAlert = some({ category: 'kibana', field: ALERT_RULE_UUID }, detailsData); const ruleName = useMemo( - () => getFieldValue({ category: 'signal', field: 'signal.rule.name' }, detailsData), + () => getFieldValue({ category: 'kibana', field: ALERT_RULE_NAME }, detailsData), [detailsData] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx index 73650bd320f326..4e9767a4fca2b7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx @@ -92,7 +92,7 @@ const ActionsComponent: React.FC = ({ const isContextMenuDisabled = useMemo( () => - eventType !== 'signal' && + eventType !== 'kibana.alert' && !( (ecsData.event?.kind?.includes('event') || ecsData.event?.kind?.includes('alert')) && ecsData.agent?.type?.includes('endpoint') @@ -132,7 +132,7 @@ const ActionsComponent: React.FC = ({
<> - {timelineId !== TimelineId.active && eventType === 'signal' && ( + {timelineId !== TimelineId.active && eventType === 'kibana.alert' && ( - !isEmpty(event.signal?.rule?.building_block_type); + !isEmpty(event.kibana?.alert?.rule?.building_block_type); export const isEvenEqlSequence = (event: Ecs): boolean => { if (!isEmpty(event.eql?.sequenceNumber)) { @@ -115,8 +115,8 @@ export const isEvenEqlSequence = (event: Ecs): boolean => { }; /** Return eventType raw or signal or eql */ export const getEventType = (event: Ecs): Omit => { - if (!isEmpty(event.signal?.rule?.id)) { - return 'signal'; + if (!isEmpty(event.kibana?.alert?.rule?.uuid)) { + return 'kibana.alert'; } else if (!isEmpty(event.eql?.parentId)) { return 'eql'; } diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx index 3a7a43da2aedc6..f2316010debf62 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx @@ -14,7 +14,4 @@ export const EVENT_MODULE_FIELD_NAME = 'event.module'; export const RULE_REFERENCE_FIELD_NAME = 'rule.reference'; export const REFERENCE_URL_FIELD_NAME = 'reference.url'; export const EVENT_URL_FIELD_NAME = 'event.url'; -export const SIGNAL_RULE_NAME_FIELD_NAME = 'signal.rule.name'; -export const SIGNAL_STATUS_FIELD_NAME = 'signal.status'; export const AGENT_STATUS_FIELD_NAME = 'agent.status'; -export const REASON_FIELD_NAME = 'signal.reason'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index 5eec4ef66f39c2..a7b209b0714332 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -11,6 +11,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui'; import { isNumber, isEmpty } from 'lodash/fp'; import React from 'react'; +import { ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { INDICATOR_REFERENCE } from '../../../../../../common/cti/constants'; import { DefaultDraggable } from '../../../../../common/components/draggables'; import { Bytes, BYTES_FORMAT } from './bytes'; @@ -28,10 +29,8 @@ import { MESSAGE_FIELD_NAME, EVENT_MODULE_FIELD_NAME, RULE_REFERENCE_FIELD_NAME, - SIGNAL_RULE_NAME_FIELD_NAME, REFERENCE_URL_FIELD_NAME, EVENT_URL_FIELD_NAME, - SIGNAL_STATUS_FIELD_NAME, AGENT_STATUS_FIELD_NAME, GEO_FIELD_TYPE, } from './constants'; @@ -135,7 +134,7 @@ const FormattedFieldValueComponent: React.FC<{ value={`${value}`} /> ); - } else if (fieldName === SIGNAL_RULE_NAME_FIELD_NAME) { + } else if (fieldName === ALERT_RULE_NAME) { return ( { @@ -68,7 +69,7 @@ const rowRenderers: RowRenderer[] = [ const browserFields: BrowserFields = {}; const defaultProps = { - columnName: REASON_FIELD_NAME, + columnName: ALERT_REASON, eventId: 'test-event-id', field, timelineId: 'test-timeline-id', @@ -81,8 +82,8 @@ describe('reasonColumnRenderer', () => { }); describe('isIntance', () => { - it('returns true when columnName is `signal.reason`', () => { - expect(reasonColumnRenderer.isInstance(REASON_FIELD_NAME, [])).toBeTruthy(); + it(`returns true when columnName is ${ALERT_REASON}`, () => { + expect(reasonColumnRenderer.isInstance(ALERT_REASON, [])).toBeTruthy(); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.tsx index 52483b4853cbc3..3083f3713c2f2e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/reason_column_renderer.tsx @@ -6,6 +6,7 @@ */ import { EuiButtonEmpty, EuiPopover, EuiPopoverTitle } from '@elastic/eui'; +import { ALERT_REASON } from '@kbn/rule-data-utils'; import { isEqual } from 'lodash/fp'; import React, { useCallback, useMemo, useState } from 'react'; @@ -14,13 +15,12 @@ import { BrowserFields, ColumnHeaderOptions, RowRenderer } from '../../../../../ import { Ecs } from '../../../../../../common/ecs'; import { eventRendererNames } from '../../../row_renderers_browser/catalog/constants'; import { ColumnRenderer } from './column_renderer'; -import { REASON_FIELD_NAME } from './constants'; import { getRowRenderer } from './get_row_renderer'; import { plainColumnRenderer } from './plain_column_renderer'; import * as i18n from './translations'; export const reasonColumnRenderer: ColumnRenderer = { - isInstance: isEqual(REASON_FIELD_NAME), + isInstance: isEqual(ALERT_REASON), renderColumn: ({ columnName, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx index 5282276f8bb51e..d0366affa9a2fd 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/cell_rendering/default_cell_renderer.test.tsx @@ -9,6 +9,7 @@ import { mount } from 'enzyme'; import { cloneDeep } from 'lodash/fp'; import React from 'react'; +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { columnRenderers } from '../body/renderers'; import { getColumnRenderer } from '../body/renderers/get_column_renderer'; import { DragDropContextWrapper } from '../../../../common/components/drag_and_drop/drag_drop_context_wrapper'; @@ -26,7 +27,7 @@ const mockImplementation = { }; describe('DefaultCellRenderer', () => { - const columnId = 'signal.rule.risk_score'; + const columnId = ALERT_RISK_SCORE; const eventId = '_id-123'; const isDetails = true; const isExpandable = true; diff --git a/x-pack/plugins/security_solution/public/ueba/components/host_rules_table/columns.tsx b/x-pack/plugins/security_solution/public/ueba/components/host_rules_table/columns.tsx index 4289b7d2c62da3..e7bbe86f90d37a 100644 --- a/x-pack/plugins/security_solution/public/ueba/components/host_rules_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/ueba/components/host_rules_table/columns.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; +import { ALERT_RULE_NAME, ALERT_RISK_SCORE, ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { DragEffects, DraggableWrapper, @@ -38,7 +39,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ id, name: ruleName, kqlQuery: '', - queryMatch: { field: 'signal.rule.name', value: ruleName, operator: IS_OPERATOR }, + queryMatch: { field: ALERT_RULE_NAME, value: ruleName, operator: IS_OPERATOR }, }} render={(dataProvider, _, snapshot) => snapshot.isDragging ? ( @@ -73,7 +74,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ id, name: ruleType, kqlQuery: '', - queryMatch: { field: 'signal.rule.type', value: ruleType, operator: IS_OPERATOR }, + queryMatch: { field: ALERT_RULE_TYPE, value: ruleType, operator: IS_OPERATOR }, }} render={(dataProvider, _, snapshot) => snapshot.isDragging ? ( @@ -109,7 +110,7 @@ export const getHostRulesColumns = (): HostRulesColumns => [ name: `${riskScore}`, kqlQuery: '', queryMatch: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, value: riskScore, operator: IS_OPERATOR, }, diff --git a/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx b/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx index 19516ad6fcafa5..eeba41c04cf53b 100644 --- a/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/ueba/components/host_tactics_table/columns.tsx @@ -6,6 +6,7 @@ */ import React from 'react'; +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { DragEffects, DraggableWrapper, @@ -18,6 +19,10 @@ import { HostTacticsColumns } from './'; import * as i18n from './translations'; import { HostTacticsFields } from '../../../../common'; +import { + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TECHNIQUE_NAME, +} from '../../../../../timelines/common/alerts'; export const getHostTacticsColumns = (): HostTacticsColumns => [ { @@ -39,7 +44,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ name: tactic, kqlQuery: '', queryMatch: { - field: 'signal.rule.threat.tactic.name', + field: ALERT_RULE_THREAT_TACTIC_NAME, value: tactic, operator: IS_OPERATOR, }, @@ -78,7 +83,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ name: technique, kqlQuery: '', queryMatch: { - field: 'signal.rule.threat.technique.name', + field: ALERT_RULE_THREAT_TECHNIQUE_NAME, value: technique, operator: IS_OPERATOR, }, @@ -117,7 +122,7 @@ export const getHostTacticsColumns = (): HostTacticsColumns => [ name: `${riskScore}`, kqlQuery: '', queryMatch: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, value: riskScore, operator: IS_OPERATOR, }, 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 a95da275fc530f..b9a4f19f4b1c61 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 @@ -34,7 +34,7 @@ import { ALERT_ANCESTORS, ALERT_ORIGINAL_EVENT, ALERT_ORIGINAL_TIME, -} from '../../field_maps/field_names'; +} from '../../../../../../../timelines/common/alerts'; import { SERVER_APP_ID } from '../../../../../../common/constants'; type SignalDoc = SignalSourceHit & { 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 1377e9ef9207e7..1ed45c15e1e999 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 @@ -26,13 +26,13 @@ import { import { invariant } from '../../../../../../common/utils/invariant'; import { RACAlert } from '../../types'; import { flattenWithPrefix } from './flatten_with_prefix'; +import { SERVER_APP_ID } from '../../../../../../common/constants'; import { ALERT_ANCESTORS, ALERT_DEPTH, ALERT_ORIGINAL_EVENT, ALERT_ORIGINAL_TIME, -} from '../../field_maps/field_names'; -import { SERVER_APP_ID } from '../../../../../../common/constants'; +} from '../../../../../../../timelines/common/alerts'; /** * Takes an event document and extracts the information needed for the corresponding entry in the child diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts index 1c4b7f03fd73ff..857121735a21ab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/field_maps/alerts.ts @@ -5,310 +5,373 @@ * 2.0. */ +import { ALERT_REASON } from '@kbn/rule-data-utils'; import { FieldMap } from '../../../../../../rule_registry/common/field_map'; +import { + ALERT_ANCESTORS, + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_DEPTH, + ALERT_GROUP, + ALERT_GROUP_ID, + ALERT_GROUP_INDEX, + ALERT_ORIGINAL_EVENT, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_AGENT_ID_STATUS, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_INGESTED, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_REASON, + ALERT_ORIGINAL_EVENT_REFERENCE, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_EVENT_URL, + ALERT_ORIGINAL_TIME, + ALERT_THREAT, + ALERT_THREAT_FRAMEWORK, + ALERT_THREAT_TACTIC, + ALERT_THREAT_TACTIC_ID, + ALERT_THREAT_TACTIC_NAME, + ALERT_THREAT_TACTIC_REFERENCE, + ALERT_THREAT_TECHNIQUE, + ALERT_THREAT_TECHNIQUE_ID, + ALERT_THREAT_TECHNIQUE_NAME, + ALERT_THREAT_TECHNIQUE_REFERENCE, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_ID, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_NAME, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_REFERENCE, + ALERT_THRESHOLD_RESULT, + ALERT_THRESHOLD_RESULT_CARDINALITY, + ALERT_THRESHOLD_RESULT_CARDINALITY_FIELD, + ALERT_THRESHOLD_RESULT_CARDINALITY_VALUE, + ALERT_THRESHOLD_RESULT_COUNT, + ALERT_THRESHOLD_RESULT_FROM, + ALERT_THRESHOLD_RESULT_TERMS, + ALERT_THRESHOLD_RESULT_TERMS_FIELD, + ALERT_THRESHOLD_RESULT_TERMS_VALUE, +} from './../../../../../../timelines/common/alerts'; export const alertsFieldMap: FieldMap = { - 'kibana.alert.ancestors': { + [ALERT_ANCESTORS]: { type: 'object', array: true, required: true, }, - 'kibana.alert.ancestors.depth': { + [ALERT_ANCESTORS_DEPTH]: { type: 'long', array: false, required: true, }, - 'kibana.alert.ancestors.id': { + [ALERT_ANCESTORS_ID]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.ancestors.index': { + [ALERT_ANCESTORS_INDEX]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.ancestors.rule': { + [ALERT_ANCESTORS_RULE]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.ancestors.type': { + [ALERT_ANCESTORS_TYPE]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.depth': { + [ALERT_DEPTH]: { type: 'long', array: false, required: true, }, - 'kibana.alert.group': { + [ALERT_GROUP]: { type: 'object', array: false, required: false, }, - 'kibana.alert.group.id': { + [ALERT_GROUP_ID]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.group.index': { + [ALERT_GROUP_INDEX]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event': { + [ALERT_ORIGINAL_EVENT]: { type: 'object', array: false, required: false, }, - 'kibana.alert.original_event.action': { + [ALERT_ORIGINAL_EVENT_ACTION]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.agent_id_status': { + [ALERT_ORIGINAL_EVENT_AGENT_ID_STATUS]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.category': { + [ALERT_ORIGINAL_EVENT_CATEGORY]: { type: 'keyword', array: true, required: true, }, - 'kibana.alert.original_event.code': { + [ALERT_ORIGINAL_EVENT_CODE]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.created': { + [ALERT_ORIGINAL_EVENT_CREATED]: { type: 'date', array: false, required: true, }, - 'kibana.alert.original_event.dataset': { + [ALERT_ORIGINAL_EVENT_DATASET]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.duration': { + [ALERT_ORIGINAL_EVENT_DURATION]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.end': { + [ALERT_ORIGINAL_EVENT_END]: { type: 'date', array: false, required: false, }, - 'kibana.alert.original_event.hash': { + [ALERT_ORIGINAL_EVENT_HASH]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.id': { + [ALERT_ORIGINAL_EVENT_ID]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.ingested': { + [ALERT_ORIGINAL_EVENT_INGESTED]: { type: 'date', array: false, required: true, }, - 'kibana.alert.original_event.kind': { + [ALERT_ORIGINAL_EVENT_KIND]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.module': { + [ALERT_ORIGINAL_EVENT_MODULE]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.original': { + [ALERT_ORIGINAL_EVENT_ORIGINAL]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.outcome': { + [ALERT_ORIGINAL_EVENT_OUTCOME]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.provider': { + [ALERT_ORIGINAL_EVENT_PROVIDER]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.original_event.reason': { + [ALERT_ORIGINAL_EVENT_REASON]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.reference': { + [ALERT_ORIGINAL_EVENT_REFERENCE]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.risk_score': { + [ALERT_ORIGINAL_EVENT_RISK_SCORE]: { type: 'float', array: false, required: false, }, - 'kibana.alert.original_event.risk_score_norm': { + [ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM]: { type: 'float', array: false, required: false, }, - 'kibana.alert.original_event.sequence': { + [ALERT_ORIGINAL_EVENT_SEQUENCE]: { type: 'long', array: false, required: true, }, - 'kibana.alert.original_event.start': { + [ALERT_ORIGINAL_EVENT_START]: { type: 'date', array: false, required: false, }, - 'kibana.alert.original_event.timezone': { + [ALERT_ORIGINAL_EVENT_TIMEZONE]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_event.type': { + [ALERT_ORIGINAL_EVENT_TYPE]: { type: 'keyword', array: true, required: true, }, - 'kibana.alert.original_event.url': { + [ALERT_ORIGINAL_EVENT_URL]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.original_time': { + [ALERT_ORIGINAL_TIME]: { type: 'date', array: false, required: true, }, - 'kibana.alert.reason': { + [ALERT_REASON]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.threat': { + [ALERT_THREAT]: { type: 'object', array: false, required: false, }, - 'kibana.alert.threat.framework': { + [ALERT_THREAT_FRAMEWORK]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.tactic': { + [ALERT_THREAT_TACTIC]: { type: 'object', array: false, required: true, }, - 'kibana.alert.threat.tactic.id': { + [ALERT_THREAT_TACTIC_ID]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.tactic.name': { + [ALERT_THREAT_TACTIC_NAME]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.tactic.reference': { + [ALERT_THREAT_TACTIC_REFERENCE]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique': { + [ALERT_THREAT_TECHNIQUE]: { type: 'object', array: false, required: true, }, - 'kibana.alert.threat.technique.id': { + [ALERT_THREAT_TECHNIQUE_ID]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique.name': { + [ALERT_THREAT_TECHNIQUE_NAME]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique.reference': { + [ALERT_THREAT_TECHNIQUE_REFERENCE]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique.subtechnique': { + [ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE]: { type: 'object', array: false, required: true, }, - 'kibana.alert.threat.technique.subtechnique.id': { + [ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_ID]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique.subtechnique.name': { + [ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_NAME]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threat.technique.subtechnique.reference': { + [ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_REFERENCE]: { type: 'keyword', array: false, required: true, }, - 'kibana.alert.threshold_result': { + [ALERT_THRESHOLD_RESULT]: { type: 'object', array: false, required: false, }, - 'kibana.alert.threshold_result.cardinality': { + [ALERT_THRESHOLD_RESULT_CARDINALITY]: { type: 'object', array: false, required: false, }, - 'kibana.alert.threshold_result.cardinality.field': { + [ALERT_THRESHOLD_RESULT_CARDINALITY_FIELD]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.threshold_result.cardinality.value': { + [ALERT_THRESHOLD_RESULT_CARDINALITY_VALUE]: { type: 'long', array: false, required: false, }, - 'kibana.alert.threshold_result.count': { + [ALERT_THRESHOLD_RESULT_COUNT]: { type: 'long', array: false, required: false, }, - 'kibana.alert.threshold_result.from': { + [ALERT_THRESHOLD_RESULT_FROM]: { type: 'date', array: false, required: false, }, - 'kibana.alert.threshold_result.terms': { + [ALERT_THRESHOLD_RESULT_TERMS]: { type: 'object', array: false, required: false, }, - 'kibana.alert.threshold_result.terms.field': { + [ALERT_THRESHOLD_RESULT_TERMS_FIELD]: { type: 'keyword', array: false, required: false, }, - 'kibana.alert.threshold_result.terms.value': { + [ALERT_THRESHOLD_RESULT_TERMS_VALUE]: { type: 'keyword', array: false, required: false, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_rules/query.host_rules.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_rules/query.host_rules.dsl.ts index 4c116104b3e14d..0b70d7bc06d0a0 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_rules/query.host_rules.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_rules/query.host_rules.dsl.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_NAME, ALERT_RISK_SCORE, ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash/fp'; import { Direction, HostRulesRequestOptions } from '../../../../../../common/search_strategy'; import { createQueryFilterClauses } from '../../../../../utils/build_query'; @@ -39,12 +40,12 @@ export const buildHostRulesQuery = ({ aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, rule_name: { terms: { - field: 'signal.rule.name', + field: ALERT_RULE_NAME, order: { risk_score: Direction.desc, }, @@ -52,19 +53,19 @@ export const buildHostRulesQuery = ({ aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, rule_type: { terms: { - field: 'signal.rule.type', + field: ALERT_RULE_TYPE, }, }, }, }, rule_count: { cardinality: { - field: 'signal.rule.name', + field: ALERT_RULE_NAME, }, }, }, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_tactics/query.host_tactics.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_tactics/query.host_tactics.dsl.ts index ec1afe247011b2..1f689dfdae2554 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_tactics/query.host_tactics.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/host_tactics/query.host_tactics.dsl.ts @@ -5,7 +5,12 @@ * 2.0. */ +import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash/fp'; +import { + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TECHNIQUE_NAME, +} from '../../../../../../../timelines/common/alerts'; import { HostTacticsRequestOptions } from '../../../../../../common/search_strategy'; import { createQueryFilterClauses } from '../../../../../utils/build_query'; @@ -39,22 +44,22 @@ export const buildHostTacticsQuery = ({ aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, tactic: { terms: { - field: 'signal.rule.threat.tactic.name', + field: ALERT_RULE_THREAT_TACTIC_NAME, }, aggs: { technique: { terms: { - field: 'signal.rule.threat.technique.name', + field: ALERT_RULE_THREAT_TECHNIQUE_NAME, }, aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, }, @@ -63,12 +68,12 @@ export const buildHostTacticsQuery = ({ }, tactic_count: { cardinality: { - field: 'signal.rule.threat.tactic.name', + field: ALERT_RULE_THREAT_TACTIC_NAME, }, }, technique_count: { cardinality: { - field: 'signal.rule.threat.technique.name', + field: ALERT_RULE_THREAT_TECHNIQUE_NAME, }, }, }, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/user_rules/query.user_rules.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/user_rules/query.user_rules.dsl.ts index c2242ff00a6c14..2f52f052889d9b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/user_rules/query.user_rules.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/ueba/user_rules/query.user_rules.dsl.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_NAME, ALERT_RISK_SCORE, ALERT_RULE_TYPE } from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash/fp'; import { Direction, UserRulesRequestOptions } from '../../../../../../common/search_strategy'; import { createQueryFilterClauses } from '../../../../../utils/build_query'; @@ -48,12 +49,12 @@ export const buildUserRulesQuery = ({ aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, rule_name: { terms: { - field: 'signal.rule.name', + field: ALERT_RULE_NAME, order: { risk_score: Direction.desc, }, @@ -61,19 +62,19 @@ export const buildUserRulesQuery = ({ aggs: { risk_score: { sum: { - field: 'signal.rule.risk_score', + field: ALERT_RISK_SCORE, }, }, rule_type: { terms: { - field: 'signal.rule.type', + field: ALERT_RULE_TYPE, }, }, }, }, rule_count: { cardinality: { - field: 'signal.rule.name', + field: ALERT_RULE_NAME, }, }, }, diff --git a/x-pack/plugins/timelines/common/alerts/constants.ts b/x-pack/plugins/timelines/common/alerts/constants.ts new file mode 100644 index 00000000000000..a95c8254aa446e --- /dev/null +++ b/x-pack/plugins/timelines/common/alerts/constants.ts @@ -0,0 +1,197 @@ +/* + * 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 { + ALERT_NAMESPACE, + ALERT_RULE_NAMESPACE, + TechnicalRuleDataFieldName, +} from '@kbn/rule-data-utils'; +import { ValuesType } from 'utility-types'; + +// Cast to `as const` to preserve the exact string value when using as a type rather than a value +export const ALERT_ANCESTORS = `${ALERT_NAMESPACE}.ancestors` as const; +export const ALERT_ANCESTORS_DEPTH = `${ALERT_ANCESTORS}.depth` as const; +export const ALERT_ANCESTORS_ID = `${ALERT_ANCESTORS}.id` as const; +export const ALERT_ANCESTORS_INDEX = `${ALERT_ANCESTORS}.index` as const; +export const ALERT_ANCESTORS_RULE = `${ALERT_ANCESTORS}.rule` as const; +export const ALERT_ANCESTORS_TYPE = `${ALERT_ANCESTORS}.type` as const; +export const ALERT_DEPTH = `${ALERT_NAMESPACE}.depth` as const; +export const ALERT_GROUP = `${ALERT_NAMESPACE}.group` as const; +export const ALERT_GROUP_ID = `${ALERT_GROUP}.id` as const; +export const ALERT_GROUP_INDEX = `${ALERT_GROUP}.index` 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; +export const ALERT_ORIGINAL_EVENT_AGENT_ID_STATUS = `${ALERT_ORIGINAL_EVENT}.agent_id_status` as const; +export const ALERT_ORIGINAL_EVENT_CATEGORY = `${ALERT_ORIGINAL_EVENT}.category` as const; +export const ALERT_ORIGINAL_EVENT_CODE = `${ALERT_ORIGINAL_EVENT}.code` as const; +export const ALERT_ORIGINAL_EVENT_CREATED = `${ALERT_ORIGINAL_EVENT}.created` as const; +export const ALERT_ORIGINAL_EVENT_DATASET = `${ALERT_ORIGINAL_EVENT}.dataset` as const; +export const ALERT_ORIGINAL_EVENT_DURATION = `${ALERT_ORIGINAL_EVENT}.duration` as const; +export const ALERT_ORIGINAL_EVENT_END = `${ALERT_ORIGINAL_EVENT}.end` as const; +export const ALERT_ORIGINAL_EVENT_HASH = `${ALERT_ORIGINAL_EVENT}.hash` as const; +export const ALERT_ORIGINAL_EVENT_ID = `${ALERT_ORIGINAL_EVENT}.id` as const; +export const ALERT_ORIGINAL_EVENT_INGESTED = `${ALERT_ORIGINAL_EVENT}.ingested` as const; +export const ALERT_ORIGINAL_EVENT_KIND = `${ALERT_ORIGINAL_EVENT}.kind` as const; +export const ALERT_ORIGINAL_EVENT_MODULE = `${ALERT_ORIGINAL_EVENT}.module` as const; +export const ALERT_ORIGINAL_EVENT_ORIGINAL = `${ALERT_ORIGINAL_EVENT}.original` as const; +export const ALERT_ORIGINAL_EVENT_OUTCOME = `${ALERT_ORIGINAL_EVENT}.outcome` as const; +export const ALERT_ORIGINAL_EVENT_PROVIDER = `${ALERT_ORIGINAL_EVENT}.provider` as const; +export const ALERT_ORIGINAL_EVENT_REASON = `${ALERT_ORIGINAL_EVENT}.reason` as const; +export const ALERT_ORIGINAL_EVENT_REFERENCE = `${ALERT_ORIGINAL_EVENT}.reference` as const; +export const ALERT_ORIGINAL_EVENT_RISK_SCORE = `${ALERT_ORIGINAL_EVENT}.risk_score` as const; +export const ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM = `${ALERT_ORIGINAL_EVENT}.risk_score_norm` as const; +export const ALERT_ORIGINAL_EVENT_SEQUENCE = `${ALERT_ORIGINAL_EVENT}.sequence` as const; +export const ALERT_ORIGINAL_EVENT_SEVERITY = `${ALERT_ORIGINAL_EVENT}.severity` as const; +export const ALERT_ORIGINAL_EVENT_START = `${ALERT_ORIGINAL_EVENT}.start` as const; +export const ALERT_ORIGINAL_EVENT_TIMEZONE = `${ALERT_ORIGINAL_EVENT}.timezone` as const; +export const ALERT_ORIGINAL_EVENT_TYPE = `${ALERT_ORIGINAL_EVENT}.type` as const; +export const ALERT_ORIGINAL_EVENT_URL = `${ALERT_ORIGINAL_EVENT}.url` as const; +export const ALERT_ORIGINAL_TIME = `${ALERT_NAMESPACE}.original_time` as const; +export const ALERT_THREAT = `${ALERT_NAMESPACE}.threat` as const; +export const ALERT_THREAT_FRAMEWORK = `${ALERT_THREAT}.framework` as const; +export const ALERT_THREAT_TACTIC = `${ALERT_THREAT}.tactic` as const; +export const ALERT_THREAT_TACTIC_ID = `${ALERT_THREAT_TACTIC}.id` as const; +export const ALERT_THREAT_TACTIC_NAME = `${ALERT_THREAT_TACTIC}.name` as const; +export const ALERT_THREAT_TACTIC_REFERENCE = `${ALERT_THREAT_TACTIC}.reference` as const; +export const ALERT_THREAT_TECHNIQUE = `${ALERT_THREAT}.technique` as const; +export const ALERT_THREAT_TECHNIQUE_ID = `${ALERT_THREAT_TECHNIQUE}.id` as const; +export const ALERT_THREAT_TECHNIQUE_NAME = `${ALERT_THREAT_TECHNIQUE}.name` as const; +export const ALERT_THREAT_TECHNIQUE_REFERENCE = `${ALERT_THREAT_TECHNIQUE}.reference` as const; +export const ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE = `${ALERT_THREAT_TECHNIQUE}.subtechnique` as const; +export const ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_ID = `${ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE}.id` as const; +export const ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_NAME = `${ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE}.name` as const; +export const ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_REFERENCE = `${ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE}.reference` as const; +export const ALERT_THRESHOLD_RESULT = `${ALERT_NAMESPACE}.threshold_result` as const; +export const ALERT_THRESHOLD_RESULT_CARDINALITY = `${ALERT_THRESHOLD_RESULT}.cardinality` as const; +export const ALERT_THRESHOLD_RESULT_CARDINALITY_FIELD = `${ALERT_THRESHOLD_RESULT_CARDINALITY}.field` as const; +export const ALERT_THRESHOLD_RESULT_CARDINALITY_VALUE = `${ALERT_THRESHOLD_RESULT_CARDINALITY}.value` as const; +export const ALERT_THRESHOLD_RESULT_COUNT = `${ALERT_THRESHOLD_RESULT}.count` as const; +export const ALERT_THRESHOLD_RESULT_FROM = `${ALERT_THRESHOLD_RESULT}.from` as const; +export const ALERT_THRESHOLD_RESULT_TERMS = `${ALERT_THRESHOLD_RESULT}.terms` as const; +export const ALERT_THRESHOLD_RESULT_TERMS_FIELD = `${ALERT_THRESHOLD_RESULT_TERMS}.field` as const; +export const ALERT_THRESHOLD_RESULT_TERMS_VALUE = `${ALERT_THRESHOLD_RESULT_TERMS}.value` as const; +export const ALERT_RULE_BUILDING_BLOCK_TYPE = `${ALERT_RULE_NAMESPACE}.building_block_type` as const; +export const ALERT_RULE_EXCEPTIONS_LIST = `${ALERT_RULE_NAMESPACE}.exceptions_list` as const; +export const ALERT_RULE_FALSE_POSITIVES = `${ALERT_RULE_NAMESPACE}.false_positives` as const; +export const ALERT_RULE_FILTERS = `${ALERT_RULE_NAMESPACE}.filters` as const; +export const ALERT_RULE_IMMUTABLE = `${ALERT_RULE_NAMESPACE}.immutable` as const; +export const ALERT_RULE_INDEX = `${ALERT_RULE_NAMESPACE}.index` as const; +export const ALERT_RULE_LANGUAGE = `${ALERT_RULE_NAMESPACE}.language` as const; +export const ALERT_RULE_MAX_SIGNALS = `${ALERT_RULE_NAMESPACE}.max_signals` as const; +export const ALERT_RULE_QUERY = `${ALERT_RULE_NAMESPACE}.query` as const; +// TODO: Could be deprecated +export const ALERT_RULE_SAVED_ID = `${ALERT_RULE_NAMESPACE}.saved_id` as const; +// TODO: not accounted for in the excel doc +export const ALERT_RULE_SIZE = `${ALERT_RULE_NAMESPACE}.size` as const; +export const ALERT_RULE_THREAT_MAPPING_ENTRIES_FIELD = `${ALERT_RULE_NAMESPACE}.threat_mapping.entries.field` as const; +export const ALERT_RULE_THREAT_MAPPING_ENTRIES_VALUE = `${ALERT_RULE_NAMESPACE}.threat_mapping.entries.value` as const; +export const ALERT_RULE_THREAT_MAPPING_ENTRIES_TYPE = `${ALERT_RULE_NAMESPACE}.threat_mapping.entries.type` as const; +export const ALERT_RULE_THRESHOLD = `${ALERT_RULE_NAMESPACE}.threshold` as const; +export const ALERT_RULE_TIMELINE_ID = `${ALERT_RULE_NAMESPACE}.timeline_id` as const; +export const ALERT_RULE_TIMELINE_TITLE = `${ALERT_RULE_NAMESPACE}.timeline_title` as const; +export const ALERT_RULE_THREAT = `${ALERT_RULE_NAMESPACE}.threat` as const; +export const ALERT_RULE_THREAT_FRAMEWORK = `${ALERT_RULE_THREAT}.framework` as const; +export const ALERT_RULE_THREAT_TACTIC = `${ALERT_RULE_THREAT}.tactic` as const; +export const ALERT_RULE_THREAT_TACTIC_ID = `${ALERT_RULE_THREAT_TACTIC}.id` as const; +export const ALERT_RULE_THREAT_TACTIC_NAME = `${ALERT_RULE_THREAT_TACTIC}.name` as const; +export const ALERT_RULE_THREAT_TACTIC_REFERENCE = `${ALERT_RULE_THREAT_TACTIC}.reference` as const; +export const ALERT_RULE_THREAT_TECHNIQUE = `${ALERT_RULE_THREAT}.technique` as const; +export const ALERT_RULE_THREAT_TECHNIQUE_ID = `${ALERT_RULE_THREAT_TECHNIQUE}.id` as const; +export const ALERT_RULE_THREAT_TECHNIQUE_NAME = `${ALERT_RULE_THREAT_TECHNIQUE}.name` as const; +export const ALERT_RULE_THREAT_TECHNIQUE_REFERENCE = `${ALERT_RULE_THREAT_TECHNIQUE}.reference` as const; + +const securityFields = { + ALERT_ANCESTORS, + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_DEPTH, + ALERT_GROUP, + ALERT_GROUP_ID, + ALERT_GROUP_INDEX, + ALERT_ORIGINAL_EVENT, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_AGENT_ID_STATUS, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_INGESTED, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_REASON, + ALERT_ORIGINAL_EVENT_REFERENCE, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_SEVERITY, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_EVENT_URL, + ALERT_ORIGINAL_TIME, + ALERT_THREAT, + ALERT_THREAT_FRAMEWORK, + ALERT_THREAT_TACTIC, + ALERT_THREAT_TACTIC_ID, + ALERT_THREAT_TACTIC_NAME, + ALERT_THREAT_TACTIC_REFERENCE, + ALERT_THREAT_TECHNIQUE, + ALERT_THREAT_TECHNIQUE_ID, + ALERT_THREAT_TECHNIQUE_NAME, + ALERT_THREAT_TECHNIQUE_REFERENCE, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_ID, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_NAME, + ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_REFERENCE, + ALERT_THRESHOLD_RESULT, + ALERT_THRESHOLD_RESULT_CARDINALITY, + ALERT_THRESHOLD_RESULT_CARDINALITY_FIELD, + ALERT_THRESHOLD_RESULT_CARDINALITY_VALUE, + ALERT_THRESHOLD_RESULT_COUNT, + ALERT_THRESHOLD_RESULT_FROM, + ALERT_THRESHOLD_RESULT_TERMS, + ALERT_THRESHOLD_RESULT_TERMS_FIELD, + ALERT_THRESHOLD_RESULT_TERMS_VALUE, + ALERT_RULE_BUILDING_BLOCK_TYPE, + ALERT_RULE_EXCEPTIONS_LIST, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_QUERY, + ALERT_RULE_SAVED_ID, + ALERT_RULE_SIZE, + ALERT_RULE_THRESHOLD, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_THREAT, + ALERT_RULE_THREAT_FRAMEWORK, + ALERT_RULE_THREAT_TACTIC, + ALERT_RULE_THREAT_TACTIC_ID, + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TACTIC_REFERENCE, + ALERT_RULE_THREAT_TECHNIQUE, + ALERT_RULE_THREAT_TECHNIQUE_ID, + ALERT_RULE_THREAT_TECHNIQUE_NAME, + ALERT_RULE_THREAT_TECHNIQUE_REFERENCE, +}; + +export type SecurityAlertRuleDataFieldName = + | ValuesType + | TechnicalRuleDataFieldName; diff --git a/x-pack/plugins/timelines/common/alerts/index.ts b/x-pack/plugins/timelines/common/alerts/index.ts new file mode 100644 index 00000000000000..63661f0d5a9963 --- /dev/null +++ b/x-pack/plugins/timelines/common/alerts/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export * from './constants'; diff --git a/x-pack/plugins/timelines/common/ecs/ecs_fields/index.ts b/x-pack/plugins/timelines/common/ecs/ecs_fields/index.ts index 239e295a1f8b13..e13d34b71d89d5 100644 --- a/x-pack/plugins/timelines/common/ecs/ecs_fields/index.ts +++ b/x-pack/plugins/timelines/common/ecs/ecs_fields/index.ts @@ -5,6 +5,44 @@ * 2.0. */ +import { + ALERT_RULE_UUID, + ALERT_RULE_FROM, + ALERT_RULE_TO, + ALERT_RULE_RULE_ID, + ALERT_RISK_SCORE, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_NAME, + ALERT_RULE_REFERENCES, + ALERT_SEVERITY, + ALERT_RULE_TAGS, + ALERT_RULE_TYPE, + ALERT_RULE_ENABLED, + ALERT_RULE_CREATED_AT, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_RULE_NOTE, + ALERT_REASON, +} from '@kbn/rule-data-utils'; +import { + ALERT_ORIGINAL_TIME, + ALERT_RULE_SAVED_ID, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_FILTERS, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_THREAT, + ALERT_RULE_SIZE, + ALERT_RULE_THRESHOLD, + ALERT_RULE_EXCEPTIONS_LIST, +} from '../../alerts'; import { extendMap } from './extend_map'; export const auditdMap: Readonly> = { @@ -290,42 +328,41 @@ export const systemFieldsMap: Readonly> = { 'system.auth.ssh.method': 'system.auth.ssh.method', }; -export const signalFieldsMap: Readonly> = { - 'signal.original_time': 'signal.original_time', - 'signal.reason': 'signal.reason', - 'signal.rule.id': 'signal.rule.id', - 'signal.rule.saved_id': 'signal.rule.saved_id', - 'signal.rule.timeline_id': 'signal.rule.timeline_id', - 'signal.rule.timeline_title': 'signal.rule.timeline_title', - 'signal.rule.output_index': 'signal.rule.output_index', - 'signal.rule.from': 'signal.rule.from', - 'signal.rule.index': 'signal.rule.index', - 'signal.rule.language': 'signal.rule.language', - 'signal.rule.query': 'signal.rule.query', - 'signal.rule.to': 'signal.rule.to', - 'signal.rule.filters': 'signal.rule.filters', - 'signal.rule.rule_id': 'signal.rule.rule_id', - 'signal.rule.false_positives': 'signal.rule.false_positives', - 'signal.rule.max_signals': 'signal.rule.max_signals', - 'signal.rule.risk_score': 'signal.rule.risk_score', - 'signal.rule.description': 'signal.rule.description', - 'signal.rule.name': 'signal.rule.name', - 'signal.rule.immutable': 'signal.rule.immutable', - 'signal.rule.references': 'signal.rule.references', - 'signal.rule.severity': 'signal.rule.severity', - 'signal.rule.tags': 'signal.rule.tags', - 'signal.rule.threat': 'signal.rule.threat', - 'signal.rule.type': 'signal.rule.type', - 'signal.rule.size': 'signal.rule.size', - 'signal.rule.enabled': 'signal.rule.enabled', - 'signal.rule.created_at': 'signal.rule.created_at', - 'signal.rule.updated_at': 'signal.rule.updated_at', - 'signal.rule.created_by': 'signal.rule.created_by', - 'signal.rule.updated_by': 'signal.rule.updated_by', - 'signal.rule.version': 'signal.rule.version', - 'signal.rule.note': 'signal.rule.note', - 'signal.rule.threshold': 'signal.rule.threshold', - 'signal.rule.exceptions_list': 'signal.rule.exceptions_list', +export const alertFieldsMap: Readonly> = { + [ALERT_ORIGINAL_TIME]: ALERT_ORIGINAL_TIME, + [ALERT_REASON]: ALERT_REASON, + [ALERT_RULE_UUID]: ALERT_RULE_UUID, + [ALERT_RULE_SAVED_ID]: ALERT_RULE_SAVED_ID, + [ALERT_RULE_TIMELINE_ID]: ALERT_RULE_TIMELINE_ID, + [ALERT_RULE_TIMELINE_TITLE]: ALERT_RULE_TIMELINE_TITLE, + [ALERT_RULE_FROM]: ALERT_RULE_FROM, + [ALERT_RULE_INDEX]: ALERT_RULE_INDEX, + [ALERT_RULE_LANGUAGE]: ALERT_RULE_LANGUAGE, + [ALERT_RULE_QUERY]: ALERT_RULE_QUERY, + [ALERT_RULE_TO]: ALERT_RULE_TO, + [ALERT_RULE_FILTERS]: ALERT_RULE_FILTERS, + [ALERT_RULE_RULE_ID]: ALERT_RULE_RULE_ID, + [ALERT_RULE_FALSE_POSITIVES]: ALERT_RULE_FALSE_POSITIVES, + [ALERT_RULE_MAX_SIGNALS]: ALERT_RULE_MAX_SIGNALS, + [ALERT_RISK_SCORE]: ALERT_RISK_SCORE, + [ALERT_RULE_DESCRIPTION]: ALERT_RULE_DESCRIPTION, + [ALERT_RULE_NAME]: ALERT_RULE_NAME, + [ALERT_RULE_IMMUTABLE]: ALERT_RULE_IMMUTABLE, + [ALERT_RULE_REFERENCES]: ALERT_RULE_REFERENCES, + [ALERT_SEVERITY]: ALERT_SEVERITY, + [ALERT_RULE_TAGS]: ALERT_RULE_TAGS, + [ALERT_RULE_THREAT]: ALERT_RULE_THREAT, + [ALERT_RULE_TYPE]: ALERT_RULE_TYPE, + [ALERT_RULE_SIZE]: ALERT_RULE_SIZE, + [ALERT_RULE_ENABLED]: ALERT_RULE_ENABLED, + [ALERT_RULE_CREATED_AT]: ALERT_RULE_CREATED_AT, + [ALERT_RULE_UPDATED_AT]: ALERT_RULE_UPDATED_AT, + [ALERT_RULE_CREATED_BY]: ALERT_RULE_CREATED_BY, + [ALERT_RULE_UPDATED_BY]: ALERT_RULE_UPDATED_BY, + [ALERT_RULE_VERSION]: ALERT_RULE_VERSION, + [ALERT_RULE_NOTE]: ALERT_RULE_NOTE, + [ALERT_RULE_THRESHOLD]: ALERT_RULE_THRESHOLD, + [ALERT_RULE_EXCEPTIONS_LIST]: ALERT_RULE_EXCEPTIONS_LIST, }; export const ruleFieldsMap: Readonly> = { @@ -337,6 +374,7 @@ export const eventFieldsMap: Readonly> = { '@timestamp': '@timestamp', message: 'message', ...{ ...agentFieldsMap }, + ...{ ...alertFieldsMap }, ...{ ...auditdMap }, ...{ ...destinationFieldsMap }, ...{ ...dnsFieldsMap }, @@ -347,7 +385,6 @@ export const eventFieldsMap: Readonly> = { ...{ ...hostFieldsMap }, ...{ ...networkFieldsMap }, ...{ ...ruleFieldsMap }, - ...{ ...signalFieldsMap }, ...{ ...sourceFieldsMap }, ...{ ...suricataFieldsMap }, ...{ ...systemFieldsMap }, diff --git a/x-pack/plugins/timelines/common/ecs/index.ts b/x-pack/plugins/timelines/common/ecs/index.ts index 8054b3c8521db5..427ed18a0c1eeb 100644 --- a/x-pack/plugins/timelines/common/ecs/index.ts +++ b/x-pack/plugins/timelines/common/ecs/index.ts @@ -14,6 +14,7 @@ import { EventEcs } from './event'; import { FileEcs } from './file'; import { GeoEcs } from './geo'; import { HostEcs } from './host'; +import { KibanaEcs } from './kibana'; import { NetworkEcs } from './network'; import { RegistryEcs } from './registry'; import { RuleEcs } from './rule'; @@ -42,6 +43,7 @@ export interface Ecs { event?: EventEcs; geo?: GeoEcs; host?: HostEcs; + kibana?: KibanaEcs; network?: NetworkEcs; registry?: RegistryEcs; rule?: RuleEcs; diff --git a/x-pack/plugins/timelines/common/ecs/kibana/index.ts b/x-pack/plugins/timelines/common/ecs/kibana/index.ts new file mode 100644 index 00000000000000..5e36da400ccaf6 --- /dev/null +++ b/x-pack/plugins/timelines/common/ecs/kibana/index.ts @@ -0,0 +1,21 @@ +/* + * 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 { RuleEcs } from '../rule'; + +export interface KibanaEcs { + alert?: { + rule?: RuleEcs; + original_time?: string[]; + status?: string[]; + group?: { + id?: string[]; + }; + threshold_result?: unknown; + workflow_status?: string[]; + }; +} diff --git a/x-pack/plugins/timelines/common/ecs/rule/index.ts b/x-pack/plugins/timelines/common/ecs/rule/index.ts index ae7e5064a8eced..d8003b7b0cc2be 100644 --- a/x-pack/plugins/timelines/common/ecs/rule/index.ts +++ b/x-pack/plugins/timelines/common/ecs/rule/index.ts @@ -6,8 +6,8 @@ */ export interface RuleEcs { - id?: string[]; rule_id?: string[]; + uuid?: string[]; name?: string[]; false_positives?: string[]; saved_id?: string[]; diff --git a/x-pack/plugins/timelines/common/index.ts b/x-pack/plugins/timelines/common/index.ts index 2242a6951c7502..340e85f36bc610 100644 --- a/x-pack/plugins/timelines/common/index.ts +++ b/x-pack/plugins/timelines/common/index.ts @@ -11,6 +11,7 @@ export * from './types'; export * from './search_strategy'; export * from './utils/accessibility'; +export * from './alerts'; export const PLUGIN_ID = 'timelines'; export const PLUGIN_NAME = 'timelines'; diff --git a/x-pack/plugins/timelines/common/utils/field_formatters.test.ts b/x-pack/plugins/timelines/common/utils/field_formatters.test.ts index 50a3117e53b9ba..f00269f219984a 100644 --- a/x-pack/plugins/timelines/common/utils/field_formatters.test.ts +++ b/x-pack/plugins/timelines/common/utils/field_formatters.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_WORKFLOW_STATUS, ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { eventDetailsFormattedFields, eventHit } from '@kbn/securitysolution-t-grid'; import { EventHit, EventSource } from '../search_strategy'; import { getDataFromFieldsHits, getDataFromSourceHits, getDataSafety } from './field_formatters'; @@ -135,8 +136,8 @@ describe('Events Details Helpers', () => { it('#getDataFromSourceHits', () => { const _source: EventSource = { '@timestamp': '2021-02-24T00:41:06.527Z', - 'signal.status': 'open', - 'signal.rule.name': 'Rawr', + [ALERT_WORKFLOW_STATUS]: 'open', + [ALERT_RULE_NAME]: 'Rawr', 'threat.indicator': [ { provider: 'yourself', @@ -161,15 +162,15 @@ describe('Events Details Helpers', () => { isObjectArray: false, }, { - category: 'signal', - field: 'signal.status', + category: 'kibana', + field: ALERT_WORKFLOW_STATUS, values: ['open'], originalValue: ['open'], isObjectArray: false, }, { - category: 'signal', - field: 'signal.rule.name', + category: 'kibana', + field: ALERT_RULE_NAME, values: ['Rawr'], originalValue: ['Rawr'], isObjectArray: false, diff --git a/x-pack/plugins/timelines/kibana.json b/x-pack/plugins/timelines/kibana.json index 0239dcdd8f1660..2c9ca1cc4d266a 100644 --- a/x-pack/plugins/timelines/kibana.json +++ b/x-pack/plugins/timelines/kibana.json @@ -7,7 +7,7 @@ "version": "1.0.0", "kibanaVersion": "kibana", "configPath": ["xpack", "timelines"], - "extraPublicDirs": ["common"], + "extraPublicDirs": ["common", "common/alerts"], "server": true, "ui": true, "requiredPlugins": ["alerting", "cases", "data", "dataEnhanced", "kibanaReact", "kibanaUtils"], diff --git a/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_case_action.test.tsx b/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_case_action.test.tsx index 19206c40d18c2d..0764f4fe37e49e 100644 --- a/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_case_action.test.tsx +++ b/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_case_action.test.tsx @@ -28,7 +28,9 @@ describe('AddToCaseAction', () => { ecs: { _id: 'test-id', _index: 'test-index', - signal: { rule: { id: ['rule-id'], name: ['rule-name'], false_positives: [] } }, + kibana: { + alert: { rule: { uuid: ['rule-id'], name: ['rule-name'], false_positives: [] } }, + }, }, }, casePermissions: { @@ -105,7 +107,7 @@ describe('AddToCaseAction', () => { ecs: { _id: 'test-id', _index: 'test-index', - signal: { rule: { id: ['rule-id'], false_positives: [] } }, + kibana: { alert: { rule: { uuid: ['rule-id'], false_positives: [] } } }, }, }} /> @@ -117,7 +119,7 @@ describe('AddToCaseAction', () => { ecs: { _id: 'test-id', _index: 'test-index', - signal: { rule: { id: ['rule-id'], false_positives: [] } }, + kibana: { alert: { rule: { uuid: ['rule-id'], false_positives: [] } } }, }, }} /> diff --git a/x-pack/plugins/timelines/public/components/drag_and_drop/helpers.ts b/x-pack/plugins/timelines/public/components/drag_and_drop/helpers.ts index 5d0c8b6fbd0009..41fd1bdb10a916 100644 --- a/x-pack/plugins/timelines/public/components/drag_and_drop/helpers.ts +++ b/x-pack/plugins/timelines/public/components/drag_and_drop/helpers.ts @@ -10,6 +10,7 @@ import { KEYBOARD_DRAG_OFFSET, getFieldIdFromDraggable } from '@kbn/securitysolu import { Dispatch } from 'redux'; import { isString, keyBy } from 'lodash/fp'; +import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { stopPropagationAndPreventDefault, TimelineId } from '../../../common'; import type { BrowserField, BrowserFields, ColumnHeaderOptions } from '../../../common'; import { tGridActions } from '../../store/t_grid'; @@ -144,7 +145,7 @@ const getAllFieldsByName = ( keyBy('name', getAllBrowserFields(browserFields)); const linkFields: Record = { - 'signal.rule.name': 'signal.rule.id', + [ALERT_RULE_NAME]: ALERT_RULE_NAME, 'event.module': 'rule.reference', }; diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/helpers.test.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/helpers.test.tsx index 2b58487fce53a2..1f47805a9e937b 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/helpers.test.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/helpers.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { omit } from 'lodash/fp'; import { ColumnHeaderOptions } from '../../../../common'; @@ -353,7 +354,7 @@ describe('helpers', () => { expect( allowSorting({ browserField: undefined, // no BrowserField metadata for this field - fieldName: 'signal.rule.name', // an allow-listed field name + fieldName: ALERT_RULE_NAME, // an allow-listed field name }) ).toBe(true); }); @@ -400,7 +401,7 @@ describe('helpers', () => { const mockedSetCellProps = jest.fn(); const ecs = { ...mockDnsEvent, - ...{ signal: { rule: { building_block_type: ['default'] } } }, + ...{ kibana: { alert: { rule: { building_block_type: ['default'] } } } }, }; addBuildingBlockStyle(ecs, THEME, mockedSetCellProps); diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/helpers.tsx index 8781a88c630df3..7c9ac024b14861 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/helpers.tsx @@ -5,10 +5,79 @@ * 2.0. */ -import { ALERT_RULE_CONSUMER, ALERT_RULE_PRODUCER } from '@kbn/rule-data-utils'; +import { + ALERT_REASON, + ALERT_RULE_CONSUMER, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_INTERVAL, + ALERT_RULE_NAME, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RISK_SCORE, + ALERT_RULE_RULE_ID, + ALERT_SEVERITY, + ALERT_RULE_TAGS, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_WORKFLOW_STATUS, + ALERT_RULE_PRODUCER, +} from '@kbn/rule-data-utils'; import { isEmpty } from 'lodash/fp'; - import { EuiDataGridCellValueElementProps } from '@elastic/eui'; +import { + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_SEVERITY, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_TIME, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_QUERY, + ALERT_RULE_SAVED_ID, + ALERT_RULE_SIZE, + ALERT_RULE_THREAT, + ALERT_RULE_THREAT_TACTIC_ID, + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TACTIC_REFERENCE, + ALERT_RULE_THREAT_TECHNIQUE_ID, + ALERT_RULE_THREAT_TECHNIQUE_NAME, + ALERT_RULE_THREAT_TECHNIQUE_REFERENCE, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, +} from '../../../../common/alerts'; + import type { Ecs } from '../../../../common/ecs'; import type { BrowserField, @@ -75,7 +144,7 @@ export const getEventIdToDataMapping = ( }, {}); export const isEventBuildingBlockType = (event: Ecs): boolean => - !isEmpty(event.signal?.rule?.building_block_type); + !isEmpty(event.kibana?.alert?.rule?.building_block_type); export const isEvenEqlSequence = (event: Ecs): boolean => { if (!isEmpty(event.eql?.sequenceNumber)) { @@ -88,10 +157,10 @@ export const isEvenEqlSequence = (event: Ecs): boolean => { } return false; }; -/** Return eventType raw or signal or eql */ +/** Return eventType raw or kibana or eql */ export const getEventType = (event: Ecs): Omit => { - if (!isEmpty(event.signal?.rule?.id)) { - return 'signal'; + if (!isEmpty(event.kibana?.alert?.rule?.uuid)) { + return 'kibana.alert'; } else if (!isEmpty(event.eql?.parentId)) { return 'eql'; } @@ -138,77 +207,72 @@ export const allowSorting = ({ }): boolean => { const isAggregatable = browserField?.aggregatable ?? false; - const isAllowlistedNonBrowserField = [ - 'signal.ancestors.depth', - 'signal.ancestors.id', - 'signal.ancestors.rule', - 'signal.ancestors.type', - 'signal.original_event.action', - 'signal.original_event.category', - 'signal.original_event.code', - 'signal.original_event.created', - 'signal.original_event.dataset', - 'signal.original_event.duration', - 'signal.original_event.end', - 'signal.original_event.hash', - 'signal.original_event.id', - 'signal.original_event.kind', - 'signal.original_event.module', - 'signal.original_event.original', - 'signal.original_event.outcome', - 'signal.original_event.provider', - 'signal.original_event.risk_score', - 'signal.original_event.risk_score_norm', - 'signal.original_event.sequence', - 'signal.original_event.severity', - 'signal.original_event.start', - 'signal.original_event.timezone', - 'signal.original_event.type', - 'signal.original_time', - 'signal.parent.depth', - 'signal.parent.id', - 'signal.parent.index', - 'signal.parent.rule', - 'signal.parent.type', - 'signal.reason', - 'signal.rule.created_by', - 'signal.rule.description', - 'signal.rule.enabled', - 'signal.rule.false_positives', - 'signal.rule.filters', - 'signal.rule.from', - 'signal.rule.id', - 'signal.rule.immutable', - 'signal.rule.index', - 'signal.rule.interval', - 'signal.rule.language', - 'signal.rule.max_signals', - 'signal.rule.name', - 'signal.rule.note', - 'signal.rule.output_index', - 'signal.rule.query', - 'signal.rule.references', - 'signal.rule.risk_score', - 'signal.rule.rule_id', - 'signal.rule.saved_id', - 'signal.rule.severity', - 'signal.rule.size', - 'signal.rule.tags', - 'signal.rule.threat', - 'signal.rule.threat.tactic.id', - 'signal.rule.threat.tactic.name', - 'signal.rule.threat.tactic.reference', - 'signal.rule.threat.technique.id', - 'signal.rule.threat.technique.name', - 'signal.rule.threat.technique.reference', - 'signal.rule.timeline_id', - 'signal.rule.timeline_title', - 'signal.rule.to', - 'signal.rule.type', - 'signal.rule.updated_by', - 'signal.rule.version', - 'signal.status', - ].includes(fieldName); + const isAllowlistedNonBrowserField = ([ + ALERT_ANCESTORS_DEPTH, + ALERT_ANCESTORS_ID, + ALERT_ANCESTORS_INDEX, + ALERT_ANCESTORS_RULE, + ALERT_ANCESTORS_TYPE, + ALERT_ORIGINAL_EVENT_ACTION, + ALERT_ORIGINAL_EVENT_CATEGORY, + ALERT_ORIGINAL_EVENT_CODE, + ALERT_ORIGINAL_EVENT_CREATED, + ALERT_ORIGINAL_EVENT_DATASET, + ALERT_ORIGINAL_EVENT_DURATION, + ALERT_ORIGINAL_EVENT_END, + ALERT_ORIGINAL_EVENT_HASH, + ALERT_ORIGINAL_EVENT_ID, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_ORIGINAL_EVENT_ORIGINAL, + ALERT_ORIGINAL_EVENT_OUTCOME, + ALERT_ORIGINAL_EVENT_PROVIDER, + ALERT_ORIGINAL_EVENT_RISK_SCORE, + ALERT_ORIGINAL_EVENT_RISK_SCORE_NORM, + ALERT_ORIGINAL_EVENT_SEQUENCE, + ALERT_ORIGINAL_EVENT_SEVERITY, + ALERT_ORIGINAL_EVENT_START, + ALERT_ORIGINAL_EVENT_TIMEZONE, + ALERT_ORIGINAL_EVENT_TYPE, + ALERT_ORIGINAL_TIME, + ALERT_REASON, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FALSE_POSITIVES, + ALERT_RULE_FILTERS, + ALERT_RULE_FROM, + ALERT_RULE_UUID, + ALERT_RULE_IMMUTABLE, + ALERT_RULE_INDEX, + ALERT_RULE_INTERVAL, + ALERT_RULE_LANGUAGE, + ALERT_RULE_MAX_SIGNALS, + ALERT_RULE_NAME, + ALERT_RULE_NOTE, + ALERT_RULE_QUERY, + ALERT_RULE_REFERENCES, + ALERT_RISK_SCORE, + ALERT_RULE_RULE_ID, + ALERT_RULE_SAVED_ID, + ALERT_SEVERITY, + ALERT_RULE_SIZE, + ALERT_RULE_TAGS, + ALERT_RULE_THREAT, + ALERT_RULE_THREAT_TACTIC_ID, + ALERT_RULE_THREAT_TACTIC_NAME, + ALERT_RULE_THREAT_TACTIC_REFERENCE, + ALERT_RULE_THREAT_TECHNIQUE_ID, + ALERT_RULE_THREAT_TECHNIQUE_NAME, + ALERT_RULE_THREAT_TECHNIQUE_REFERENCE, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_WORKFLOW_STATUS, + ] as string[]).includes(fieldName); return isAllowlistedNonBrowserField || isAggregatable; }; diff --git a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx index c04cc58f453c3a..47179fb683e48d 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/event_rendered_view/index.tsx @@ -15,7 +15,7 @@ import { EuiHorizontalRule, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; +import { ALERT_REASON, ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import { get } from 'lodash'; import moment from 'moment'; import React, { ComponentType, useCallback, useMemo } from 'react'; @@ -164,8 +164,8 @@ const EventRenderedViewComponent = ({ hideForMobile: false, // eslint-disable-next-line react/display-name render: (name: unknown, item: TimelineItem) => { - const ruleName = get(item, `ecs.signal.rule.name`); /* `ecs.${ALERT_RULE_NAME}`*/ - const ruleId = get(item, `ecs.signal.rule.id`); /* `ecs.${ALERT_RULE_ID}`*/ + const ruleName = get(item, `ecs.${ALERT_RULE_NAME}`); + const ruleId = get(item, `ecs.${ALERT_RULE_UUID}`); return ; }, }, @@ -179,7 +179,7 @@ const EventRenderedViewComponent = ({ // eslint-disable-next-line react/display-name render: (name: unknown, item: TimelineItem) => { const ecsData = get(item, 'ecs'); - const reason = get(item, `ecs.signal.reason`); /* `ecs.${ALERT_REASON}`*/ + const reason = get(item, `ecs.${ALERT_REASON}`); const rowRenderersValid = rowRenderers.filter((rowRenderer) => rowRenderer.isInstance(ecsData) ); diff --git a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx index 5fe766077a74c9..512ba1f5af25f7 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx @@ -9,7 +9,6 @@ import type { Filter, EsQueryConfig, Query } from '@kbn/es-query'; import { FilterStateStore } from '@kbn/es-query'; import { isEmpty, get } from 'lodash/fp'; import memoizeOne from 'memoize-one'; -import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { elementOrChildrenHasFocus, getFocusedAriaColindexCell, @@ -192,7 +191,7 @@ export const buildCombinedQuery = (combineQueriesParams: CombineQueries) => { const combinedQuery = combineQueries(combineQueriesParams); return combinedQuery ? { - filterQuery: replaceStatusField(combinedQuery!.filterQuery), + filterQuery: combinedQuery!.filterQuery, } : null; }; @@ -229,23 +228,12 @@ export const getCombinedFilterQuery = ({ filters, ...combineQueriesParams }: CombineQueries & { from: string; to: string }): string => { - return replaceStatusField( - combineQueries({ - ...combineQueriesParams, - filters: [...filters, buildTimeRangeFilter(from, to)], - })!.filterQuery - ); + return combineQueries({ + ...combineQueriesParams, + filters: [...filters, buildTimeRangeFilter(from, to)], + })!.filterQuery; }; -/** - * This function is a temporary patch to prevent queries using old `signal.status` field. - * @todo The `signal.status` field should not be queried anymore and - * must be replaced by `ALERT_WORKFLOW_STATUS` field name constant - * @deprecated - */ -const replaceStatusField = (query: string): string => - query.replaceAll('signal.status', ALERT_WORKFLOW_STATUS); - /** * The CSS class name of a "stateful event", which appears in both * the `Timeline` and the `Events Viewer` widget diff --git a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_items.test.tsx b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_items.test.tsx index 789aeeeb187fdd..f7c870a8592a01 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_items.test.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_items.test.tsx @@ -8,6 +8,7 @@ import { omit } from 'lodash/fp'; import React from 'react'; import { waitFor } from '@testing-library/react'; +import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import { mockBrowserFields, TestProviders } from '../../../../mock'; import { defaultColumnHeaderType } from '../../body/column_headers/default_headers'; import { DEFAULT_DATE_COLUMN_MIN_WIDTH } from '../../body/constants'; @@ -193,20 +194,20 @@ describe('field_items', () => { }); }); - test('it returns the expected signal column settings', async () => { - const mockSelectedCategoryId = 'signal'; - const mockBrowserFieldsWithSignal = { + test('it returns the expected kibana column settings', async () => { + const mockSelectedCategoryId = 'kibana'; + const mockBrowserFieldsWithAlert = { ...mockBrowserFields, - signal: { + kibana: { fields: { - 'signal.rule.name': { + [ALERT_RULE_NAME]: { aggregatable: true, - category: 'signal', + category: 'kibana', description: 'rule name', example: '', format: '', indexes: ['auditbeat', 'filebeat', 'packetbeat'], - name: 'signal.rule.name', + name: ALERT_RULE_NAME, searchable: true, type: 'string', }, @@ -219,9 +220,9 @@ describe('field_items', () => { { ); wrapper - .find(`[data-test-subj="field-signal.rule.name-checkbox"]`) + .find(`[data-test-subj="field-${ALERT_RULE_NAME}-checkbox"]`) .last() .simulate('change', { target: { checked: true }, @@ -244,7 +245,7 @@ describe('field_items', () => { await waitFor(() => { expect(toggleColumn).toBeCalledWith({ columnHeaderType: 'not-filtered', - id: 'signal.rule.name', + id: ALERT_RULE_NAME, initialWidth: 180, }); }); diff --git a/x-pack/plugins/timelines/public/container/index.tsx b/x-pack/plugins/timelines/public/container/index.tsx index 30245ea9f17afc..c884327c978b2c 100644 --- a/x-pack/plugins/timelines/public/container/index.tsx +++ b/x-pack/plugins/timelines/public/container/index.tsx @@ -141,7 +141,7 @@ export const useTimelineEvents = ({ ); const prevTimelineRequest = useRef | null>(null); - const clearSignalsState = useCallback(() => { + const clearAlertsState = useCallback(() => { if (id != null && detectionsTimelineIds.some((timelineId) => timelineId === id)) { dispatch(tGridActions.clearEventsLoading({ id })); dispatch(tGridActions.clearEventsDeleted({ id })); @@ -150,10 +150,10 @@ export const useTimelineEvents = ({ const wrappedLoadPage = useCallback( (newActivePage: number) => { - clearSignalsState(); + clearAlertsState(); setActivePage(newActivePage); }, - [clearSignalsState] + [clearAlertsState] ); const refetchGrid = useCallback(() => { @@ -194,7 +194,6 @@ export const useTimelineEvents = ({ if (request == null || skip) { return; } - const asyncSearch = async () => { prevTimelineRequest.current = request; abortCtrl.current = new AbortController(); 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 a1490834b24b97..0b77985be71702 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 @@ -8,7 +8,7 @@ import { get, isEmpty } from 'lodash/fp'; import { useState, useCallback, useMemo, SyntheticEvent } from 'react'; import { useLocation } from 'react-router-dom'; import { useDispatch } from 'react-redux'; -import { ALERT_RULE_NAME, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; +import { ALERT_RULE_NAME, ALERT_RULE_UUID, ALERT_UUID } from '@kbn/rule-data-utils'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { Case, SubCase } from '../../../cases/common'; import { TimelinesStartServices } from '../types'; @@ -120,13 +120,13 @@ export const useAddToCase = ({ const isAlert = useMemo(() => { if (event !== undefined) { const data = [...event.data]; - return data.some(({ field }) => field === 'kibana.alert.uuid'); + return data.some(({ field }) => field === ALERT_UUID); } else { return false; } }, [event]); const isSecurityAlert = useMemo(() => { - return !isEmpty(event?.ecs.signal?.rule?.id); + return !isEmpty(event?.ecs.kibana?.alert?.rule?.uuid); }, [event]); const isEventSupported = isSecurityAlert || isAlert; const userCanCrud = casePermissions?.crud ?? false; diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/constants.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/constants.ts index 8e8798d89a64cf..32a86ce67c35a1 100644 --- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/constants.ts +++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/constants.ts @@ -5,7 +5,38 @@ * 2.0. */ -import { ALERT_RULE_CONSUMER } from '@kbn/rule-data-utils'; +import { + ALERT_RULE_CONSUMER, + ALERT_RULE_FROM, + ALERT_RULE_NAME, + ALERT_RULE_TO, + ALERT_RULE_UUID, + ALERT_RULE_TYPE, + ALERT_RULE_VERSION, + ALERT_SEVERITY, + ALERT_RISK_SCORE, + ALERT_RULE_NOTE, + ALERT_REASON, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; +import { + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_RULE_FILTERS, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_INDEX, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_THRESHOLD_RESULT, + ALERT_RULE_EXCEPTIONS_LIST, + ALERT_RULE_SAVED_ID, + ALERT_RULE_THRESHOLD, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_BUILDING_BLOCK_TYPE, +} from '../../../../../../common/alerts'; + // import { CTI_ROW_RENDERER_FIELDS } from '../../../../../../common/cti/constants'; // TODO: share with security_solution/common/cti/constants.ts @@ -43,25 +74,25 @@ export const CTI_ROW_RENDERER_FIELDS = [ export const TIMELINE_EVENTS_FIELDS = [ ALERT_RULE_CONSUMER, '@timestamp', - 'signal.status', - 'signal.group.id', - 'signal.original_time', - 'signal.reason', - 'signal.rule.filters', - 'signal.rule.from', - 'signal.rule.language', - 'signal.rule.query', - 'signal.rule.name', - 'signal.rule.to', - 'signal.rule.id', - 'signal.rule.index', - 'signal.rule.type', - 'signal.original_event.kind', - 'signal.original_event.module', - 'signal.rule.version', - 'signal.rule.severity', - 'signal.rule.risk_score', - 'signal.threshold_result', + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_REASON, + ALERT_RULE_FILTERS, + ALERT_RULE_FROM, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_NAME, + ALERT_RULE_TO, + ALERT_RULE_UUID, + ALERT_RULE_INDEX, + ALERT_RULE_TYPE, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, + ALERT_RULE_VERSION, + ALERT_SEVERITY, + ALERT_RISK_SCORE, + ALERT_THRESHOLD_RESULT, + ALERT_WORKFLOW_STATUS, 'event.code', 'event.module', 'event.action', @@ -172,14 +203,13 @@ export const TIMELINE_EVENTS_FIELDS = [ 'endgame.target_domain_name', 'endgame.target_logon_id', 'endgame.target_user_name', - 'signal.rule.saved_id', - 'signal.rule.timeline_id', - 'signal.rule.timeline_title', - 'signal.rule.output_index', - 'signal.rule.note', - 'signal.rule.threshold', - 'signal.rule.exceptions_list', - 'signal.rule.building_block_type', + ALERT_RULE_SAVED_ID, + ALERT_RULE_TIMELINE_ID, + ALERT_RULE_TIMELINE_TITLE, + ALERT_RULE_NOTE, + ALERT_RULE_THRESHOLD, + ALERT_RULE_EXCEPTIONS_LIST, + ALERT_RULE_BUILDING_BLOCK_TYPE, 'suricata.eve.proto', 'suricata.eve.flow_id', 'suricata.eve.alert.signature', @@ -217,6 +247,7 @@ export const TIMELINE_EVENTS_FIELDS = [ 'process.executable', 'process.title', 'process.working_directory', + 'signal.rule.threshold', 'zeek.session_id', 'zeek.connection.local_resp', 'zeek.connection.local_orig', diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/helpers.test.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/helpers.test.ts index 4fb67cc3a79743..f1d0ece6f81768 100644 --- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/helpers.test.ts +++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/all/helpers.test.ts @@ -5,7 +5,24 @@ * 2.0. */ +import { + ALERT_RULE_FROM, + ALERT_RULE_TYPE, + ALERT_RULE_UUID, + ALERT_RISK_SCORE, + ALERT_WORKFLOW_STATUS, + ALERT_SEVERITY, + ALERT_RULE_VERSION, + ALERT_RULE_NAME, + ALERT_RULE_TO, +} from '@kbn/rule-data-utils'; import { eventHit } from '@kbn/securitysolution-t-grid'; +import { + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_INDEX, + ALERT_ORIGINAL_TIME, +} from '../../../../../../common/alerts'; import { EventHit } from '../../../../../../common/search_strategy'; import { TIMELINE_EVENTS_FIELDS } from './constants'; import { buildObjectForFieldPath, formatTimelineData } from './helpers'; @@ -125,158 +142,158 @@ describe('#formatTimelineData', () => { }); }); - it('rule signal results', async () => { + it('rule alert results', async () => { const response: EventHit = { _index: '.siem-signals-patrykkopycinski-default-000007', _id: 'a77040f198355793c35bf22b900902371309be615381f0a2ec92c208b6132562', _score: 0, _source: { - signal: { - threshold_result: { - count: 10000, - value: '2a990c11-f61b-4c8e-b210-da2574e9f9db', - }, - parent: { - depth: 0, - index: - 'apm-*-transaction*,traces-apm*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', - id: '0268af90-d8da-576a-9747-2a191519416a', - type: 'event', - }, - depth: 1, - _meta: { - version: 14, - }, - rule: { - note: null, - throttle: null, - references: [], - severity_mapping: [], - description: 'asdasd', - created_at: '2021-01-09T11:25:45.046Z', - language: 'kuery', - threshold: { - field: '', - value: 200, - }, - building_block_type: null, - output_index: '.siem-signals-patrykkopycinski-default', - type: 'threshold', - rule_name_override: null, - enabled: true, - exceptions_list: [], - updated_at: '2021-01-09T13:36:39.204Z', - timestamp_override: null, - from: 'now-360s', - id: '696c24e0-526d-11eb-836c-e1620268b945', - timeline_id: null, - max_signals: 100, - severity: 'low', - risk_score: 21, - risk_score_mapping: [], - author: [], - query: '_id :*', - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - filters: [ - { - $state: { - store: 'appState', - }, - meta: { - negate: false, - alias: null, - disabled: false, - type: 'exists', - value: 'exists', - key: '_index', - }, - exists: { - field: '_index', - }, - }, - { - $state: { - store: 'appState', - }, - meta: { - negate: false, - alias: 'id_exists', - disabled: false, - type: 'exists', - value: 'exists', - key: '_id', - }, - exists: { - field: '_id', - }, - }, - ], - created_by: 'patryk_test_user', - version: 1, - saved_id: null, - tags: [], - rule_id: '2a990c11-f61b-4c8e-b210-da2574e9f9db', - license: '', - immutable: false, - timeline_title: null, - meta: { - from: '1m', - kibana_siem_app_url: 'http://localhost:5601/app/security', + kibana: { + alert: { + threshold_result: { + count: 10000, + value: '2a990c11-f61b-4c8e-b210-da2574e9f9db', }, - name: 'Threshold test', - updated_by: 'patryk_test_user', - interval: '5m', - false_positives: [], - to: 'now', - threat: [], - actions: [], - }, - original_time: '2021-01-09T13:39:32.595Z', - ancestors: [ - { + parent: { depth: 0, index: 'apm-*-transaction*,traces-apm*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', id: '0268af90-d8da-576a-9747-2a191519416a', type: 'event', }, - ], - parents: [ - { - depth: 0, - index: - 'apm-*-transaction*,traces-apm*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', - id: '0268af90-d8da-576a-9747-2a191519416a', - type: 'event', + depth: 1, + _meta: { + version: 14, }, - ], - status: 'open', + rule: { + note: null, + throttle: null, + references: [], + severity_mapping: [], + description: 'asdasd', + created_at: '2021-01-09T11:25:45.046Z', + language: 'kuery', + threshold: { + field: '', + value: 200, + }, + building_block_type: null, + type: 'threshold', + rule_name_override: null, + enabled: true, + exceptions_list: [], + updated_at: '2021-01-09T13:36:39.204Z', + timestamp_override: null, + from: 'now-360s', + id: '696c24e0-526d-11eb-836c-e1620268b945', + timeline_id: null, + max_signals: 100, + severity: 'low', + risk_score: 21, + risk_score_mapping: [], + author: [], + query: '_id :*', + index: [ + 'apm-*-transaction*', + 'traces-apm*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + filters: [ + { + $state: { + store: 'appState', + }, + meta: { + negate: false, + alias: null, + disabled: false, + type: 'exists', + value: 'exists', + key: '_index', + }, + exists: { + field: '_index', + }, + }, + { + $state: { + store: 'appState', + }, + meta: { + negate: false, + alias: 'id_exists', + disabled: false, + type: 'exists', + value: 'exists', + key: '_id', + }, + exists: { + field: '_id', + }, + }, + ], + created_by: 'patryk_test_user', + version: 1, + saved_id: null, + tags: [], + rule_id: '2a990c11-f61b-4c8e-b210-da2574e9f9db', + license: '', + immutable: false, + timeline_title: null, + meta: { + from: '1m', + kibana_siem_app_url: 'http://localhost:5601/app/security', + }, + name: 'Threshold test', + updated_by: 'patryk_test_user', + interval: '5m', + false_positives: [], + to: 'now', + threat: [], + actions: [], + }, + original_time: '2021-01-09T13:39:32.595Z', + ancestors: [ + { + depth: 0, + index: + 'apm-*-transaction*,traces-apm*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', + id: '0268af90-d8da-576a-9747-2a191519416a', + type: 'event', + }, + ], + parents: [ + { + depth: 0, + index: + 'apm-*-transaction*,traces-apm*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*', + id: '0268af90-d8da-576a-9747-2a191519416a', + type: 'event', + }, + ], + workflow_status: 'open', + }, }, }, fields: { - 'signal.rule.output_index': ['.siem-signals-patrykkopycinski-default'], - 'signal.rule.from': ['now-360s'], - 'signal.rule.language': ['kuery'], + [ALERT_RULE_FROM]: ['now-360s'], + [ALERT_RULE_LANGUAGE]: ['kuery'], '@timestamp': ['2021-01-09T13:41:40.517Z'], - 'signal.rule.query': ['_id :*'], - 'signal.rule.type': ['threshold'], - 'signal.rule.id': ['696c24e0-526d-11eb-836c-e1620268b945'], - 'signal.rule.risk_score': [21], - 'signal.status': ['open'], + [ALERT_RULE_QUERY]: ['_id :*'], + [ALERT_RULE_TYPE]: ['threshold'], + [ALERT_RULE_UUID]: ['696c24e0-526d-11eb-836c-e1620268b945'], + [ALERT_RISK_SCORE]: [21], + [ALERT_WORKFLOW_STATUS]: ['open'], 'event.kind': ['signal'], - 'signal.original_time': ['2021-01-09T13:39:32.595Z'], - 'signal.rule.severity': ['low'], - 'signal.rule.version': ['1'], - 'signal.rule.index': [ + [ALERT_ORIGINAL_TIME]: ['2021-01-09T13:39:32.595Z'], + [ALERT_SEVERITY]: ['low'], + [ALERT_RULE_VERSION]: ['1'], + [ALERT_RULE_INDEX]: [ 'apm-*-transaction*', 'traces-apm*', 'auditbeat-*', @@ -286,8 +303,8 @@ describe('#formatTimelineData', () => { 'packetbeat-*', 'winlogbeat-*', ], - 'signal.rule.name': ['Threshold test'], - 'signal.rule.to': ['now'], + [ALERT_RULE_NAME]: ['Threshold test'], + [ALERT_RULE_TO]: ['now'], }, _type: '', sort: ['1610199700517'], @@ -321,78 +338,79 @@ describe('#formatTimelineData', () => { event: { kind: ['signal'], }, - signal: { - original_time: ['2021-01-09T13:39:32.595Z'], - status: ['open'], - threshold_result: ['{"count":10000,"value":"2a990c11-f61b-4c8e-b210-da2574e9f9db"}'], - rule: { - building_block_type: [], - exceptions_list: [], - from: ['now-360s'], - id: ['696c24e0-526d-11eb-836c-e1620268b945'], - index: [ - 'apm-*-transaction*', - 'traces-apm*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ], - language: ['kuery'], - name: ['Threshold test'], - output_index: ['.siem-signals-patrykkopycinski-default'], + kibana: { + alert: { + original_time: ['2021-01-09T13:39:32.595Z'], risk_score: ['21'], - query: ['_id :*'], + workflow_status: ['open'], severity: ['low'], - to: ['now'], - type: ['threshold'], - version: ['1'], - timeline_id: [], - timeline_title: [], - saved_id: [], - note: [], - threshold: [ - JSON.stringify({ - field: '', - value: 200, - }), - ], - filters: [ - JSON.stringify({ - $state: { - store: 'appState', - }, - meta: { - negate: false, - alias: null, - disabled: false, - type: 'exists', - value: 'exists', - key: '_index', - }, - exists: { - field: '_index', - }, - }), - JSON.stringify({ - $state: { - store: 'appState', - }, - meta: { - negate: false, - alias: 'id_exists', - disabled: false, - type: 'exists', - value: 'exists', - key: '_id', - }, - exists: { - field: '_id', - }, - }), - ], + threshold_result: ['{"count":10000,"value":"2a990c11-f61b-4c8e-b210-da2574e9f9db"}'], + rule: { + building_block_type: [], + exceptions_list: [], + from: ['now-360s'], + uuid: ['696c24e0-526d-11eb-836c-e1620268b945'], + index: [ + 'apm-*-transaction*', + 'traces-apm*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + language: ['kuery'], + name: ['Threshold test'], + query: ['_id :*'], + to: ['now'], + type: ['threshold'], + version: ['1'], + timeline_id: [], + timeline_title: [], + saved_id: [], + note: [], + threshold: [ + JSON.stringify({ + field: '', + value: 200, + }), + ], + filters: [ + JSON.stringify({ + $state: { + store: 'appState', + }, + meta: { + negate: false, + alias: null, + disabled: false, + type: 'exists', + value: 'exists', + key: '_index', + }, + exists: { + field: '_index', + }, + }), + JSON.stringify({ + $state: { + store: 'appState', + }, + meta: { + negate: false, + alias: 'id_exists', + disabled: false, + type: 'exists', + value: 'exists', + key: '_id', + }, + exists: { + field: '_id', + }, + }), + ], + }, }, }, }, diff --git a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/query.events_details.dsl.test.ts b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/query.events_details.dsl.test.ts index 3572a2b9c497ed..ed4b1d82e7c13c 100644 --- a/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/query.events_details.dsl.test.ts +++ b/x-pack/plugins/timelines/server/search_strategy/timeline/factory/events/details/query.events_details.dsl.test.ts @@ -9,7 +9,7 @@ import { buildTimelineDetailsQuery } from './query.events_details.dsl'; describe('buildTimelineDetailsQuery', () => { it('returns the expected query', () => { - const indexName = '.siem-signals-default'; + const indexName = '.alerts-security.alerts-default'; const eventId = 'f0a936d50b5b3a5a193d415459c14587fe633f7e519df7b5dc151d56142680e3'; const docValueFields = [ { field: '@timestamp' }, @@ -54,7 +54,7 @@ describe('buildTimelineDetailsQuery', () => { }, }, "ignoreUnavailable": true, - "index": ".siem-signals-default", + "index": ".alerts-security.alerts-default", "size": 1, } `); diff --git a/x-pack/test/api_integration/apis/security_solution/utils.ts b/x-pack/test/api_integration/apis/security_solution/utils.ts index c17a6abca27f1b..7e23322eaf97e5 100644 --- a/x-pack/test/api_integration/apis/security_solution/utils.ts +++ b/x-pack/test/api_integration/apis/security_solution/utils.ts @@ -4,8 +4,28 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { + ALERT_RULE_FROM, + ALERT_RULE_NAME, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UUID, + ALERT_WORKFLOW_STATUS, +} from '@kbn/rule-data-utils'; import { JsonObject, JsonArray } from '@kbn/utility-types'; +import { + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_RULE_BUILDING_BLOCK_TYPE, + ALERT_RULE_FILTERS, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_INDEX, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, +} from '../../../../plugins/timelines/common'; + export const getFilterValue = (hostName: string, from: string, to: string): JsonObject => ({ bool: { filter: [ @@ -37,6 +57,7 @@ export const getFilterValue = (hostName: string, from: string, to: string): Json }, }); +// TODO: Revert these to pure strings to avoid pulling in logic from other plugins export const getFieldsToRequest = (): string[] => [ '@timestamp', 'message', @@ -47,21 +68,21 @@ export const getFieldsToRequest = (): string[] => [ 'destination.ip', 'user.name', '@timestamp', - 'signal.status', - 'signal.group.id', - 'signal.original_time', - 'signal.rule.building_block_type', - 'signal.rule.filters', - 'signal.rule.from', - 'signal.rule.language', - 'signal.rule.query', - 'signal.rule.name', - 'signal.rule.to', - 'signal.rule.id', - 'signal.rule.index', - 'signal.rule.type', - 'signal.original_event.kind', - 'signal.original_event.module', + ALERT_WORKFLOW_STATUS, + ALERT_GROUP_ID, + ALERT_ORIGINAL_TIME, + ALERT_RULE_BUILDING_BLOCK_TYPE, + ALERT_RULE_FILTERS, + ALERT_RULE_FROM, + ALERT_RULE_LANGUAGE, + ALERT_RULE_QUERY, + ALERT_RULE_NAME, + ALERT_RULE_TO, + ALERT_RULE_UUID, + ALERT_RULE_INDEX, + ALERT_RULE_TYPE, + ALERT_ORIGINAL_EVENT_KIND, + ALERT_ORIGINAL_EVENT_MODULE, 'file.path', 'file.Ext.code_signature.subject_name', 'file.Ext.code_signature.trusted',