From 315e85c90aba64ff5a1677d736a4933633d27b5b Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 7 Dec 2021 17:12:21 -0700 Subject: [PATCH] [Security Solution][Detections] Updates RuleDetails to query alerts by RuleId instead of Rule SO ID (#120053) * Switches RuleDetails to query alerts by ruleId instead of SO id * Increases integrity of test outputs * Cleans up duplicate RuleRegistry functions * Removes support for rule.id for alerts filter and updates exceptions to use new filter --- .../src/technical_field_names.ts | 3 + .../exceptions/add_exception_modal/index.tsx | 9 +- .../exceptions/edit_exception_modal/index.tsx | 9 +- .../exceptions/use_add_exception.test.tsx | 25 ++- .../exceptions/use_add_exception.tsx | 36 ++-- .../alerts_table/default_config.test.tsx | 8 +- .../alerts_table/default_config.tsx | 163 +++--------------- .../components/alerts_table/index.tsx | 30 +--- .../detection_engine/detection_engine.tsx | 34 +--- .../detection_engine/rules/details/index.tsx | 39 +---- .../use_filters_for_signals_by_category.ts | 18 +- .../find_rule_status_internal_route.test.ts | 8 +- .../lib/detection_engine/routes/utils.test.ts | 12 +- .../lib/detection_engine/routes/utils.ts | 2 +- 14 files changed, 102 insertions(+), 294 deletions(-) diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index 349719c019c22..fde8deade36b5 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -24,6 +24,7 @@ const VERSION = `${KIBANA_NAMESPACE}.version` as const; // Fields pertaining to the alert const ALERT_ACTION_GROUP = `${ALERT_NAMESPACE}.action_group` as const; +const ALERT_BUILDING_BLOCK_TYPE = `${ALERT_NAMESPACE}.building_block_type` as const; const ALERT_DURATION = `${ALERT_NAMESPACE}.duration.us` as const; const ALERT_END = `${ALERT_NAMESPACE}.end` as const; const ALERT_EVALUATION_THRESHOLD = `${ALERT_NAMESPACE}.evaluation.threshold` as const; @@ -91,6 +92,7 @@ const fields = { TAGS, TIMESTAMP, ALERT_ACTION_GROUP, + ALERT_BUILDING_BLOCK_TYPE, ALERT_DURATION, ALERT_END, ALERT_EVALUATION_THRESHOLD, @@ -141,6 +143,7 @@ const fields = { export { ALERT_ACTION_GROUP, + ALERT_BUILDING_BLOCK_TYPE, ALERT_DURATION, ALERT_END, ALERT_EVALUATION_THRESHOLD, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx index afff935619740..617c66fa3c3da 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/add_exception_modal/index.tsx @@ -327,11 +327,16 @@ export const AddExceptionModal = memo(function AddExceptionModal({ const alertIdToClose = shouldCloseAlert && alertData ? alertData._id : undefined; const bulkCloseIndex = shouldBulkCloseAlert && signalIndexName != null ? [signalIndexName] : undefined; - addOrUpdateExceptionItems(ruleId, enrichExceptionItems(), alertIdToClose, bulkCloseIndex); + addOrUpdateExceptionItems( + maybeRule?.rule_id ?? '', + enrichExceptionItems(), + alertIdToClose, + bulkCloseIndex + ); } }, [ addOrUpdateExceptionItems, - ruleId, + maybeRule, enrichExceptionItems, shouldCloseAlert, shouldBulkCloseAlert, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx index 1724f616e7fc8..f88bf855049ef 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/edit_exception_modal/index.tsx @@ -267,11 +267,16 @@ export const EditExceptionModal = memo(function EditExceptionModal({ if (addOrUpdateExceptionItems !== null) { const bulkCloseIndex = shouldBulkCloseAlert && signalIndexName !== null ? [signalIndexName] : undefined; - addOrUpdateExceptionItems(ruleId, enrichExceptionItems(), undefined, bulkCloseIndex); + addOrUpdateExceptionItems( + maybeRule?.rule_id ?? '', + enrichExceptionItems(), + undefined, + bulkCloseIndex + ); } }, [ addOrUpdateExceptionItems, - ruleId, + maybeRule, enrichExceptionItems, shouldBulkCloseAlert, signalIndexName, diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx index 0d7366557ff6e..564bb965a8782 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx @@ -44,16 +44,14 @@ describe('useAddOrUpdateException', () => { let updateExceptionListItem: jest.SpyInstance>; let getQueryFilter: jest.SpyInstance>; let buildAlertStatusesFilter: jest.SpyInstance< - ReturnType - >; - let buildAlertsRuleIdFilter: jest.SpyInstance< - ReturnType + ReturnType >; + let buildAlertsFilter: jest.SpyInstance>; let addOrUpdateItemsArgs: Parameters; let render: () => RenderHookResult; const onError = jest.fn(); const onSuccess = jest.fn(); - const ruleId = 'rule-id'; + const ruleStaticId = 'rule-id'; const alertIdToClose = 'idToClose'; const bulkCloseIndex = ['.custom']; const itemsToAdd: CreateExceptionListItemSchema[] = [ @@ -128,14 +126,11 @@ describe('useAddOrUpdateException', () => { getQueryFilter = jest.spyOn(getQueryFilterHelper, 'getQueryFilter'); - buildAlertStatusesFilter = jest.spyOn( - buildFilterHelpers, - 'buildAlertStatusesFilterRuleRegistry' - ); + buildAlertStatusesFilter = jest.spyOn(buildFilterHelpers, 'buildAlertStatusesFilter'); - buildAlertsRuleIdFilter = jest.spyOn(buildFilterHelpers, 'buildAlertsRuleIdFilter'); + buildAlertsFilter = jest.spyOn(buildFilterHelpers, 'buildAlertsFilter'); - addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate]; + addOrUpdateItemsArgs = [ruleStaticId, itemsToAddOrUpdate]; render = () => renderHook( () => @@ -262,7 +257,7 @@ describe('useAddOrUpdateException', () => { describe('when alertIdToClose is passed in', () => { beforeEach(() => { - addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate, alertIdToClose]; + addOrUpdateItemsArgs = [ruleStaticId, itemsToAddOrUpdate, alertIdToClose]; }); it('should update the alert status', async () => { await act(async () => { @@ -317,7 +312,7 @@ describe('useAddOrUpdateException', () => { describe('when bulkCloseIndex is passed in', () => { beforeEach(() => { - addOrUpdateItemsArgs = [ruleId, itemsToAddOrUpdate, undefined, bulkCloseIndex]; + addOrUpdateItemsArgs = [ruleStaticId, itemsToAddOrUpdate, undefined, bulkCloseIndex]; }); it('should update the status of only alerts that are open', async () => { await act(async () => { @@ -351,8 +346,8 @@ describe('useAddOrUpdateException', () => { addOrUpdateItems(...addOrUpdateItemsArgs); } await waitForNextUpdate(); - expect(buildAlertsRuleIdFilter).toHaveBeenCalledTimes(1); - expect(buildAlertsRuleIdFilter.mock.calls[0][0]).toEqual(ruleId); + expect(buildAlertsFilter).toHaveBeenCalledTimes(1); + expect(buildAlertsFilter.mock.calls[0][0]).toEqual(ruleStaticId); }); }); it('should generate the query filter using exceptions', async () => { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx index 7cb8b643aa0e8..71c49f7c2daad 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx @@ -17,27 +17,25 @@ import { HttpStart } from '../../../../../../../src/core/public'; import { updateAlertStatus } from '../../../detections/containers/detection_engine/alerts/api'; import { getUpdateAlertsQuery } from '../../../detections/components/alerts_table/actions'; import { - buildAlertsRuleIdFilter, + buildAlertsFilter, buildAlertStatusesFilter, - buildAlertStatusesFilterRuleRegistry, } from '../../../detections/components/alerts_table/default_config'; import { getQueryFilter } from '../../../../common/detection_engine/get_query_filter'; import { Index } from '../../../../common/detection_engine/schemas/common/schemas'; -import { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features'; import { formatExceptionItemForUpdate, prepareExceptionItemsForBulkClose } from './helpers'; import { useKibana } from '../../lib/kibana'; /** * Adds exception items to the list. Also optionally closes alerts. * - * @param ruleId id of the rule where the exception updates will be applied + * @param ruleStaticId static id of the rule (rule.ruleId, not rule.id) where the exception updates will be applied * @param exceptionItemsToAddOrUpdate array of ExceptionListItemSchema to add or update * @param alertIdToClose - optional string representing alert to close * @param bulkCloseIndex - optional index used to create bulk close query * */ export type AddOrUpdateExceptionItemsFunc = ( - ruleId: string, + ruleStaticId: string, exceptionItemsToAddOrUpdate: Array, alertIdToClose?: string, bulkCloseIndex?: Index @@ -72,10 +70,10 @@ export const useAddOrUpdateException = ({ const addOrUpdateExceptionRef = useRef(null); const { addExceptionListItem, updateExceptionListItem } = useApi(services.http); const addOrUpdateException = useCallback( - async (ruleId, exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex) => { + async (ruleStaticId, exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex) => { if (addOrUpdateExceptionRef.current != null) { addOrUpdateExceptionRef.current( - ruleId, + ruleStaticId, exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex @@ -84,15 +82,13 @@ export const useAddOrUpdateException = ({ }, [] ); - // TODO: Once we are past experimental phase this code should be removed - const ruleRegistryEnabled = useIsExperimentalFeatureEnabled('ruleRegistryEnabled'); useEffect(() => { let isSubscribed = true; const abortCtrl = new AbortController(); const onUpdateExceptionItemsAndAlertStatus: AddOrUpdateExceptionItemsFunc = async ( - ruleId, + ruleStaticId, exceptionItemsToAddOrUpdate, alertIdToClose, bulkCloseIndex @@ -131,15 +127,16 @@ export const useAddOrUpdateException = ({ } if (bulkCloseIndex != null) { - // TODO: Once we are past experimental phase this code should be removed - const alertStatusFilter = ruleRegistryEnabled - ? buildAlertStatusesFilterRuleRegistry(['open', 'acknowledged', 'in-progress']) - : buildAlertStatusesFilter(['open', 'acknowledged', 'in-progress']); + const alertStatusFilter = buildAlertStatusesFilter([ + 'open', + 'acknowledged', + 'in-progress', + ]); const filter = getQueryFilter( '', 'kuery', - [...buildAlertsRuleIdFilter(ruleId), ...alertStatusFilter], + [...buildAlertsFilter(ruleStaticId), ...alertStatusFilter], bulkCloseIndex, prepareExceptionItemsForBulkClose(exceptionItemsToAddOrUpdate), false @@ -185,14 +182,7 @@ export const useAddOrUpdateException = ({ isSubscribed = false; abortCtrl.abort(); }; - }, [ - addExceptionListItem, - http, - onSuccess, - onError, - ruleRegistryEnabled, - updateExceptionListItem, - ]); + }, [addExceptionListItem, http, onSuccess, onError, updateExceptionListItem]); return [{ isLoading }, addOrUpdateException]; }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx index 13e93604863b4..aab6cabdb3a93 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.test.tsx @@ -7,7 +7,7 @@ import { ExistsFilter, Filter } from '@kbn/es-query'; import { - buildAlertsRuleIdFilter, + buildAlertsFilter, buildAlertStatusesFilter, buildAlertStatusFilter, buildThreatMatchFilter, @@ -18,21 +18,21 @@ jest.mock('./actions'); describe('alerts default_config', () => { describe('buildAlertsRuleIdFilter', () => { test('given a rule id this will return an array with a single filter', () => { - const filters: Filter[] = buildAlertsRuleIdFilter('rule-id-1'); + const filters: Filter[] = buildAlertsFilter('rule-id-1'); const expectedFilter: Filter = { meta: { alias: null, negate: false, disabled: false, type: 'phrase', - key: 'kibana.alert.rule.uuid', + key: 'kibana.alert.rule.rule_id', params: { query: 'rule-id-1', }, }, query: { match_phrase: { - 'kibana.alert.rule.uuid': 'rule-id-1', + 'kibana.alert.rule.rule_id': 'rule-id-1', }, }, }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx index a5947e45ed0f0..663d133f04b1c 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/default_config.tsx @@ -6,21 +6,13 @@ */ import { - ALERT_DURATION, - ALERT_RULE_PRODUCER, - ALERT_START, + ALERT_BUILDING_BLOCK_TYPE, ALERT_WORKFLOW_STATUS, - ALERT_UUID, - ALERT_RULE_UUID, - ALERT_RULE_NAME, - ALERT_RULE_CATEGORY, - ALERT_RULE_SEVERITY, - ALERT_RULE_RISK_SCORE, + ALERT_RULE_RULE_ID, } from '@kbn/rule-data-utils/technical_field_names'; import type { Filter } from '@kbn/es-query'; -import { defaultColumnHeaderType } from '../../../timelines/components/timeline/body/column_headers/default_headers'; -import { ColumnHeaderOptions, RowRendererId } from '../../../../common/types/timeline'; +import { RowRendererId } from '../../../../common/types/timeline'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; import { SubsetTimelineModel } from '../../../timelines/store/timeline/model'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; @@ -34,12 +26,12 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { should: [ { term: { - 'kibana.alert.workflow_status': status, + [ALERT_WORKFLOW_STATUS]: status, }, }, { term: { - 'kibana.alert.workflow_status': 'in-progress', + [ALERT_WORKFLOW_STATUS]: 'in-progress', }, }, ], @@ -47,7 +39,7 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { } : { term: { - 'kibana.alert.workflow_status': status, + [ALERT_WORKFLOW_STATUS]: status, }, }; @@ -58,7 +50,7 @@ export const buildAlertStatusFilter = (status: Status): Filter[] => { negate: false, disabled: false, type: 'phrase', - key: 'kibana.alert.workflow_status', + key: ALERT_WORKFLOW_STATUS, params: { query: status, }, @@ -76,7 +68,7 @@ export const buildAlertStatusesFilter = (statuses: Status[]): Filter[] => { bool: { should: statuses.map((status) => ({ term: { - 'kibana.alert.workflow_status': status, + [ALERT_WORKFLOW_STATUS]: status, }, })), }, @@ -94,8 +86,15 @@ export const buildAlertStatusesFilter = (statuses: Status[]): Filter[] => { ]; }; -export const buildAlertsRuleIdFilter = (ruleId: string | null): Filter[] => - ruleId +/** + * Builds Kuery filter for fetching alerts for a specific rule. Takes the rule's + * static id, i.e. `rule.ruleId` (not rule.id), so that alerts for _all + * historical instances_ of the rule are returned. + * + * @param ruleStaticId Rule's static id: `rule.ruleId` + */ +export const buildAlertsFilter = (ruleStaticId: string | null): Filter[] => + ruleStaticId ? [ { meta: { @@ -103,14 +102,14 @@ export const buildAlertsRuleIdFilter = (ruleId: string | null): Filter[] => negate: false, disabled: false, type: 'phrase', - key: 'kibana.alert.rule.uuid', + key: ALERT_RULE_RULE_ID, params: { - query: ruleId, + query: ruleStaticId, }, }, query: { match_phrase: { - 'kibana.alert.rule.uuid': ruleId, + [ALERT_RULE_RULE_ID]: ruleStaticId, }, }, }, @@ -127,10 +126,10 @@ export const buildShowBuildingBlockFilter = (showBuildingBlockAlerts: boolean): negate: true, disabled: false, type: 'exists', - key: 'kibana.alert.building_block_type', + key: ALERT_BUILDING_BLOCK_TYPE, value: 'exists', }, - query: { exists: { field: 'kibana.alert.building_block_type' } }, + query: { exists: { field: ALERT_BUILDING_BLOCK_TYPE } }, }, ]; @@ -183,121 +182,3 @@ export const requiredFieldsForActions = [ 'host.os.family', 'event.code', ]; - -// TODO: Once we are past experimental phase this code should be removed -export const buildAlertStatusFilterRuleRegistry = (status: Status): Filter[] => { - const combinedQuery = - status === 'acknowledged' - ? { - bool: { - should: [ - { - term: { - [ALERT_WORKFLOW_STATUS]: status, - }, - }, - { - term: { - [ALERT_WORKFLOW_STATUS]: 'in-progress', - }, - }, - ], - }, - } - : { - term: { - [ALERT_WORKFLOW_STATUS]: status, - }, - }; - - return [ - { - meta: { - alias: null, - negate: false, - disabled: false, - type: 'phrase', - key: ALERT_WORKFLOW_STATUS, - params: { - query: status, - }, - }, - query: combinedQuery, - }, - ]; -}; - -// TODO: Once we are past experimental phase this code should be removed -export const buildAlertStatusesFilterRuleRegistry = (statuses: Status[]): Filter[] => { - const combinedQuery = { - bool: { - should: statuses.map((status) => ({ - term: { - [ALERT_WORKFLOW_STATUS]: status, - }, - })), - }, - }; - - return [ - { - meta: { - alias: null, - negate: false, - disabled: false, - }, - query: combinedQuery, - }, - ]; -}; - -export const buildShowBuildingBlockFilterRuleRegistry = ( - showBuildingBlockAlerts: boolean -): Filter[] => - showBuildingBlockAlerts - ? [] - : [ - { - meta: { - alias: null, - negate: true, - disabled: false, - type: 'exists', - key: 'kibana.alert.building_block_type', - value: 'exists', - }, - query: { exists: { field: 'kibana.alert.building_block_type' } }, - }, - ]; - -export const requiredFieldMappingsForActionsRuleRegistry = { - '@timestamp': '@timestamp', - 'event.kind': 'event.kind', - 'rule.severity': ALERT_RULE_SEVERITY, - 'rule.risk_score': ALERT_RULE_RISK_SCORE, - 'alert.uuid': ALERT_UUID, - 'alert.start': ALERT_START, - 'event.action': 'event.action', - 'alert.workflow_status': ALERT_WORKFLOW_STATUS, - 'alert.duration.us': ALERT_DURATION, - 'rule.uuid': ALERT_RULE_UUID, - 'rule.name': ALERT_RULE_NAME, - 'rule.category': ALERT_RULE_CATEGORY, - producer: ALERT_RULE_PRODUCER, - tags: 'tags', -}; - -export const alertsHeadersRuleRegistry: ColumnHeaderOptions[] = Object.entries( - requiredFieldMappingsForActionsRuleRegistry -).map(([alias, field]) => ({ - columnHeaderType: defaultColumnHeaderType, - displayAsText: alias, - id: field, -})); - -export const alertsDefaultModelRuleRegistry: SubsetTimelineModel = { - ...timelineDefaults, - columns: alertsHeadersRuleRegistry, - showCheckboxes: true, - excludedRowRendererIds: Object.values(RowRendererId), -}; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index bbab423738ca0..256a063c44158 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -40,9 +40,7 @@ import { updateAlertStatusAction } from './actions'; import { AditionalFiltersAction, AlertsUtilityBar } from './alerts_utility_bar'; import { alertsDefaultModel, - alertsDefaultModelRuleRegistry, buildAlertStatusFilter, - buildAlertStatusFilterRuleRegistry, requiredFieldsForActions, } from './default_config'; import { buildTimeRangeFilter } from './helpers'; @@ -106,8 +104,6 @@ export const AlertsTableComponent: React.FC = ({ const kibana = useKibana(); const [, dispatchToaster] = useStateToaster(); const { addWarning } = useAppToasts(); - // TODO: Once we are past experimental phase this code should be removed - const ruleRegistryEnabled = useIsExperimentalFeatureEnabled('ruleRegistryEnabled'); const ACTION_BUTTON_COUNT = 4; const getGlobalQuery = useCallback( @@ -247,14 +243,9 @@ export const AlertsTableComponent: React.FC = ({ refetchQuery: inputsModel.Refetch, { status, selectedStatus }: UpdateAlertsStatusProps ) => { - // TODO: Once we are past experimental phase this code should be removed - const currentStatusFilter = ruleRegistryEnabled - ? buildAlertStatusFilterRuleRegistry(status) - : buildAlertStatusFilter(status); - await updateAlertStatusAction({ query: showClearSelectionAction - ? getGlobalQuery(currentStatusFilter)?.filterQuery + ? getGlobalQuery(buildAlertStatusFilter(status))?.filterQuery : undefined, alertIds: Object.keys(selectedEventIds), selectedStatus, @@ -273,7 +264,6 @@ export const AlertsTableComponent: React.FC = ({ showClearSelectionAction, onAlertStatusUpdateSuccess, onAlertStatusUpdateFailure, - ruleRegistryEnabled, ] ); @@ -327,24 +317,16 @@ export const AlertsTableComponent: React.FC = ({ ); const defaultFiltersMemo = useMemo(() => { - // TODO: Once we are past experimental phase this code should be removed - const alertStatusFilter = ruleRegistryEnabled - ? buildAlertStatusFilterRuleRegistry(filterGroup) - : buildAlertStatusFilter(filterGroup); + const alertStatusFilter = buildAlertStatusFilter(filterGroup); if (isEmpty(defaultFilters)) { return alertStatusFilter; } else if (defaultFilters != null && !isEmpty(defaultFilters)) { return [...defaultFilters, ...alertStatusFilter]; } - }, [defaultFilters, filterGroup, ruleRegistryEnabled]); + }, [defaultFilters, filterGroup]); const { filterManager } = useKibana().services.data.query; - // TODO: Once we are past experimental phase this code should be removed - const defaultTimelineModel = ruleRegistryEnabled - ? alertsDefaultModelRuleRegistry - : alertsDefaultModel; - const tGridEnabled = useIsExperimentalFeatureEnabled('tGridEnabled'); useEffect(() => { @@ -359,7 +341,7 @@ export const AlertsTableComponent: React.FC = ({ : c ), documentType: i18n.ALERTS_DOCUMENT_TYPE, - excludedRowRendererIds: defaultTimelineModel.excludedRowRendererIds as RowRendererId[], + excludedRowRendererIds: alertsDefaultModel.excludedRowRendererIds as RowRendererId[], filterManager, footerText: i18n.TOTAL_COUNT_OF_ALERTS, id: timelineId, @@ -370,7 +352,7 @@ export const AlertsTableComponent: React.FC = ({ showCheckboxes: true, }) ); - }, [dispatch, defaultTimelineModel, filterManager, tGridEnabled, timelineId]); + }, [dispatch, filterManager, tGridEnabled, timelineId]); const leadingControlColumns = useMemo(() => getDefaultControlColumn(ACTION_BUTTON_COUNT), []); @@ -383,7 +365,7 @@ export const AlertsTableComponent: React.FC = ({ additionalFilters={additionalFiltersComponent} currentFilter={filterGroup} defaultCellActions={defaultCellActions} - defaultModel={defaultTimelineModel} + defaultModel={alertsDefaultModel} end={to} entityType="events" hasAlertsCrud={hasIndexWrite && hasIndexMaintenance} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx index bcff80778475e..8ad6716670c32 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx @@ -24,7 +24,6 @@ import { connect, ConnectedProps, useDispatch } from 'react-redux'; import { Dispatch } from 'redux'; import { Status } from '../../../../common/detection_engine/schemas/common/schemas'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { isTab } from '../../../../../timelines/public'; import { useDeepEqualSelector, useShallowEqualSelector } from '../../../common/hooks/use_selector'; import { SecurityPageName } from '../../../app/types'; @@ -61,9 +60,7 @@ import { timelineActions, timelineSelectors } from '../../../timelines/store/tim import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; import { buildAlertStatusFilter, - buildAlertStatusFilterRuleRegistry, buildShowBuildingBlockFilter, - buildShowBuildingBlockFilterRuleRegistry, buildThreatMatchFilter, } from '../../components/alerts_table/default_config'; import { useSourcererDataView } from '../../../common/containers/sourcerer'; @@ -115,8 +112,6 @@ const DetectionEnginePageComponent: React.FC = ({ const getGlobalQuerySelector = useMemo(() => inputsSelectors.globalQuerySelector(), []); const query = useDeepEqualSelector(getGlobalQuerySelector); const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); - // TODO: Once we are past experimental phase this code should be removed - const ruleRegistryEnabled = useIsExperimentalFeatureEnabled('ruleRegistryEnabled'); const { to, from } = useGlobalTime(); const { globalFullScreen } = useGlobalFullScreen(); @@ -187,39 +182,20 @@ const DetectionEnginePageComponent: React.FC = ({ const alertsHistogramDefaultFilters = useMemo( () => [ ...filters, - ...(ruleRegistryEnabled - ? [ - // TODO: Once we are past experimental phase this code should be removed - ...buildShowBuildingBlockFilterRuleRegistry(showBuildingBlockAlerts), - ...buildAlertStatusFilterRuleRegistry(filterGroup), - ] - : [ - ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), - ...buildAlertStatusFilter(filterGroup), - ]), + ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), + ...buildAlertStatusFilter(filterGroup), ...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts), ], - [ - filters, - ruleRegistryEnabled, - showBuildingBlockAlerts, - showOnlyThreatIndicatorAlerts, - filterGroup, - ] + [filters, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts, filterGroup] ); // AlertsTable manages global filters itself, so not including `filters` const alertsTableDefaultFilters = useMemo( () => [ - ...(ruleRegistryEnabled - ? [ - // TODO: Once we are past experimental phase this code should be removed - ...buildShowBuildingBlockFilterRuleRegistry(showBuildingBlockAlerts), - ] - : [...buildShowBuildingBlockFilter(showBuildingBlockAlerts)]), + ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), ...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts), ], - [ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts] + [showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts] ); const onShowBuildingBlockAlertsChangedCallback = useCallback( diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 98ed33c647b2e..b9f73dd03c106 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -63,11 +63,9 @@ import { useUserData } from '../../../../components/user_info'; import { StepDefineRule } from '../../../../components/rules/step_define_rule'; import { StepScheduleRule } from '../../../../components/rules/step_schedule_rule'; import { - buildAlertsRuleIdFilter, + buildAlertsFilter, buildAlertStatusFilter, - buildAlertStatusFilterRuleRegistry, buildShowBuildingBlockFilter, - buildShowBuildingBlockFilterRuleRegistry, buildThreatMatchFilter, } from '../../../../components/alerts_table/default_config'; import { RuleSwitch } from '../../../../components/rules/rule_switch'; @@ -250,9 +248,6 @@ const RuleDetailsPageComponent: React.FC = ({ const { globalFullScreen } = useGlobalFullScreen(); const [filterGroup, setFilterGroup] = useState(FILTER_OPEN); - // TODO: Once we are past experimental phase this code should be removed - const ruleRegistryEnabled = useIsExperimentalFeatureEnabled('ruleRegistryEnabled'); - // TODO: Steph/ueba remove when past experimental const uebaEnabled = useIsExperimentalFeatureEnabled('uebaEnabled'); @@ -416,39 +411,21 @@ const RuleDetailsPageComponent: React.FC = ({ const alertDefaultFilters = useMemo( () => [ - ...buildAlertsRuleIdFilter(ruleId), - ...(ruleRegistryEnabled - ? [ - ...buildShowBuildingBlockFilterRuleRegistry(showBuildingBlockAlerts), // TODO: Once we are past experimental phase this code should be removed - ...buildAlertStatusFilterRuleRegistry(filterGroup), - ] - : [ - ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), - ...buildAlertStatusFilter(filterGroup), - ]), + ...buildAlertsFilter(rule?.rule_id ?? ''), + ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), + ...buildAlertStatusFilter(filterGroup), ...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts), ], - [ - ruleId, - ruleRegistryEnabled, - showBuildingBlockAlerts, - showOnlyThreatIndicatorAlerts, - filterGroup, - ] + [rule, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts, filterGroup] ); const alertsTableDefaultFilters = useMemo( () => [ - ...buildAlertsRuleIdFilter(ruleId), - ...(ruleRegistryEnabled - ? [ - // TODO: Once we are past experimental phase this code should be removed - ...buildShowBuildingBlockFilterRuleRegistry(showBuildingBlockAlerts), - ] - : [...buildShowBuildingBlockFilter(showBuildingBlockAlerts)]), + ...buildAlertsFilter(rule?.rule_id ?? ''), + ...buildShowBuildingBlockFilter(showBuildingBlockAlerts), ...buildThreatMatchFilter(showOnlyThreatIndicatorAlerts), ], - [ruleId, ruleRegistryEnabled, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts] + [rule, showBuildingBlockAlerts, showOnlyThreatIndicatorAlerts] ); const alertMergedFilters = useMemo( diff --git a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/use_filters_for_signals_by_category.ts b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/use_filters_for_signals_by_category.ts index 69d43d822eff7..d1ec19803fa72 100644 --- a/x-pack/plugins/security_solution/public/overview/components/signals_by_category/use_filters_for_signals_by_category.ts +++ b/x-pack/plugins/security_solution/public/overview/components/signals_by_category/use_filters_for_signals_by_category.ts @@ -8,11 +8,7 @@ import { useMemo } from 'react'; import type { Filter } from '@kbn/es-query'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; -import { - buildShowBuildingBlockFilter, - buildShowBuildingBlockFilterRuleRegistry, -} from '../../../detections/components/alerts_table/default_config'; +import { buildShowBuildingBlockFilter } from '../../../detections/components/alerts_table/default_config'; // On the Overview page, in the Detection Alert Trend, we never show // "building block" alerts to remove noise from the Overview UI. @@ -20,17 +16,9 @@ import { const SHOW_BUILDING_BLOCK_ALERTS = false; export const useFiltersForSignalsByCategory = (baseFilters: Filter[]) => { - // TODO: Once we are past experimental phase this code should be removed - const ruleRegistryEnabled = useIsExperimentalFeatureEnabled('ruleRegistryEnabled'); - const resultingFilters = useMemo( - () => [ - ...baseFilters, - ...(ruleRegistryEnabled - ? buildShowBuildingBlockFilterRuleRegistry(SHOW_BUILDING_BLOCK_ALERTS) // TODO: Once we are past experimental phase this code should be removed - : buildShowBuildingBlockFilter(SHOW_BUILDING_BLOCK_ALERTS)), - ], - [baseFilters, ruleRegistryEnabled] + () => [...baseFilters, ...buildShowBuildingBlockFilter(SHOW_BUILDING_BLOCK_ALERTS)], + [baseFilters] ); return resultingFilters; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_status_internal_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_status_internal_route.test.ts index 285b839cacb9f..69f36422aafc5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_status_internal_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rule_status_internal_route.test.ts @@ -11,6 +11,7 @@ import { getAlertMock, getRuleExecutionStatusSucceeded, getRuleExecutionStatusFailed, + resolveAlertMock, } from '../__mocks__/request_responses'; import { serverMock, requestContextMock, requestMock } from '../__mocks__'; import { findRuleStatusInternalRoute } from './find_rule_status_internal_route'; @@ -38,6 +39,9 @@ describe.each([ clients.rulesClient.get.mockResolvedValue( getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) ); + clients.rulesClient.resolve.mockResolvedValue( + resolveAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); findRuleStatusInternalRoute(server.router); }); @@ -70,7 +74,7 @@ describe.each([ test('returns success if rule status client writes an error status', async () => { // 0. task manager tried to run the rule but couldn't, so the alerting framework // wrote an error to the executionStatus. - const failingExecutionRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const failingExecutionRule = resolveAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); failingExecutionRule.executionStatus = { status: 'error', lastExecutionDate: failingExecutionRule.executionStatus.lastExecutionDate, @@ -81,7 +85,7 @@ describe.each([ }; // 1. getFailingRules api found a rule where the executionStatus was 'error' - clients.rulesClient.get.mockResolvedValue({ + clients.rulesClient.resolve.mockResolvedValue({ ...failingExecutionRule, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts index 5fe15c2839066..20dd37839f9d0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.test.ts @@ -20,7 +20,7 @@ import { } from './utils'; import { responseMock } from './__mocks__'; import { exampleRuleStatus } from '../signals/__mocks__/es_results'; -import { getAlertMock } from './__mocks__/request_responses'; +import { resolveAlertMock } from './__mocks__/request_responses'; import { AlertExecutionStatusErrorReasons } from '../../../../../alerting/common'; import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; import { RuleExecutionStatus } from '../../../../common/detection_engine/schemas/common/schemas'; @@ -223,12 +223,14 @@ describe.each([ rulesClient = rulesClientMock.create(); }); it('getFailingRules finds no failing rules', async () => { - rulesClient.get.mockResolvedValue(getAlertMock(isRuleRegistryEnabled, getQueryRuleParams())); + rulesClient.resolve.mockResolvedValue( + resolveAlertMock(isRuleRegistryEnabled, getQueryRuleParams()) + ); const res = await getFailingRules(['my-fake-id'], rulesClient); expect(res).toEqual({}); }); it('getFailingRules finds a failing rule', async () => { - const foundRule = getAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); + const foundRule = resolveAlertMock(isRuleRegistryEnabled, getQueryRuleParams()); foundRule.executionStatus = { status: 'error', lastExecutionDate: foundRule.executionStatus.lastExecutionDate, @@ -237,12 +239,12 @@ describe.each([ message: 'oops', }, }; - rulesClient.get.mockResolvedValue(foundRule); + rulesClient.resolve.mockResolvedValue(foundRule); const res = await getFailingRules([foundRule.id], rulesClient); expect(res).toEqual({ [foundRule.id]: foundRule }); }); it('getFailingRules throws an error', async () => { - rulesClient.get.mockImplementation(() => { + rulesClient.resolve.mockImplementation(() => { throw new Error('my test error'); }); let error; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts index 127c52496a5c5..a6e977207b838 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/utils.ts @@ -238,7 +238,7 @@ export const getFailingRules = async ( try { const errorRules = await Promise.all( ids.map(async (id) => - rulesClient.get({ + rulesClient.resolve({ id, }) )