Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Detection Engine] Adds support for suppressing EQL sequence alerts #189725

Merged
merged 91 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 88 commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
a2f4c8f
interim commit - undo me
dhurley14 Jul 24, 2024
70cf919
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Jul 29, 2024
707727a
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Jul 29, 2024
1eb6a58
first commit, working suppression by time range, need to filter out b…
dhurley14 Aug 1, 2024
79206ce
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Aug 5, 2024
1514ad5
create building block alerts for non-suppressed alert
dhurley14 Aug 5, 2024
bb120aa
enables UI for creating suppressed sequence alert
dhurley14 Aug 5, 2024
b1db508
merge with main
dhurley14 Aug 7, 2024
e44fc04
update import order, updates logic for get suppressed terms
dhurley14 Aug 12, 2024
68b7863
adds usage of lodash/get function to fetch suppression value
dhurley14 Aug 12, 2024
837b5ae
functionally complete rewrite
dhurley14 Aug 13, 2024
807ff03
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Aug 28, 2024
3f8bb0a
mostly console logs, some cleanup
dhurley14 Sep 3, 2024
d551198
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Sep 3, 2024
13c21bc
enables feature flag for ui
dhurley14 Sep 5, 2024
ae53bf1
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Sep 5, 2024
d1f7268
type fixes
dhurley14 Sep 9, 2024
4f5e14b
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Sep 9, 2024
b065fb6
fix bug where building block alerts were not being added to individua…
dhurley14 Sep 9, 2024
19334e4
working test with feature flag enabled
dhurley14 Sep 9, 2024
1a6d913
adds more ftr tests with additional bug fixes
dhurley14 Sep 17, 2024
3bfa5ab
adds more tests
dhurley14 Sep 19, 2024
6b74bb4
adds test for not suppressing outside of duration
dhurley14 Sep 24, 2024
4f42733
passing tests
dhurley14 Sep 24, 2024
88424c2
fixes lint and type check errors
dhurley14 Sep 25, 2024
3960710
merge with main
dhurley14 Sep 25, 2024
79917be
removes unused translations
dhurley14 Sep 26, 2024
11c8a4b
missing intendedTimestamp from merge with main
dhurley14 Sep 26, 2024
9899887
fix type errors
dhurley14 Sep 26, 2024
15e12ff
fix tests
dhurley14 Sep 26, 2024
8a38f2f
test fixes
dhurley14 Sep 27, 2024
e9811c9
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Sep 27, 2024
d4701b4
fix type error
dhurley14 Sep 27, 2024
50f1b24
skip test in serverless and fix conflicts and cypress config file
dhurley14 Sep 30, 2024
992c983
fix type errors in ftr test
dhurley14 Sep 30, 2024
e34b416
more cleanup, move utility functions to utils file
dhurley14 Sep 30, 2024
3bcbad5
undo addition of building block type to alert schema
dhurley14 Sep 30, 2024
63b09c4
more cleanup
dhurley14 Oct 1, 2024
cbc46e0
updates example json for sequence rules
dhurley14 Oct 1, 2024
b9d3950
utilize pre-existing logic for building alert in sequence suppression
dhurley14 Oct 1, 2024
88a6397
refactor buildAlertGroupFromSequence to use object param instead of p…
dhurley14 Oct 1, 2024
d0ad714
add comment for feature flag
dhurley14 Oct 1, 2024
59f12b2
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Oct 2, 2024
b9ed401
update logic for building block alerts
dhurley14 Oct 14, 2024
e8792b2
merge with main, resolves conflicts
dhurley14 Oct 14, 2024
1709a05
move logic for suppression terms and fields to after we build shell a…
dhurley14 Oct 25, 2024
36f9b97
prevent eql sequence suppression for building block rule types
dhurley14 Oct 27, 2024
926478f
add subAlerts when wrapping suppressed sequences to be used in alertW…
dhurley14 Nov 4, 2024
51a4651
merge with main
dhurley14 Nov 4, 2024
fda2a84
evaluate do not suppress for values from generated shell alert, not f…
dhurley14 Nov 5, 2024
ac0c179
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 5, 2024
351d223
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 5, 2024
af229f8
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 5, 2024
0412e25
adds eql utility class to encapsulate related params and centralize d…
dhurley14 Nov 7, 2024
4e3587e
flatten subAlerts and shell alerts when they are newAlerts
dhurley14 Nov 7, 2024
3079b9e
fixes as castings
dhurley14 Nov 7, 2024
4393b35
merge with origin
dhurley14 Nov 7, 2024
550ea89
remove unused function wrapSuppressedSequences
dhurley14 Nov 7, 2024
cc7687c
use latest fields for type guards
dhurley14 Nov 7, 2024
74b01c9
Revert "prevent eql sequence suppression for building block rule types"
dhurley14 Nov 8, 2024
6ed8121
adds e2e test for suppressing alerts from building block rule type
dhurley14 Nov 8, 2024
b4aac4a
remove console log
dhurley14 Nov 8, 2024
d6ca5b5
cleans up comments in test file, remove unused property leftover from…
dhurley14 Nov 12, 2024
d8956e5
merge with main
dhurley14 Nov 13, 2024
9d83958
flatten subAlerts when present
dhurley14 Nov 14, 2024
002500d
use data already present
dhurley14 Nov 14, 2024
5fad454
remove casting
dhurley14 Nov 14, 2024
479b16a
removes eql utils class, pass shared params to other functions, remov…
dhurley14 Nov 14, 2024
88e05e1
assert correct functionality for sequence rule with 3 sequences in th…
dhurley14 Nov 14, 2024
22e1416
fix comment in test
dhurley14 Nov 14, 2024
fcf28d3
adds partition utility function within test suite
dhurley14 Nov 14, 2024
19c5257
remove unused types
dhurley14 Nov 14, 2024
fe390bb
some more cleanup
dhurley14 Nov 14, 2024
7c1a53d
remove unused type
dhurley14 Nov 18, 2024
aa9d5d3
narrow type for alertSuppression param
dhurley14 Nov 18, 2024
dce9b92
updates return type and field name for getSuppressionTerms, also chan…
dhurley14 Nov 18, 2024
d1067ae
partition on group.index field in e2e test
dhurley14 Nov 18, 2024
73e5f9a
partition on group.index field in e2e test
dhurley14 Nov 18, 2024
ba05c66
adds cypress test to create eql sequence rule with suppression and mo…
dhurley14 Nov 18, 2024
65b5a9c
fixes misaligned assertions between shell alert and building block al…
dhurley14 Nov 22, 2024
9f1583b
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Nov 22, 2024
8b020ce
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Nov 26, 2024
09be989
removes suppression fields when saving and suppression is disabled
dhurley14 Nov 26, 2024
cc27026
skip test in serverless env because of feature flags
dhurley14 Nov 27, 2024
9db4d35
Merge remote-tracking branch 'upstream/main' into eql-sequence-suppre…
dhurley14 Nov 27, 2024
9c35d5e
Merge branch 'main' into eql-sequence-suppression
dhurley14 Nov 27, 2024
5bcdf9f
eql sequence suppression feature flag set default to enabled
dhurley14 Dec 2, 2024
98a9c11
Merge branch 'eql-sequence-suppression' of github.com:dhurley14/kiban…
dhurley14 Dec 2, 2024
7abac02
merge with main
dhurley14 Dec 4, 2024
a38142f
remove ruletype param from useAlertSuppression hook since all rule ty…
dhurley14 Dec 4, 2024
fe47eb5
fix translation files
dhurley14 Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions x-pack/plugins/rule_registry/common/schemas/8.17.0/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 } from '@kbn/rule-data-utils';
import { SearchTypes } from '@kbn/data-plugin/common';
import { AlertWithCommonFields880 } from '../8.8.0';

