diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts index 744742f64eb4..2362a6a392a5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/schedule_notification_actions.ts @@ -34,7 +34,7 @@ const convertToLegacyAlert = (alert: RACAlert) => * Formats alerts before sending to `scheduleActions`. We augment the context with * the equivalent "legacy" alert context so that pre-8.0 actions will continue to work. */ -const formatAlertsForNotificationActions = (alerts: unknown[]) => { +const formatAlertsForNotificationActions = (alerts: unknown[]): unknown[] => { return alerts.map((alert) => isRACAlert(alert) ? { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts index efdaf2377872..018220e40093 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.test.ts @@ -69,4 +69,21 @@ describe('Expand Dotted', () => { flat: 'yep', }); }); + + it('expands non dotted field without changing it other than reference', () => { + const simpleDottedObj = { + test: { value: '123' }, + }; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); + + it('expands empty object without changing it other than reference', () => { + const simpleDottedObj = {}; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); + + it('if we allow arrays as a type, it should not touch them', () => { + const simpleDottedObj: string[] = ['hello']; + expect(expandDottedObject(simpleDottedObj)).toEqual(simpleDottedObj); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts index 69a9cb8236cb..f90f589486ff 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/expand_dotted.ts @@ -45,6 +45,9 @@ const expandDottedField = (dottedFieldName: string, val: unknown): object => { * } */ export const expandDottedObject = (dottedObj: object) => { + if (Array.isArray(dottedObj)) { + return dottedObj; + } return Object.entries(dottedObj).reduce( (acc, [key, val]) => merge(acc, expandDottedField(key, val)), {} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 48def86203e9..8da9267daaba 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -8,6 +8,7 @@ import moment from 'moment'; import sinon from 'sinon'; import { TransportResult } from '@elastic/elasticsearch'; +import { ALERT_UUID } from '@kbn/rule-data-utils'; import { alertsMock, AlertServicesMock } from '../../../../../alerting/server/mocks'; import { listMock } from '../../../../../lists/server/mocks'; @@ -41,6 +42,7 @@ import { getValidDateFromDoc, calculateTotal, getTotalHitsValue, + isRACAlert, } from './utils'; import { BulkResponseErrorAggregation, SearchAfterAndBulkCreateReturnType } from './types'; import { @@ -1519,4 +1521,52 @@ describe('utils', () => { expect(calculateTotal(undefined, 2)).toBe(-1); }); }); + + describe('isRACAlert', () => { + test('alert with dotted fields returns true', () => { + expect( + isRACAlert({ + [ALERT_UUID]: '123', + }) + ).toEqual(true); + }); + + test('alert with nested fields returns true', () => { + expect( + isRACAlert({ + kibana: { + alert: { uuid: '123' }, + }, + }) + ).toEqual(true); + }); + + test('undefined returns false', () => { + expect(isRACAlert(undefined)).toEqual(false); + }); + + test('null returns false', () => { + expect(isRACAlert(null)).toEqual(false); + }); + + test('number returns false', () => { + expect(isRACAlert(5)).toEqual(false); + }); + + test('string returns false', () => { + expect(isRACAlert('a')).toEqual(false); + }); + + test('array returns false', () => { + expect(isRACAlert([])).toEqual(false); + }); + + test('empty object returns false', () => { + expect(isRACAlert({})).toEqual(false); + }); + + test('alert with null value returns false', () => { + expect(isRACAlert({ 'kibana.alert.uuid': null })).toEqual(false); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 7cdcae96490a..8a59d71fe74e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -986,7 +986,7 @@ export const isWrappedRACAlert = (event: SimpleHit): event is WrappedRACAlert => }; export const isRACAlert = (event: unknown): event is RACAlert => { - return (event as RACAlert)?.[ALERT_UUID] != null; + return get(event, ALERT_UUID) != null; }; export const racFieldMappings: Record = {