From 69e7066f3eb224bd282d58891f90828983b1b407 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko Date: Tue, 7 Nov 2023 16:43:27 +0000 Subject: [PATCH 1/4] [Security Solution][Detection engine] fix dedupliaction ES|QL test --- .../rule_execution_logic/esql.ts | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts index 9ae0bf9773de6..9c428c0049674 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts @@ -20,12 +20,15 @@ import { previewRule, createRule, getOpenSignals as getOpenAlerts, + waitForEventLogExecuteComplete, + getSignalsByIds as getAlertsByIds, } from '../../utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { previewRuleWithExceptionEntries } from '../../utils/preview_rule_with_exception_entries'; import { deleteAllExceptions } from '../../../lists_api_integration/utils'; import { dataGeneratorFactory } from '../../utils/data_generator'; import { removeRandomValuedProperties } from './utils'; +import { patchRule } from '../../utils/patch_rule'; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { @@ -710,19 +713,24 @@ export default ({ getService }: FtrProviderContext) => { expect(previewAlerts.length).toBe(150); }); - // as per https://github.com/elastic/kibana/pull/170034, test is failing on CI and flaky locally - // skipping it for now for further investigation - it.skip('should generate alerts when docs overlap execution intervals and alerts number reached max_signals in one of the executions', async () => { + // we use actual rule executions, not preview, because for preview API alerts index refresh=false for non suppressed alerts + // first rule execution catches 130 documents and generates 100 alerts + // second rule execution catches 150 docs, 120 of which were captured during the first execution and generates only 60 alerts. Because rest are deduplicated + // so in total we 160 alerts should be generated + it.only('should generate alerts when docs overlap execution intervals and alerts number reached max_signals in one of the real executions', async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = { - ...getCreateEsqlRulesSchemaMock('rule-1', true), + ...getCreateEsqlRulesSchemaMock(`rule-${id}`, true), query: `from ecs_compliant [metadata _id] ${internalIdPipe( id )} | keep _id, agent.name | sort agent.name`, - from: 'now-45m', - interval: '30m', + from: '2020-10-28T05:15:00.000Z', + to: '2020-10-28T06:00:00.000Z', + interval: '45m', max_signals: 100, + enabled: true, }; + const createdRule = await createRule(supertest, log, rule); // docs fall in first rule executions await indexGeneratedDocuments({ @@ -772,20 +780,35 @@ export default ({ getService }: FtrProviderContext) => { }), }); - const { previewId } = await previewRule({ - supertest, - rule, - timeframeEnd: new Date('2020-10-28T06:30:00.000Z'), - invocationCount: 2, + // first rule run should generate 100 alerts from first 3 batches of index documents + await waitForEventLogExecuteComplete(es, log, createdRule.id, 1); + + // refresh alerts index, so we can get all created alerts + await es.indices.refresh({ index: '.alerts-security.alerts-*' }); + + await patchRule(supertest, log, { + id: createdRule.id, + enabled: false, }); - const previewAlerts = await getPreviewAlerts({ - es, - previewId, - size: 200, + + // re-trigger rule execution with new interval + await patchRule(supertest, log, { + id: createdRule.id, + from: '2020-10-28T05:45:00.000Z', + to: '2020-10-28T06:30:00.000Z', + enabled: true, }); - // should generate 160 alerts - expect(previewAlerts.length).toBe(160); + // second rule run should generate only 60 new alerts, the rest should be deduplicated + await waitForEventLogExecuteComplete(es, log, createdRule.id, 2); + + // refresh alerts index, so we can get all created alerts + await es.indices.refresh({ index: '.alerts-security.alerts-*' }); + + const alertsResponse = await getAlertsByIds(supertest, log, [createdRule.id], 200); + + // should return 160 alerts + expect(alertsResponse.hits.hits.length).toBe(160); }); }); From fe67f9fef96f0a7a3114c48d1f65e1d8444b5e29 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Tue, 7 Nov 2023 17:24:16 +0000 Subject: [PATCH 2/4] Update esql.ts --- .../security_and_spaces/rule_execution_logic/esql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts index 9c428c0049674..151f75bd456e4 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts @@ -717,7 +717,7 @@ export default ({ getService }: FtrProviderContext) => { // first rule execution catches 130 documents and generates 100 alerts // second rule execution catches 150 docs, 120 of which were captured during the first execution and generates only 60 alerts. Because rest are deduplicated // so in total we 160 alerts should be generated - it.only('should generate alerts when docs overlap execution intervals and alerts number reached max_signals in one of the real executions', async () => { + it('should generate alerts when docs overlap execution intervals and alerts number reached max_signals in one of the real executions', async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = { ...getCreateEsqlRulesSchemaMock(`rule-${id}`, true), From 0f2bfa6b2c6fd8a200489a540a6f0ab51020a9dd Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko Date: Tue, 7 Nov 2023 18:47:48 +0000 Subject: [PATCH 3/4] attempt ot fix --- .../rule_execution_logic/esql.ts | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts index 151f75bd456e4..ce8a0afd25e24 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts @@ -11,6 +11,7 @@ import { orderBy } from 'lodash'; import { EsqlRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema'; import { getCreateEsqlRulesSchemaMock } from '@kbn/security-solution-plugin/common/api/detection_engine/model/rule_schema/mocks'; +import { RuleExecutionStatusEnum } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring'; import { getMaxSignalsWarning } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_types/utils/utils'; import { @@ -20,8 +21,6 @@ import { previewRule, createRule, getOpenSignals as getOpenAlerts, - waitForEventLogExecuteComplete, - getSignalsByIds as getAlertsByIds, } from '../../utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { previewRuleWithExceptionEntries } from '../../utils/preview_rule_with_exception_entries'; @@ -730,7 +729,6 @@ export default ({ getService }: FtrProviderContext) => { max_signals: 100, enabled: true, }; - const createdRule = await createRule(supertest, log, rule); // docs fall in first rule executions await indexGeneratedDocuments({ @@ -780,18 +778,27 @@ export default ({ getService }: FtrProviderContext) => { }), }); + const createdRule = await createRule(supertest, log, rule); + // first rule run should generate 100 alerts from first 3 batches of index documents - await waitForEventLogExecuteComplete(es, log, createdRule.id, 1); + const alertsResponseFromFirstRuleExecution = await getOpenAlerts( + supertest, + log, + es, + createdRule, + // rule has warning, alerts were truncated, thus "partial failure" status + RuleExecutionStatusEnum['partial failure'], + 200 + ); - // refresh alerts index, so we can get all created alerts - await es.indices.refresh({ index: '.alerts-security.alerts-*' }); + // should return 100 alerts + expect(alertsResponseFromFirstRuleExecution.hits.hits.length).toBe(100); + // re-trigger rule execution with new interval await patchRule(supertest, log, { id: createdRule.id, enabled: false, }); - - // re-trigger rule execution with new interval await patchRule(supertest, log, { id: createdRule.id, from: '2020-10-28T05:45:00.000Z', @@ -799,13 +806,15 @@ export default ({ getService }: FtrProviderContext) => { enabled: true, }); - // second rule run should generate only 60 new alerts, the rest should be deduplicated - await waitForEventLogExecuteComplete(es, log, createdRule.id, 2); - - // refresh alerts index, so we can get all created alerts - await es.indices.refresh({ index: '.alerts-security.alerts-*' }); - - const alertsResponse = await getAlertsByIds(supertest, log, [createdRule.id], 200); + const alertsResponse = await getOpenAlerts( + supertest, + log, + es, + createdRule, + RuleExecutionStatusEnum.succeeded, + 200, + new Date() + ); // should return 160 alerts expect(alertsResponse.hits.hits.length).toBe(160); From e26f56100ecf09da3559861c11f4f0515e02b74b Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:30:14 +0000 Subject: [PATCH 4/4] Update x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts Co-authored-by: Ievgen Sorokopud --- .../security_and_spaces/rule_execution_logic/esql.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts index ce8a0afd25e24..51db00fc1ed6b 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/esql.ts @@ -715,7 +715,7 @@ export default ({ getService }: FtrProviderContext) => { // we use actual rule executions, not preview, because for preview API alerts index refresh=false for non suppressed alerts // first rule execution catches 130 documents and generates 100 alerts // second rule execution catches 150 docs, 120 of which were captured during the first execution and generates only 60 alerts. Because rest are deduplicated - // so in total we 160 alerts should be generated + // so in total 160 alerts should be generated it('should generate alerts when docs overlap execution intervals and alerts number reached max_signals in one of the real executions', async () => { const id = uuidv4(); const rule: EsqlRuleCreateProps = {