Skip to content

Commit

Permalink
[Security Solution][Alerts] Alert suppression time window (elastic#14…
Browse files Browse the repository at this point in the history
…8868)

## Summary

Adds ability to specify a time window with alert suppression on Query
rules. If more alerts are detected with the same value in the "group by"
field in subsequent rule executions, the existing alert will be updated
to reflect the new doc count and suppression end time rather than
creating a new alert.

### Create Rule

![image](https://user-images.githubusercontent.com/55718608/212997145-cee96a7d-fc3b-4b08-8845-5a9c7876fa0a.png)

### Rule Details

![image](https://user-images.githubusercontent.com/55718608/212997293-69d93392-f74e-4e4e-925a-befbee531659.png)

---------

Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Mike Côté <[email protected]>
  • Loading branch information
3 people authored and kqualters-elastic committed Feb 6, 2023
1 parent 90132ab commit 5726d4a
Show file tree
Hide file tree
Showing 51 changed files with 1,893 additions and 160 deletions.
5 changes: 5 additions & 0 deletions packages/kbn-rule-data-utils/src/default_alerts_as_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ const ALERT_FLAPPING = `${ALERT_NAMESPACE}.flapping` as const;
// kibana.alert.id - alert ID, also known as alert instance ID
const ALERT_ID = `${ALERT_NAMESPACE}.id` as const;

// kibana.alert.last_detected - timestamp when the alert was last seen
const ALERT_LAST_DETECTED = `${ALERT_NAMESPACE}.last_detected` as const;

// kibana.alert.reason - human readable reason that this alert is active
const ALERT_REASON = `${ALERT_NAMESPACE}.reason` as const;

Expand Down Expand Up @@ -91,6 +94,7 @@ const fields = {
ALERT_END,
ALERT_FLAPPING,
ALERT_ID,
ALERT_LAST_DETECTED,
ALERT_REASON,
ALERT_RULE_CATEGORY,
ALERT_RULE_CONSUMER,
Expand All @@ -116,6 +120,7 @@ export {
ALERT_END,
ALERT_FLAPPING,
ALERT_ID,
ALERT_LAST_DETECTED,
ALERT_REASON,
ALERT_RULE_CATEGORY,
ALERT_RULE_CONSUMER,
Expand Down
33 changes: 33 additions & 0 deletions x-pack/plugins/rule_registry/common/schemas/8.6.0/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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_SUPPRESSION_TERMS,
ALERT_SUPPRESSION_START,
ALERT_SUPPRESSION_END,
ALERT_SUPPRESSION_DOCS_COUNT,
} from '@kbn/rule-data-utils';
import { AlertWithCommonFields800 } from '../8.0.0';

/* DO NOT MODIFY THIS SCHEMA TO ADD NEW FIELDS. These types represent the alerts that shipped in 8.0.0.
Any changes to these types should be bug fixes so the types more accurately represent the alerts from 8.0.0.
If you are adding new fields for a new release of Kibana, create a new sibling folder to this one
for the version to be released and add the field(s) to the schema in that folder.
Then, update `../index.ts` to import from the new folder that has the latest schemas, add the
new schemas to the union of all alert schemas, and re-export the new schemas as the `*Latest` schemas.
*/

export interface SuppressionFields860 {
[ALERT_SUPPRESSION_TERMS]: Array<{ field: string; value: string | number | null }>;
[ALERT_SUPPRESSION_START]: Date;
[ALERT_SUPPRESSION_END]: Date;
[ALERT_SUPPRESSION_DOCS_COUNT]: number;
}

export type AlertWithSuppressionFields860<T> = AlertWithCommonFields800<T> & SuppressionFields860;
8 changes: 8 additions & 0 deletions x-pack/plugins/rule_registry/common/schemas/8.7.0/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
TIMESTAMP,
ALERT_RULE_PARAMETERS,
} from '@kbn/rule-data-utils';
import { AlertWithCommonFields800 } from '../8.0.0';

import { SuppressionFields860 } from '../8.6.0';

/* DO NOT MODIFY THIS SCHEMA TO ADD NEW FIELDS. These types represent the alerts that shipped in 8.7.0.
Any changes to these types should be bug fixes so the types more accurately represent the alerts from 8.7.0.
Expand All @@ -32,6 +35,11 @@ Then, update `../index.ts` to import from the new folder that has the latest sch
new schemas to the union of all alert schemas, and re-export the new schemas as the `*Latest` schemas.
*/

export interface SuppressionFields870 extends SuppressionFields860 {
[ALERT_INSTANCE_ID]: string;
}

export type AlertWithSuppressionFields870<T> = AlertWithCommonFields800<T> & SuppressionFields870;
const commonAlertIdFieldNames = [ALERT_INSTANCE_ID, ALERT_UUID];
export type CommonAlertIdFieldName870 = Values<typeof commonAlertIdFieldNames>;

Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/rule_registry/common/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import type {
AlertWithCommonFields870,
} from './8.7.0';

import type { AlertWithSuppressionFields870, SuppressionFields870 } from './8.7.0';

export type {
AlertWithSuppressionFields870 as AlertWithSuppressionFieldsLatest,
SuppressionFields870 as SuppressionFieldsLatest,
CommonAlertFieldName870 as CommonAlertFieldNameLatest,
CommonAlertIdFieldName870 as CommonAlertIdFieldNameLatest,
CommonAlertFields870 as CommonAlertFieldsLatest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,18 @@ export class RuleDataClient implements IRuleDataClient {
};

return {
search: async <TSearchRequest extends ESSearchRequest>(
search: async <
TSearchRequest extends ESSearchRequest,
TAlertDoc = Partial<ParsedTechnicalFields & ParsedExperimentalFields>
>(
request: TSearchRequest
): Promise<
ESSearchResponse<Partial<ParsedTechnicalFields & ParsedExperimentalFields>, TSearchRequest>
> => {
): Promise<ESSearchResponse<TAlertDoc, TSearchRequest>> => {
try {
const clusterClient = await waitUntilReady();
return (await clusterClient.search({
...request,
index: indexPattern,
})) as unknown as ESSearchResponse<
Partial<ParsedTechnicalFields & ParsedExperimentalFields>,
TSearchRequest
>;
})) as unknown as ESSearchResponse<TAlertDoc, TSearchRequest>;
} catch (err) {
this.options.logger.error(`Error performing search in RuleDataClient - ${err.message}`);
throw err;
Expand Down
9 changes: 5 additions & 4 deletions x-pack/plugins/rule_registry/server/rule_data_client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ export interface IRuleDataClient {
}

export interface IRuleDataReader {
search<TSearchRequest extends ESSearchRequest>(
search<
TSearchRequest extends ESSearchRequest,
TAlertDoc = Partial<ParsedTechnicalFields & ParsedExperimentalFields>
>(
request: TSearchRequest
): Promise<
ESSearchResponse<Partial<ParsedTechnicalFields & ParsedExperimentalFields>, TSearchRequest>
>;
): Promise<ESSearchResponse<TAlertDoc, TSearchRequest>>;

getDynamicIndexPattern(target?: string): Promise<{
title: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { PersistenceServices } from './persistence_types';
export const createPersistenceServicesMock = (): jest.Mocked<PersistenceServices> => {
return {
alertWithPersistence: jest.fn(),
alertWithSuppression: jest.fn(),
};
};

Expand Down
Loading

0 comments on commit 5726d4a

Please sign in to comment.