[8.12] [Security Solution][Detection Engine] fixes alert suppression for threshold rule when suppression value is a number (#173093) (#173354)

# Backport

This will backport the following commits from `main` to `8.12`:
- [[Security Solution][Detection Engine] fixes alert suppression for
threshold rule when suppression value is a number
(#173093)](https://github.com/elastic/kibana/pull/173093)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Vitalii
Dmyterko","email":"92328789+vitaliidm@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-12-14T09:12:19Z","message":"[Security
Solution][Detection Engine] fixes alert suppression for threshold rule
when suppression value is a number (#173093)\n\n## Summary\r\n\r\n-
fixes rule execution failure, when one of the suppression values
is\r\n`number` type\r\n - adds functions test to cover the case
\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"424708c9e569a77bbdc862f7bef1b7c92db6ba4a","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Detections
and Resp","Team: SecuritySolution","backport:prev-minor","Team:Detection
Engine","v8.12.0","v8.13.0"],"number":173093,"url":"https://github.com/elastic/kibana/pull/173093","mergeCommit":{"message":"[Security
Solution][Detection Engine] fixes alert suppression for threshold rule
when suppression value is a number (#173093)\n\n## Summary\r\n\r\n-
fixes rule execution failure, when one of the suppression values
is\r\n`number` type\r\n - adds functions test to cover the case
\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"424708c9e569a77bbdc862f7bef1b7c92db6ba4a"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/173093","number":173093,"mergeCommit":{"message":"[Security
Solution][Detection Engine] fixes alert suppression for threshold rule
when suppression value is a number (#173093)\n\n## Summary\r\n\r\n-
fixes rule execution failure, when one of the suppression values
is\r\n`number` type\r\n - adds functions test to cover the case
\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not
applicable to this PR.\r\n\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"424708c9e569a77bbdc862f7bef1b7c92db6ba4a"}}]}]
BACKPORT-->

Co-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2023-12-14 05:40:24 -05:00 committed by GitHub
parent 726025cdc9
commit 15a6cc8236
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 3 deletions

View file

@ -6,6 +6,7 @@
*/
import objectHash from 'object-hash';
import sortBy from 'lodash/sortBy';
import type { SuppressionFieldsLatest } from '@kbn/rule-registry-plugin/common/schemas';
import {
@ -79,9 +80,7 @@ export const wrapSuppressedThresholdALerts = ({
completeRule.ruleParams.ruleId
);
const suppressedValues = Object.entries(bucket.key)
.map(([key, value]) => value)
.sort((a, b) => a.localeCompare(b));
const suppressedValues = sortBy(Object.entries(bucket.key).map(([_, value]) => value));
const id = objectHash([
hit._index,

View file

@ -66,6 +66,9 @@
"properties": {
"name": {
"type": "keyword"
},
"uptime": {
"type": "long"
}
}
},

View file

@ -655,6 +655,82 @@ export default ({ getService }: FtrProviderContext) => {
});
});
// should work correctly if one of the suppressed fields is keyword, another - number
it('should update an existing alert in the time window with multiple fields of different types', async () => {
const id = uuidv4();
const timestamp = '2020-10-28T05:45:00.000Z';
const firstRunDoc = {
id,
'@timestamp': timestamp,
agent: {
name: 'agent-1',
},
host: {
uptime: 100,
},
};
const secondRunDoc = {
...firstRunDoc,
'@timestamp': '2020-10-28T06:15:00.000Z',
};
await indexListOfDocuments([firstRunDoc, firstRunDoc, secondRunDoc, secondRunDoc]);
const rule: ThresholdRuleCreateProps = {
...getThresholdRuleForAlertTesting(['ecs_compliant']),
query: `id:${id}`,
threshold: {
field: ['agent.name', 'host.uptime'],
value: 2,
},
alert_suppression: {
duration: {
value: 2,
unit: 'h',
},
},
from: 'now-35m',
interval: '30m',
};
const { previewId } = await previewRule({
supertest,
rule,
timeframeEnd: new Date('2020-10-28T06:30:00.000Z'),
invocationCount: 2,
});
const previewAlerts = await getPreviewAlerts({
es,
previewId,
sort: ['agent.type', ALERT_ORIGINAL_TIME],
});
expect(previewAlerts.length).toEqual(1);
expect(previewAlerts[0]._source).toEqual(
expect.objectContaining({
[ALERT_SUPPRESSION_TERMS]: [
{
field: 'agent.name',
value: 'agent-1',
},
{
field: 'host.uptime',
value: 100,
},
],
[TIMESTAMP]: '2020-10-28T06:00:00.000Z',
[ALERT_LAST_DETECTED]: '2020-10-28T06:30:00.000Z',
[ALERT_ORIGINAL_TIME]: timestamp,
[ALERT_SUPPRESSION_START]: '2020-10-28T06:00:00.000Z',
[ALERT_SUPPRESSION_END]: '2020-10-28T06:30:00.000Z',
[ALERT_SUPPRESSION_DOCS_COUNT]: 1,
})
);
});
it('should correctly suppress when using a timestamp override', async () => {
const id = uuidv4();
const timestamp = '2020-10-28T05:45:00.000Z';