import { SuppressionFields8130 } from '../8.13.0';

/* DO NOT MODIFY THIS SCHEMA TO ADD NEW FIELDS. These types represent the alerts that shipped in 8.13.0.
Any changes to these types should be bug fixes so the types more accurately represent the alerts from 8.13.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 SuppressionFields8170
extends Omit<SuppressionFields8130, typeof ALERT_SUPPRESSION_TERMS> {
[ALERT_SUPPRESSION_TERMS]: Array<{
field: string;
value: SearchTypes | null;
dhurley14 marked this conversation as resolved.
Show resolved Hide resolved
}>;
}

export type AlertWithSuppressionFields8170<T> = AlertWithCommonFields880<T> & SuppressionFields8170;
6 changes: 3 additions & 3 deletions x-pack/plugins/rule_registry/common/schemas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import type {
CommonAlertFields880,
} from './8.8.0';

import type { AlertWithSuppressionFields8130, SuppressionFields8130 } from './8.13.0';
import type { AlertWithSuppressionFields8170, SuppressionFields8170 } from './8.17.0';

export type {
AlertWithSuppressionFields8130 as AlertWithSuppressionFieldsLatest,
SuppressionFields8130 as SuppressionFieldsLatest,
AlertWithSuppressionFields8170 as AlertWithSuppressionFieldsLatest,
SuppressionFields8170 as SuppressionFieldsLatest,
CommonAlertFieldName880 as CommonAlertFieldNameLatest,
CommonAlertIdFieldName870 as CommonAlertIdFieldNameLatest,
CommonAlertFields880 as CommonAlertFieldsLatest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ALERT_RULE_EXECUTION_TIMESTAMP,
} from '@kbn/rule-data-utils';
import { mapKeys, snakeCase } from 'lodash/fp';

import type { IRuleDataClient } from '..';
import { getCommonAlertFields } from './get_common_alert_fields';
import { CreatePersistenceRuleTypeWrapper } from './persistence_types';
Expand Down Expand Up @@ -471,9 +472,11 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper
}, {});

// filter out alerts that were already suppressed
// alert was suppressed if its suppression ends is older than suppression end of existing alert
// if existing alert was created earlier during the same rule execution - then alerts can be counted as not suppressed yet
// as they are processed for the first against this existing alert
// alert was suppressed if its suppression ends is older
// than suppression end of existing alert
// if existing alert was created earlier during the same
// rule execution - then alerts can be counted as not suppressed yet
// as they are processed for the first time against this existing alert
const nonSuppressedAlerts = filteredDuplicates.filter((alert) => {
const existingAlert =
existingAlertsByInstanceId[alert._source[ALERT_INSTANCE_ID]];
Expand Down Expand Up @@ -544,7 +547,15 @@ export const createPersistenceRuleTypeWrapper: CreatePersistenceRuleTypeWrapper
];
});

let enrichedAlerts = newAlerts;
// we can now augment and enrich
// the sub alerts (if any) the same as we would
// any other newAlert
let enrichedAlerts = newAlerts.some((newAlert) => newAlert.subAlerts != null)
? newAlerts.flatMap((newAlert) => {
const { subAlerts, ...everything } = newAlert;
return [everything, ...(subAlerts ?? [])];
})
: newAlerts;

if (enrichAlerts) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export type SuppressedAlertService = <T extends SuppressionFieldsLatest>(
alerts: Array<{
_id: string;
_source: T;
subAlerts?: Array<{
_id: string;
_source: T;
}>;
}>,
suppressionWindow: string,
enrichAlerts?: (
Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/security_solution/common/experimental_features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ export type ExperimentalFeatures = { [K in keyof typeof allowedExperimentalValue
* This object is then used to validate and parse the value entered.
*/
export const allowedExperimentalValues = Object.freeze({
/*
* Enables experimental feature flag for eql sequence alert suppression.
*
* Ticket: https://github.com/elastic/security-team/issues/9608
* Owners: https://github.com/orgs/elastic/teams/security-detection-engine
* Added: on October 1st, 2024 in https://github.com/elastic/kibana/pull/189725
* Turned: on (TBD)
* Expires: on (TBD)
*/
alertSuppressionForSequenceEqlRuleEnabled: true,

// FIXME:PT delete?
excludePoliciesInFilterEnabled: false,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ const RuleTypeEuiFormRow = styled(EuiFormRow).attrs<{ $isVisible: boolean }>(({
},
}))<{ $isVisible: boolean }>``;

// eslint-disable-next-line complexity
const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
dataSourceType,
defaultSavedQuery,
Expand All @@ -175,7 +174,6 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
}) => {
const queryClient = useQueryClient();

const { isSuppressionEnabled: isAlertSuppressionEnabled } = useAlertSuppression(ruleType);
const [openTimelineSearch, setOpenTimelineSearch] = useState(false);
const [indexModified, setIndexModified] = useState(false);
const [threatIndexModified, setThreatIndexModified] = useState(false);
Expand Down Expand Up @@ -451,41 +449,32 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
* purpose and so are treated as if the field is always selected. */
const areSuppressionFieldsSelected = isThresholdRule || Boolean(alertSuppressionFields?.length);

const areSuppressionFieldsDisabledBySequence =
isEqlRule(ruleType) &&
isEqlSequenceQuery(queryBar?.query?.query as string) &&
alertSuppressionFields?.length === 0;
const { isSuppressionEnabled: isAlertSuppressionEnabled } = useAlertSuppression(
ruleType,
isEqlSequenceQuery(queryBar?.query?.query as string)
);

/** If we don't have ML field information, users can't meaningfully interact with suppression fields */
const areSuppressionFieldsDisabledByMlFields =
isMlRule(ruleType) && (mlRuleConfigLoading || !mlSuppressionFields.length);

/** Suppression fields are generally disabled if either:
* - License is insufficient (i.e. less than platinum)
* - An EQL Sequence is used
* - ML Field information is not available
*/
const areSuppressionFieldsDisabled =
!isAlertSuppressionLicenseValid ||
areSuppressionFieldsDisabledBySequence ||
areSuppressionFieldsDisabledByMlFields;
!isAlertSuppressionLicenseValid || areSuppressionFieldsDisabledByMlFields;

const isSuppressionGroupByDisabled =
(areSuppressionFieldsDisabled || isEsqlSuppressionLoading) && !areSuppressionFieldsSelected;

const suppressionGroupByDisabledText = useMemo(() => {
if (areSuppressionFieldsDisabledBySequence) {
return i18n.EQL_SEQUENCE_SUPPRESSION_DISABLE_TOOLTIP;
} else if (areSuppressionFieldsDisabledByMlFields) {
if (areSuppressionFieldsDisabledByMlFields) {
return i18n.MACHINE_LEARNING_SUPPRESSION_DISABLED_LABEL;
} else {
return alertSuppressionUpsellingMessage;
}
}, [
alertSuppressionUpsellingMessage,
areSuppressionFieldsDisabledByMlFields,
areSuppressionFieldsDisabledBySequence,
]);
}, [alertSuppressionUpsellingMessage, areSuppressionFieldsDisabledByMlFields]);

const suppressionGroupByFields = useMemo(() => {
if (isEsqlRule(ruleType)) {
Expand Down Expand Up @@ -946,13 +935,14 @@ const StepDefineRuleReadOnlyComponent: FC<StepDefineRuleReadOnlyProps> = ({
}) => {
const dataForDescription: Partial<DefineStepRule> = getStepDataDataSource(data);
const transformFields = useExperimentalFeatureFieldsTransform();
const fieldsToDisplay = transformFields(dataForDescription);

return (
<StepContentWrapper data-test-subj="definitionRule" addPadding={addPadding}>
<StepRuleDescription
columns={descriptionColumns}
schema={filterRuleFieldsForType(schema, data.ruleType)}
data={filterRuleFieldsForType(transformFields(dataForDescription), data.ruleType)}
data={filterRuleFieldsForType(fieldsToDisplay, data.ruleType)}
indexPatterns={indexPattern}
/>
</StepContentWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
customValidators,
} from '../../../../common/components/threat_match/helpers';
import {
isEqlRule,
isEqlSequenceQuery,
isEsqlRule,
isNewTermsRule,
isThreatMatchRule,
Expand All @@ -39,7 +37,6 @@ import {
THREAT_MATCH_INDEX_HELPER_TEXT,
THREAT_MATCH_REQUIRED,
THREAT_MATCH_EMPTIES,
EQL_SEQUENCE_SUPPRESSION_GROUPBY_VALIDATION_TEXT,
} from './translations';
import {
ALERT_SUPPRESSION_DURATION_FIELD_NAME,
Expand Down Expand Up @@ -591,33 +588,13 @@ export const schema: FormSchema<DefineStepRule> = {
validator: (...args: Parameters<ValidationFunc>) => {
const [{ formData }] = args;
const needsValidation = isSuppressionRuleConfiguredWithGroupBy(formData.ruleType);

if (!needsValidation) {
return;
}

return alertSuppressionFieldsValidatorFactory()(...args);
},
},
{
validator: (
...args: Parameters<ValidationFunc>
): ReturnType<ValidationFunc<{}, ERROR_CODE>> | undefined => {
const [{ formData, value }] = args;

if (!isEqlRule(formData.ruleType) || !Array.isArray(value) || value.length === 0) {
return;
}

const query: string = formData.queryBar?.query?.query ?? '';

if (isEqlSequenceQuery(query)) {
return {
message: EQL_SEQUENCE_SUPPRESSION_GROUPBY_VALIDATION_TEXT,
};
}
},
},
],
},
[ALERT_SUPPRESSION_DURATION_FIELD_NAME]: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,22 +183,6 @@ export const getEnableThresholdSuppressionLabel = (fields: string[] | undefined)
)
);

export const EQL_SEQUENCE_SUPPRESSION_DISABLE_TOOLTIP = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.eqlSequenceSuppressionDisableText',
{
defaultMessage: 'Suppression is not supported for EQL sequence queries.',
}
);

export const EQL_SEQUENCE_SUPPRESSION_GROUPBY_VALIDATION_TEXT = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.eqlSequenceSuppressionValidationText',
{
defaultMessage:
'{EQL_SEQUENCE_SUPPRESSION_DISABLE_TOOLTIP} Change the EQL query to a non-sequence query, or remove the suppression fields.',
values: { EQL_SEQUENCE_SUPPRESSION_DISABLE_TOOLTIP },
}
);

export const MACHINE_LEARNING_SUPPRESSION_DISABLED_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.createRule.stepDefineRule.machineLearningSuppressionDisabledLabel',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,45 @@

import { useCallback } from 'react';
import type { DefineStepRule } from '../../../../detections/pages/detection_engine/rules/types';
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
import { isEqlRule, isEqlSequenceQuery } from '../../../../../common/detection_engine/utils';
import {
ALERT_SUPPRESSION_FIELDS_FIELD_NAME,
ALERT_SUPPRESSION_DURATION_TYPE_FIELD_NAME,
ALERT_SUPPRESSION_DURATION_FIELD_NAME,
ALERT_SUPPRESSION_MISSING_FIELDS_FIELD_NAME,
} from '../../../rule_creation/components/alert_suppression_edit';

/**
* transforms DefineStepRule fields according to experimental feature flags
*/
export const useExperimentalFeatureFieldsTransform = <T extends Partial<DefineStepRule>>(): ((
fields: T
) => T) => {
const transformer = useCallback((fields: T) => {
return fields;
}, []);
const isAlertSuppressionForSequenceEqlRuleEnabled = useIsExperimentalFeatureEnabled(
dhurley14 marked this conversation as resolved.
Show resolved Hide resolved
'alertSuppressionForSequenceEqlRuleEnabled'
);
const transformer = useCallback(
(fields: T) => {
const isSuppressionDisabled =
isEqlRule(fields.ruleType) &&
isEqlSequenceQuery(fields.queryBar?.query?.query as string) &&
!isAlertSuppressionForSequenceEqlRuleEnabled;

// reset any alert suppression values hidden behind feature flag
if (isSuppressionDisabled) {
return {
...fields,
[ALERT_SUPPRESSION_FIELDS_FIELD_NAME]: [],
[ALERT_SUPPRESSION_DURATION_TYPE_FIELD_NAME]: undefined,
[ALERT_SUPPRESSION_DURATION_FIELD_NAME]: undefined,
[ALERT_SUPPRESSION_MISSING_FIELDS_FIELD_NAME]: undefined,
};
}
return fields;
},
[isAlertSuppressionForSequenceEqlRuleEnabled]
);

return transformer;
};
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { useUserData } from '../../../../detections/components/user_info';
import { StepPanel } from '../../../rule_creation/components/step_panel';
import { StepAboutRule } from '../../components/step_about_rule';
import { StepDefineRule } from '../../components/step_define_rule';
import { useExperimentalFeatureFieldsTransform } from '../../components/step_define_rule/use_experimental_feature_fields_transform';
import { StepScheduleRule } from '../../components/step_schedule_rule';
import { StepRuleActions } from '../../../rule_creation/components/step_rule_actions';
import { formatRule } from '../rule_creation/helpers';
Expand All @@ -52,6 +53,7 @@ import {
MaxWidthEuiFlexItem,
} from '../../../../detections/pages/detection_engine/rules/helpers';
import * as ruleI18n from '../../../../detections/pages/detection_engine/rules/translations';
import type { DefineStepRule } from '../../../../detections/pages/detection_engine/rules/types';
import { RuleStep } from '../../../../detections/pages/detection_engine/rules/types';
import * as i18n from './translations';
import { SecurityPageName } from '../../../../app/types';
Expand Down Expand Up @@ -369,11 +371,16 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => {

const { startTransaction } = useStartTransaction();

const defineFieldsTransform = useExperimentalFeatureFieldsTransform<DefineStepRule>();

const saveChanges = useCallback(async () => {
startTransaction({ name: SINGLE_RULE_ACTIONS.SAVE });
const localDefineStepData: DefineStepRule = defineFieldsTransform({
...defineStepData,
});
const updatedRule = await updateRule({
...formatRule<RuleUpdateProps>(
defineStepData,
localDefineStepData,
aboutStepData,
scheduleStepData,
actionsStepData,
Expand All @@ -391,8 +398,9 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => {
}, [
aboutStepData,
actionsStepData,
addSuccess,
defineStepData,
defineFieldsTransform,
addSuccess,
navigateToApp,
rule?.exceptions_list,
ruleId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@

import { renderHook } from '@testing-library/react';
import type { Type } from '@kbn/securitysolution-io-ts-alerting-types';
import * as useIsExperimentalFeatureEnabledMock from '../../../common/hooks/use_experimental_features';
import { useAlertSuppression } from './use_alert_suppression';

describe('useAlertSuppression', () => {
jest
.spyOn(useIsExperimentalFeatureEnabledMock, 'useIsExperimentalFeatureEnabled')
.mockReturnValue(false);
(
[
'new_terms',
Expand Down
Loading