[9.0] [Security Solution] Fix rule filters display issues (#222963) (#224303)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Security Solution] Fix rule filters display issues
(#222963)](https://github.com/elastic/kibana/pull/222963)

<!--- Backport version: 9.6.6 -->

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

<!--BACKPORT [{"author":{"name":"Nikita
Indik","email":"nikita.indik@elastic.co"},"sourceCommit":{"committedDate":"2025-06-17T16:14:44Z","message":"[Security
Solution] Fix rule filters display issues (#222963)\n\n**Resolves:
https://github.com/elastic/kibana/issues/203615**\n**Resolves:
https://github.com/elastic/kibana/issues/203600**\n\n## Summary\nThis PR
resolves a few bugs related to how query filters are displayed:\n- fixes
display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout (bug introduced in PR #210191)\n - fixes warnings
shown in edit mode of rule upgrade flyout\n- fixes warning flashes on
rule edit page when updating the index\npattern\n\n## Changes\n\n###
Display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout\nCaused by change in recent [PR](#210191) where we
stopped responding\nwith a full filter object.\n\n<details>\n
<summary>Click to see screenshots</summary>\n **Before**\n<img
width=\"951\"
alt=\"broken_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/3b06feb6-595f-4140-a795-3ac7a3d81fed\"\n/>\n\n
**After**\n<img width=\"948\"
alt=\"fixed_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/6a59c2a5-7165-4e4e-9a2f-8cb4250125a0\"\n/>\n</details>\n\n###
Warnings shown in edit mode of rule upgrade flyout\nCaused by a mismatch
between index patterns in filters and data view\nobjects. We path both
filters and a data view into a unified search\ncomponent. If it detects
a mismatch, it shows a confusing warning.\n\n<details>\n <summary>Click
to see screenshots</summary>\n **Before**\n<img width=\"1265\"
alt=\"broken_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/947be729-a247-4eee-8046-155c2599e0bd\"\n/>\n\n
**After**\n<img width=\"1265\"
alt=\"fixed_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/7bec19bc-5180-47f1-876e-850677d1503d\"\n/>\n</details>\n\n###
Warning flashes on rule edit page when updating the index
pattern\nCaused by a re-render with an incomplete DataView
object.\n\n<details>\n <summary>Click to see screen
recordings</summary>\n
**Before**\n\n\nhttps://github.com/user-attachments/assets/0140cfa5-4a87-4ed2-8c81-80e3b94e1166\n\n
**After**\n\n\nhttps://github.com/user-attachments/assets/0b539d11-bed2-4e4b-9399-ea95f7f5baa4\n\n</details>\n\nAlso
removed\n`x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/threatmatch_input/index.tsx`\nbecause
it was not used
anywhere.","sha":"f0829b7c1179ef998380153ad7dd5b6a3bee6ea2","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:fix","Team:Detections
and Resp","Team: SecuritySolution","Team:Detection Rule
Management","Feature:Prebuilt Detection Rules","Feature:Rule
Creation","Feature:Rule
Edit","backport:version","v9.1.0","v8.19.0","v9.0.3","v8.18.3","v8.17.8"],"title":"[Security
Solution] Fix rule filters display
issues","number":222963,"url":"https://github.com/elastic/kibana/pull/222963","mergeCommit":{"message":"[Security
Solution] Fix rule filters display issues (#222963)\n\n**Resolves:
https://github.com/elastic/kibana/issues/203615**\n**Resolves:
https://github.com/elastic/kibana/issues/203600**\n\n## Summary\nThis PR
resolves a few bugs related to how query filters are displayed:\n- fixes
display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout (bug introduced in PR #210191)\n - fixes warnings
shown in edit mode of rule upgrade flyout\n- fixes warning flashes on
rule edit page when updating the index\npattern\n\n## Changes\n\n###
Display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout\nCaused by change in recent [PR](#210191) where we
stopped responding\nwith a full filter object.\n\n<details>\n
<summary>Click to see screenshots</summary>\n **Before**\n<img
width=\"951\"
alt=\"broken_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/3b06feb6-595f-4140-a795-3ac7a3d81fed\"\n/>\n\n
**After**\n<img width=\"948\"
alt=\"fixed_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/6a59c2a5-7165-4e4e-9a2f-8cb4250125a0\"\n/>\n</details>\n\n###
Warnings shown in edit mode of rule upgrade flyout\nCaused by a mismatch
between index patterns in filters and data view\nobjects. We path both
filters and a data view into a unified search\ncomponent. If it detects
a mismatch, it shows a confusing warning.\n\n<details>\n <summary>Click
to see screenshots</summary>\n **Before**\n<img width=\"1265\"
alt=\"broken_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/947be729-a247-4eee-8046-155c2599e0bd\"\n/>\n\n
**After**\n<img width=\"1265\"
alt=\"fixed_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/7bec19bc-5180-47f1-876e-850677d1503d\"\n/>\n</details>\n\n###
Warning flashes on rule edit page when updating the index
pattern\nCaused by a re-render with an incomplete DataView
object.\n\n<details>\n <summary>Click to see screen
recordings</summary>\n
**Before**\n\n\nhttps://github.com/user-attachments/assets/0140cfa5-4a87-4ed2-8c81-80e3b94e1166\n\n
**After**\n\n\nhttps://github.com/user-attachments/assets/0b539d11-bed2-4e4b-9399-ea95f7f5baa4\n\n</details>\n\nAlso
removed\n`x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/threatmatch_input/index.tsx`\nbecause
it was not used
anywhere.","sha":"f0829b7c1179ef998380153ad7dd5b6a3bee6ea2"}},"sourceBranch":"main","suggestedTargetBranches":["8.19","9.0","8.18","8.17"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/222963","number":222963,"mergeCommit":{"message":"[Security
Solution] Fix rule filters display issues (#222963)\n\n**Resolves:
https://github.com/elastic/kibana/issues/203615**\n**Resolves:
https://github.com/elastic/kibana/issues/203600**\n\n## Summary\nThis PR
resolves a few bugs related to how query filters are displayed:\n- fixes
display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout (bug introduced in PR #210191)\n - fixes warnings
shown in edit mode of rule upgrade flyout\n- fixes warning flashes on
rule edit page when updating the index\npattern\n\n## Changes\n\n###
Display of filters with \"AND\"/\"OR\" logic in view mode of
rule\nupgrade flyout\nCaused by change in recent [PR](#210191) where we
stopped responding\nwith a full filter object.\n\n<details>\n
<summary>Click to see screenshots</summary>\n **Before**\n<img
width=\"951\"
alt=\"broken_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/3b06feb6-595f-4140-a795-3ac7a3d81fed\"\n/>\n\n
**After**\n<img width=\"948\"
alt=\"fixed_filters_flyout_view\"\nsrc=\"https://github.com/user-attachments/assets/6a59c2a5-7165-4e4e-9a2f-8cb4250125a0\"\n/>\n</details>\n\n###
Warnings shown in edit mode of rule upgrade flyout\nCaused by a mismatch
between index patterns in filters and data view\nobjects. We path both
filters and a data view into a unified search\ncomponent. If it detects
a mismatch, it shows a confusing warning.\n\n<details>\n <summary>Click
to see screenshots</summary>\n **Before**\n<img width=\"1265\"
alt=\"broken_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/947be729-a247-4eee-8046-155c2599e0bd\"\n/>\n\n
**After**\n<img width=\"1265\"
alt=\"fixed_filters_flyout_edit\"\nsrc=\"https://github.com/user-attachments/assets/7bec19bc-5180-47f1-876e-850677d1503d\"\n/>\n</details>\n\n###
Warning flashes on rule edit page when updating the index
pattern\nCaused by a re-render with an incomplete DataView
object.\n\n<details>\n <summary>Click to see screen
recordings</summary>\n
**Before**\n\n\nhttps://github.com/user-attachments/assets/0140cfa5-4a87-4ed2-8c81-80e3b94e1166\n\n
**After**\n\n\nhttps://github.com/user-attachments/assets/0b539d11-bed2-4e4b-9399-ea95f7f5baa4\n\n</details>\n\nAlso
removed\n`x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/threatmatch_input/index.tsx`\nbecause
it was not used
anywhere.","sha":"f0829b7c1179ef998380153ad7dd5b6a3bee6ea2"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.0","label":"v9.0.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.17","label":"v8.17.8","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Nikita Indik <nikita.indik@elastic.co>
This commit is contained in:
Kibana Machine 2025-06-17 20:04:52 +02:00 committed by GitHub
parent 58e519350f
commit 5fd06dc37b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 54 additions and 150 deletions

View file

@ -99,6 +99,11 @@ const normalizeFilterArray = (filters: RuleFilterArray | undefined): RuleFilterA
? {
negate: filter.meta.negate,
disabled: filter.meta.disabled !== undefined ? filter.meta.disabled : false,
params: filter.meta.params,
relation: 'relation' in filter.meta ? filter.meta?.relation : undefined,
type: filter.meta.type ?? 'custom',
alias: filter.meta.alias ?? undefined,
key: filter.meta.key ?? undefined,
}
: undefined,
}));

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { cloneDeep, isEmpty } from 'lodash';
import { isEmpty } from 'lodash';
import type { PropsWithChildren, FC } from 'react';
import React, { memo, useMemo, useCallback, useState, useEffect } from 'react';
import deepEqual from 'fast-deep-equal';
@ -20,6 +20,7 @@ import { Storage } from '@kbn/kibana-utils-plugin/public';
import { css, Global } from '@emotion/react';
import { useKibana } from '../../lib/kibana';
import { convertToQueryType } from './convert_to_query_type';
import { matchFiltersToIndexPattern } from './match_filters_to_index_pattern';
export interface QueryBarComponentProps {
dataTestSubj?: string;
@ -165,18 +166,12 @@ export const QueryBar = memo<QueryBarComponentProps>(
}, [data.dataViews, indexPattern, isEsql]);
const searchBarFilters = useMemo(() => {
if (isDataView(indexPattern) || isEsql) {
if (!dataView?.id || isEsql) {
return filters;
}
/**
* We update filters and set new data view id to make sure that SearchBar does not show data view picker
* More details in https://github.com/elastic/kibana/issues/174026
*/
const updatedFilters = cloneDeep(filters);
updatedFilters.forEach((filter) => (filter.meta.index = indexPattern.title));
return updatedFilters;
}, [filters, indexPattern, isEsql]);
return matchFiltersToIndexPattern(dataView.id, filters);
}, [filters, isEsql, dataView?.id]);
const timeHistory = useMemo(() => new TimeHistory(new Storage(localStorage)), []);
const arrDataView = useMemo(() => (dataView != null ? [dataView] : []), [dataView]);

View file

@ -0,0 +1,36 @@
/*
* 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 type { Filter } from '@kbn/es-query';
import { cloneDeep } from 'lodash';
/**
* Updates each filter's `meta.index` property to match the specified index pattern.
*
* This ensures compatibility with the filters UI component, which requires `meta.index`
* to match the current index pattern. If it doesn't, the UI will:
* - Display a vague warning: "Field does not exist in current view"
* (see: https://github.com/elastic/kibana/issues/178908)
* - Display the word "warning" instead of an actual value for filters with "AND" or "OR" operators
* (see: https://github.com/elastic/kibana/issues/203615)
* - Show an unnecessary data view selector in the filter editor
* (see: https://github.com/elastic/kibana/pull/174922)
*
* To prevent this confusing behavior, we explicitly set `meta.index` on each filter
* to match the provided index pattern string.
*
* @param indexPattern Index pattern string to associate the filters with.
* @param filters An array of filters to update.
* @returns A new array of filters with the updated index property.
*/
export function matchFiltersToIndexPattern(indexPattern: string, filters: Filter[]): Filter[] {
const updatedFilters = cloneDeep(filters);
updatedFilters.forEach((filter) => {
filter.meta.index = indexPattern;
});
return updatedFilters;
}

View file

@ -1,119 +0,0 @@
/*
* 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 React, { memo, useCallback, useEffect, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiFormRow } from '@elastic/eui';
import type { DataViewBase } from '@kbn/es-query';
import type { ThreatMapEntries } from '../../../../common/components/threat_match/types';
import { ThreatMatchComponent } from '../../../../common/components/threat_match';
import type { FieldHook } from '../../../../shared_imports';
import { UseField, getFieldValidityAndErrorMessage } from '../../../../shared_imports';
import { schema } from '../step_define_rule/schema';
import { QueryBarField } from '../query_bar_field';
interface ThreatMatchEditProps {
path: string;
threatIndexPatterns: DataViewBase;
indexPatterns: DataViewBase;
threatIndexPatternsLoading: boolean;
onValidityChange?: (isValid: boolean) => void;
}
export const ThreatMatchEdit = memo(function ThreatMatchEdit({
path,
indexPatterns,
threatIndexPatterns,
threatIndexPatternsLoading,
onValidityChange,
}: ThreatMatchEditProps): JSX.Element {
const componentProps = {
indexPatterns,
threatIndexPatterns,
threatIndexPatternsLoading,
onValidityChange,
};
return <UseField path={path} component={ThreatMatchField} componentProps={componentProps} />;
});
interface ThreatMatchFieldProps {
field: FieldHook<ThreatMapEntries[]>;
threatIndexPatterns: DataViewBase;
indexPatterns: DataViewBase;
threatIndexPatternsLoading: boolean;
onValidityChange?: (isValid: boolean) => void;
}
function ThreatMatchField({
field,
threatIndexPatterns,
indexPatterns,
threatIndexPatternsLoading,
onValidityChange,
}: ThreatMatchFieldProps): JSX.Element {
const { isInvalid: isThreatMappingInvalid, errorMessage } =
getFieldValidityAndErrorMessage(field);
const [isThreatIndexPatternValid, setIsThreatIndexPatternValid] = useState(false);
useEffect(() => {
if (onValidityChange) {
onValidityChange(!isThreatMappingInvalid && isThreatIndexPatternValid);
}
}, [isThreatIndexPatternValid, isThreatMappingInvalid, onValidityChange]);
const handleMappingsEntryChange = useCallback(
(newEntryItems: ThreatMapEntries[]): void => {
field.setValue(newEntryItems);
},
[field]
);
return (
<>
<EuiFlexGroup direction="column">
<EuiFlexItem grow>
<UseField
path="threatQueryBar"
config={{
...schema.threatQueryBar,
labelAppend: null,
}}
component={QueryBarField}
componentProps={{
idAria: 'detectionEngineStepDefineThreatRuleQueryBar',
indexPattern: threatIndexPatterns,
isDisabled: false,
isLoading: threatIndexPatternsLoading,
dataTestSubj: 'detectionEngineStepDefineThreatRuleQueryBar',
openTimelineSearch: false,
onValidityChange: setIsThreatIndexPatternValid,
}}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
<EuiFormRow
label={field.label}
labelAppend={field.labelAppend}
helpText={field.helpText}
error={errorMessage}
isInvalid={isThreatMappingInvalid}
fullWidth
>
<ThreatMatchComponent
mappingEntries={field.value}
indexPatterns={indexPatterns}
threatIndexPatterns={threatIndexPatterns}
data-test-subj="threatmatch-builder"
id-aria="threatmatch-builder"
onMappingEntriesChange={handleMappingsEntryChange}
/>
</EuiFormRow>
<EuiSpacer size="m" />
</>
);
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useMemo } from 'react';
import React from 'react';
import { isEmpty } from 'lodash/fp';
import {
EuiDescriptionList,
@ -27,7 +27,6 @@ import type { SavedQuery } from '@kbn/data-plugin/public';
import { mapAndFlattenFilters } from '@kbn/data-plugin/public';
import { FilterItems } from '@kbn/unified-search-plugin/public';
import useToggle from 'react-use/lib/useToggle';
import { isDataView } from '../../../../common/components/query_bar';
import type {
AlertSuppressionMissingFieldsStrategy,
EqlOptionalFields,
@ -68,6 +67,7 @@ import {
EQL_OPTIONS_EVENT_TIMESTAMP_FIELD_LABEL,
} from '../../../rule_creation/components/eql_query_edit/translations';
import { useDataView } from './three_way_diff/final_edit/fields/hooks/use_data_view';
import { matchFiltersToIndexPattern } from '../../../../common/components/query_bar/match_filters_to_index_pattern';
interface SavedQueryNameProps {
savedQueryName: string;
@ -97,29 +97,16 @@ export const Filters = ({
? { dataViewId }
: { indexPatterns: index ?? defaultIndexPattern };
const { dataView } = useDataView(useDataViewParams);
const isEsql = filters.some((filter) => filter?.query?.language === 'esql');
const searchBarFilters = useMemo(() => {
if (!index || isDataView(index) || isEsql) {
return filters;
}
const filtersWithUpdatedMetaIndex = filters.map((filter) => {
return {
...filter,
meta: {
...filter.meta,
index: index.join(','),
},
};
});
return filtersWithUpdatedMetaIndex;
}, [filters, index, isEsql]);
if (!dataView) {
if (!dataView?.id || isEsql) {
return null;
}
const flattenedFilters = mapAndFlattenFilters(searchBarFilters);
const flattenedFilters = mapAndFlattenFilters(filters);
const matchedFilters = matchFiltersToIndexPattern(dataView.id, flattenedFilters);
const styles = filtersStyles;
return (
@ -130,7 +117,7 @@ export const Filters = ({
responsive={false}
gutterSize="xs"
>
<FilterItems filters={flattenedFilters} indexPatterns={[dataView]} readOnly />
<FilterItems filters={matchedFilters} indexPatterns={[dataView]} readOnly />
</EuiFlexGroup>
);
};