mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
# 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:
parent
58e519350f
commit
5fd06dc37b
5 changed files with 54 additions and 150 deletions
|
@ -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,
|
||||
}));
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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" />
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue