Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,6 @@ 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 @@ -56,7 +56,6 @@ import {
isThresholdRule as getIsThresholdRule,
isQueryRule,
isEsqlRule,
isEqlSequenceQuery,
isSuppressionRuleInGA,
} from '../../../../../common/detection_engine/utils';
import { EqlQueryEdit } from '../../../rule_creation/components/eql_query_edit';
Expand Down Expand Up @@ -310,9 +309,7 @@ const StepDefineRuleComponent: FC<StepDefineRuleProps> = ({
* purpose and so are treated as if the field is always selected. */
const areSuppressionFieldsSelected = isThresholdRule || Boolean(alertSuppressionFields?.length);

const { isSuppressionEnabled: isAlertSuppressionEnabled } = useAlertSuppression(
isEqlSequenceQuery(queryBar?.query?.query as string)
);
const { isSuppressionEnabled: isAlertSuppressionEnabled } = useAlertSuppression(ruleType);

/** If we don't have ML field information, users can't meaningfully interact with suppression fields */
const areSuppressionFieldsDisabledByMlFields =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,16 @@

import { useCallback } from 'react';
import type { DefineStepRule } from '../../../common/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 isAlertSuppressionForSequenceEqlRuleEnabled = useIsExperimentalFeatureEnabled(
'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]
);
const transformer = useCallback((fields: T) => {
return fields;
}, []);

return transformer;
};
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ export const RuleDefinitionSection = ({
ruleType: rule.type,
});

const { isSuppressionEnabled } = useAlertSuppression();
const { isSuppressionEnabled } = useAlertSuppression(rule.type);

const definitionSectionListItems = prepareDefinitionSectionListItems(
rule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,40 @@
*/

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);
it(`should return the isSuppressionEnabled true if query for all rule types is not an eql sequence query`, () => {
const { result } = renderHook(() => useAlertSuppression());
expect(result.current.isSuppressionEnabled).toBe(true);
(
[
'new_terms',
'threat_match',
'saved_query',
'query',
'threshold',
'eql',
'esql',
'machine_learning',
] as Type[]
).forEach((ruleType) => {
it(`should return the isSuppressionEnabled true for ${ruleType} rule type that exists in SUPPRESSIBLE_ALERT_RULES`, () => {
const { result } = renderHook(() => useAlertSuppression(ruleType));

expect(result.current.isSuppressionEnabled).toBe(true);
});
});

jest
.spyOn(useIsExperimentalFeatureEnabledMock, 'useIsExperimentalFeatureEnabled')
.mockReturnValue(false);
it('should return isSuppressionEnabled false for eql sequence query when feature flag is disabled', () => {
const { result } = renderHook(() => useAlertSuppression(true));
const { result } = renderHook(() => useAlertSuppression(undefined));
expect(result.current.isSuppressionEnabled).toBe(false);
});

it('should return false if rule type is not a suppressible rule', () => {
const { result } = renderHook(() => useAlertSuppression('OTHER_RULE_TYPE' as Type));
expect(result.current.isSuppressionEnabled).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,21 @@
* 2.0.
*/
import { useCallback } from 'react';
import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features';
import type { Type } from '@kbn/securitysolution-io-ts-alerting-types';
import { isSuppressibleAlertRule } from '../../../../common/detection_engine/utils';

export interface UseAlertSuppressionReturn {
isSuppressionEnabled: boolean;
}

export const useAlertSuppression = (isEqlSequenceQuery = false): UseAlertSuppressionReturn => {
const isAlertSuppressionForSequenceEQLRuleEnabled = useIsExperimentalFeatureEnabled(
'alertSuppressionForSequenceEqlRuleEnabled'
);

export const useAlertSuppression = (ruleType: Type | undefined): UseAlertSuppressionReturn => {
const isSuppressionEnabledForRuleType = useCallback(() => {
if (isEqlSequenceQuery) {
return isAlertSuppressionForSequenceEQLRuleEnabled;
if (!ruleType) {
return false;
}

return true;
}, [isAlertSuppressionForSequenceEQLRuleEnabled, isEqlSequenceQuery]);
return isSuppressibleAlertRule(ruleType);
}, [ruleType]);

return {
isSuppressionEnabled: isSuppressionEnabledForRuleType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ export const eqlExecutor = async ({
} else if (sequences) {
if (
isAlertSuppressionActive &&
experimentalFeatures.alertSuppressionForSequenceEqlRuleEnabled &&
alertSuppressionTypeGuard(completeRule.ruleParams.alertSuppression)
) {
await bulkCreateSuppressedSequencesInMemory({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"enabled": true,
"index": ["auditbeat*", "packetbeat*"],
"interval": "30s",
"query": "sequence with maxspan=10m [any where agent.type == \"auditbeat\"] [any where event.category == \"network_traffic\"]",
"query": "sequence with maxspan=10m [any where agent.type == \"auditbeat\"] [any where event.category == \"network\"]",
"meta": {
"anything_you_want_ui_related_or_otherwise": {
"as_deep_structured_as_you_need": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ export function createTestConfig(options: CreateTestConfigOptions, testFiles?: s
'previewTelemetryUrlEnabled',
'riskScoringPersistence',
'riskScoringRoutesEnabled',
'alertSuppressionForSequenceEqlRuleEnabled',
])}`,
`--plugin-path=${path.resolve(
__dirname,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,5 @@ export default createTestConfig({
'testing_ignored.constant',
'/testing_regex*/',
])}`, // See tests within the file "ignore_fields.ts" which use these values in "alertIgnoreFields"
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'alertSuppressionForSequenceEqlRuleEnabled',
])}`,
],
});
3 changes: 0 additions & 3 deletions x-pack/test/security_solution_cypress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
// See https://github.com/elastic/kibana/pull/125396 for details
'--xpack.alerting.rules.minimumScheduleInterval.value=1s',
'--xpack.ruleRegistry.unsafe.legacyMultiTenancy.enabled=true',
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'alertSuppressionForSequenceEqlRuleEnabled',
])}`,
// mock cloud to enable the guided onboarding tour in e2e tests
'--xpack.cloud.id=test',
`--home.disableWelcomeScreen=true`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ describe(
{
tags: ['@ess', '@serverless'],
env: {
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'alertSuppressionForSequenceEqlRuleEnabled',
])}`,
],
kbnServerArgs: [],
},
},
() => {
Expand Down