From a8048ddf6b3f6623c87236c875a0ef1506a39fe2 Mon Sep 17 00:00:00 2001 From: Luke Gmys <11671118+lgestc@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:11:00 +0100 Subject: [PATCH] [Security Solution] Remove index pattern field from Sourcerer (#190113) ## Summary This PR removes index pattern field from the sourcerer model, replacing it with direct access to data view spec. The end goal for the sourcerer is to just utilize platform wide Data View Types, instead of some custom abstractions / containers such as indexPattern field which is effectively a DataViewSpec, just packed up differently. --- .../top_values_popover/top_values_popover.tsx | 4 +- .../common/components/events_viewer/index.tsx | 9 ++- .../markdown_editor/plugins/insight/index.tsx | 6 +- .../plugins/insight/use_insight_query.ts | 6 +- .../common/components/top_n/index.test.tsx | 4 +- .../public/common/components/top_n/index.tsx | 8 +-- .../common/components/top_n/top_n.test.tsx | 4 +- .../public/common/components/top_n/top_n.tsx | 7 ++- .../alerts/alerts_by_status_donut.test.ts | 1 + .../common/alerts/alerts_histogram.test.ts | 1 + .../common/alerts/alerts_table.test.ts | 1 + .../common/alerts/rule_preview.test.ts | 1 + .../common/authentication.test.ts | 1 + .../lens_attributes/common/event.test.ts | 1 + .../common/external_alert.test.ts | 1 + .../hosts/kpi_host_area.test.ts | 1 + .../hosts/kpi_host_metric.test.ts | 1 + .../hosts/kpi_unique_ips_area.test.ts | 1 + .../hosts/kpi_unique_ips_bar.test.ts | 1 + .../kpi_unique_ips_destination_metric.test.ts | 1 + .../kpi_unique_ips_source_metric.test.ts | 1 + .../network/dns_top_domains.test.ts | 1 + .../network/kpi_dns_queries.test.ts | 1 + .../network/kpi_network_events.test.ts | 1 + .../network/kpi_tls_handshakes.test.ts | 1 + .../network/kpi_unique_flow_ids.test.ts | 1 + .../kpi_unique_private_ips_area.test.ts | 1 + .../kpi_unique_private_ips_bar.test.ts | 1 + ...que_private_ips_destination_metric.test.ts | 1 + ...i_unique_private_ips_source_metric.test.ts | 1 + .../users/kpi_total_users_area.test.ts | 1 + .../users/kpi_total_users_metric.test.ts | 1 + ...user_authentication_metric_failure.test.ts | 1 + .../kpi_user_authentications_area.test.ts | 1 + .../kpi_user_authentications_bar.test.ts | 1 + ...ser_authentications_metric_success.test.ts | 1 + .../use_lens_attributes.test.tsx | 5 ++ .../public/common/lib/kuery/index.test.ts | 6 +- .../public/common/lib/kuery/index.ts | 17 ++++-- .../public/common/mock/index_pattern.ts | 5 ++ .../execution_log_table.test.tsx | 2 +- .../execution_log_table.tsx | 36 ++++++----- .../pages/rule_details/index.tsx | 2 +- .../alerts_kpis/chart_panels/index.test.tsx | 1 + .../alerts_table/alerts_grouping.test.tsx | 1 + .../alerts_table/alerts_grouping.tsx | 8 ++- .../alerts_table/alerts_sub_grouping.tsx | 8 +-- .../components/alerts_table/index.tsx | 16 ++--- .../use_add_bulk_to_timeline.tsx | 7 +-- .../detection_engine_filters.test.tsx | 4 +- .../detection_engine_filters.tsx | 9 ++- .../render_cell_value.test.tsx | 1 + .../rules/use_rule_from_timeline.test.ts | 1 + .../use_persistent_controls.test.tsx | 1 + .../use_persistent_controls.tsx | 8 ++- .../detection_engine.test.tsx | 5 +- .../detection_engine/detection_engine.tsx | 16 +++-- .../api/hooks/use_preview_risk_scores.ts | 60 +++++++++++-------- .../components/risk_score_preview_section.tsx | 41 +++++++------ .../index.tsx | 2 +- .../lens_attributes/risk_score_donut.test.ts | 1 + .../risk_score_over_time_area.test.ts | 1 + .../risk_score_summary.test.ts | 1 + .../hosts/pages/details/details_tabs.test.tsx | 41 +++++++------ .../hosts/pages/details/details_tabs.tsx | 2 +- .../explore/hosts/pages/details/index.tsx | 10 ++-- .../explore/hosts/pages/details/types.ts | 5 +- .../public/explore/hosts/pages/hosts.tsx | 11 ++-- .../network/pages/details/index.test.tsx | 4 ++ .../explore/network/pages/details/index.tsx | 12 ++-- .../pages/navigation/network_routes.tsx | 9 ++- .../explore/network/pages/navigation/types.ts | 5 +- .../explore/network/pages/network.test.tsx | 1 + .../public/explore/network/pages/network.tsx | 11 ++-- .../explore/users/pages/details/index.tsx | 10 ++-- .../explore/users/pages/details/types.ts | 5 +- .../public/explore/users/pages/users.tsx | 11 ++-- .../left/components/entities_details.test.tsx | 4 +- .../left/components/host_details.test.tsx | 4 +- .../left/components/session_view.test.tsx | 3 +- .../left/components/user_details.test.tsx | 4 +- .../use_threat_intelligence_details.test.ts | 3 +- .../hooks/use_threat_intelligence_details.ts | 2 +- .../shared/hooks/use_event_details.test.tsx | 3 +- .../shared/hooks/use_event_details.ts | 8 +-- .../components/network_details.tsx | 4 +- .../public/kubernetes/pages/index.tsx | 9 +-- .../utils/data_view_spec_to_index_pattern.ts | 15 +++++ .../components/event_counts/index.test.tsx | 4 +- .../components/event_counts/index.tsx | 16 ++--- .../components/events_by_dataset/index.tsx | 11 ++-- .../public/overview/pages/overview.tsx | 7 +-- .../components/alerts_sourcerer.test.tsx | 1 + .../public/sourcerer/components/index.tsx | 4 +- .../components/sourcerer_integration.test.tsx | 1 + .../components/timeline_sourcerer.test.tsx | 1 + .../use_get_sourcerer_data_view.test.ts | 4 +- .../use_get_sourcerer_data_view.tsx | 2 +- .../sourcerer/containers/hooks.test.tsx | 7 +-- .../public/sourcerer/containers/index.tsx | 4 +- .../public/sourcerer/containers/mocks.ts | 13 ---- .../public/sourcerer/store/model.ts | 8 +-- .../actions/open_timeline_button.test.tsx | 6 +- .../components/modal/header/index.test.tsx | 3 + .../components/modal/header/index.tsx | 14 ++++- .../components/timeline/kpi/kpi_container.tsx | 6 +- .../timeline/query_bar/eql/index.tsx | 42 ++++++------- .../components/timeline/query_bar/index.tsx | 16 ++++- .../timeline/search_or_filter/index.tsx | 27 ++++----- .../components/timeline/tabs/eql/index.tsx | 2 +- .../components/timeline/tabs/pinned/index.tsx | 2 +- .../components/timeline/tabs/query/index.tsx | 7 +-- .../timelines/pages/timelines_page.test.tsx | 2 + .../query_bar/hooks/use_filter_in_out.ts | 4 +- .../threat_intelligence/public/types.ts | 2 +- 115 files changed, 436 insertions(+), 317 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts diff --git a/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx index f03be50f39660..3f7842c4a2e92 100644 --- a/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx +++ b/x-pack/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx @@ -16,7 +16,7 @@ import { useKibana } from '../../../common/lib/kibana'; export const TopValuesPopover = React.memo(() => { const { pathname } = useLocation(); - const { browserFields, indexPattern } = useSourcererDataView(getScopeFromPath(pathname)); + const { browserFields, sourcererDataView } = useSourcererDataView(getScopeFromPath(pathname)); const { services: { topValuesPopover }, } = useKibana(); @@ -44,7 +44,7 @@ export const TopValuesPopover = React.memo(() => { showLegend scopeId={data.scopeId} toggleTopN={onClose} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} browserFields={browserFields} /> diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index e251370c7e4d3..b86f65e020a11 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -180,9 +180,8 @@ const StatefulEventsViewerComponent: React.FC) => { const isEditMode = node != null; - const { indexPattern } = useSourcererDataView(SourcererScopeName.default); + const { sourcererDataView } = useSourcererDataView(SourcererScopeName.default); const { unifiedSearch: { ui: { FiltersBuilderLazy }, @@ -400,7 +400,7 @@ const InsightEditorComponent = ({ ); }, [labelController.field.value, providers, dataView]); const filtersStub = useMemo(() => { - const index = indexPattern && indexPattern.getName ? indexPattern.getName() : '*'; + const index = sourcererDataView.name ?? '*'; return [ { $state: { @@ -414,7 +414,7 @@ const InsightEditorComponent = ({ }, }, ]; - }, [indexPattern]); + }, [sourcererDataView]); const isPlatinum = useLicense().isAtLeast('platinum'); return ( diff --git a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts index 43323a6b62f7a..a88485237e21c 100644 --- a/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts +++ b/x-pack/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts @@ -41,7 +41,7 @@ export const useInsightQuery = ({ }: UseInsightQuery): UseInsightQueryResult => { const { uiSettings } = useKibana().services; const esQueryConfig = useMemo(() => getEsQueryConfig(uiSettings), [uiSettings]); - const { browserFields, selectedPatterns, indexPattern, dataViewId } = useSourcererDataView( + const { browserFields, selectedPatterns, sourcererDataView, dataViewId } = useSourcererDataView( SourcererScopeName.timeline ); const [hasError, setHasError] = useState(false); @@ -51,7 +51,7 @@ export const useInsightQuery = ({ const parsedCombinedQueries = combineQueries({ config: esQueryConfig, dataProviders, - indexPattern, + indexPattern: sourcererDataView, browserFields, filters, kqlQuery: { @@ -66,7 +66,7 @@ export const useInsightQuery = ({ setHasError(true); return null; } - }, [browserFields, dataProviders, esQueryConfig, hasError, indexPattern, filters]); + }, [browserFields, dataProviders, esQueryConfig, hasError, sourcererDataView, filters]); const [dataLoadingState, { events, totalCount }] = useTimelineEvents({ dataViewId, diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx index 6c45faf63e566..2359aed5d6949 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.test.tsx @@ -10,7 +10,7 @@ import { mount } from 'enzyme'; import React from 'react'; import { waitFor } from '@testing-library/react'; import { mockBrowserFields } from '../../containers/source/mock'; -import { mockGlobalState, TestProviders, mockIndexPattern, createMockStore } from '../../mock'; +import { mockGlobalState, TestProviders, createMockStore, mockDataViewSpec } from '../../mock'; import type { State } from '../../store'; import type { Props } from './top_n'; @@ -145,7 +145,7 @@ const store = createMockStore(state); const testProps = { browserFields: mockBrowserFields, field, - indexPattern: mockIndexPattern, + indexPattern: mockDataViewSpec, scopeId: TableId.hostsPageEvents, toggleTopN: jest.fn(), onFilterAdded: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx index cdad88b247f2d..11ec06908afe7 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx @@ -9,8 +9,8 @@ import React, { useMemo } from 'react'; import type { ConnectedProps } from 'react-redux'; import { connect } from 'react-redux'; -import type { DataViewBase, Filter, Query } from '@kbn/es-query'; -import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import type { Filter, Query } from '@kbn/es-query'; +import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; import { isActiveTimeline } from '../../../helpers'; import { InputsModelId } from '../../store/inputs/constants'; import { useGlobalTime } from '../../containers/use_global_time'; @@ -77,7 +77,7 @@ const connector = connect(makeMapStateToProps); export interface OwnProps { browserFields: BrowserFields; field: string; - indexPattern: DataViewBase; + dataViewSpec?: DataViewSpec; scopeId?: string; toggleTopN: () => void; onFilterAdded?: () => void; @@ -97,7 +97,7 @@ const StatefulTopNComponent: React.FC = ({ browserFields, dataProviders, field, - indexPattern, + dataViewSpec: indexPattern, globalFilters = EMPTY_FILTERS, globalQuery = EMPTY_QUERY, kqlMode, diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx index 79ab897e34bfc..73086e2d584be 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.test.tsx @@ -10,7 +10,7 @@ import { mount } from 'enzyme'; import React from 'react'; import { waitFor } from '@testing-library/react'; -import { TestProviders, mockIndexPattern } from '../../mock'; +import { TestProviders, mockDataViewSpec } from '../../mock'; import { allEvents, defaultOptions } from './helpers'; import type { Props as TopNProps } from './top_n'; @@ -107,7 +107,7 @@ describe('TopN', () => { field, filters: [], from: '2020-04-14T00:31:47.695Z', - indexPattern: mockIndexPattern, + indexPattern: mockDataViewSpec, options: defaultOptions, query, setAbsoluteRangeDatePickerTarget: InputsModelId.global, diff --git a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx index 48386a71a07fc..5c3cecfe3fce3 100644 --- a/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -9,7 +9,8 @@ import { EuiButtonIcon, EuiSuperSelect } from '@elastic/eui'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; -import type { DataViewBase, Filter, Query } from '@kbn/es-query'; +import type { Filter, Query } from '@kbn/es-query'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import type { GlobalTimeArgs } from '../../containers/use_global_time'; import { EventsByDataset } from '../../../overview/components/events_by_dataset'; import { SignalsByCategory } from '../../../overview/components/signals_by_category'; @@ -48,7 +49,7 @@ export interface Props extends Pick = ({ filters={applicableFilters} from={from} headerChildren={headerChildren} - indexPattern={indexPattern} + dataViewSpec={indexPattern} onlyField={field} paddingSize={paddingSize} query={query} diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_by_status_donut.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_by_status_donut.test.ts index 98f64ab00152a..7240f1de35ac6 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_by_status_donut.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_by_status_donut.test.ts @@ -20,6 +20,7 @@ jest.mock('../../../../../../sourcerer/containers', () => ({ dataViewId: 'security-solution-my-test', indicesExist: true, selectedPatterns: ['signal-index'], + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_histogram.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_histogram.test.ts index dd4b7050632e0..d712f69a295a1 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_histogram.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_histogram.test.ts @@ -20,6 +20,7 @@ jest.mock('../../../../../../sourcerer/containers', () => ({ dataViewId: 'security-solution-my-test', indicesExist: true, selectedPatterns: ['signal-index'], + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_table.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_table.test.ts index 399bf374bb707..cec804e090f10 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_table.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/alerts_table.test.ts @@ -32,6 +32,7 @@ jest.mock('../../../../../../sourcerer/containers', () => ({ dataViewId: 'security-solution-my-test', indicesExist: true, selectedPatterns: ['signal-index'], + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/rule_preview.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/rule_preview.test.ts index 6c704ae9e532f..73f871def8ee9 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/rule_preview.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/alerts/rule_preview.test.ts @@ -22,6 +22,7 @@ jest.mock('../../../../../../sourcerer/containers', () => ({ dataViewId: 'security-solution-my-test', indicesExist: true, selectedPatterns: ['signal-index'], + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.test.ts index 1abba440af95c..6d2b510da4897 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/authentication.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/event.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/event.test.ts index a7855ff7367bd..b29b10f8b9b4e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/event.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/event.test.ts @@ -22,6 +22,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.test.ts index 5c4998a03524c..8fd7c0a57cc6e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/common/external_alert.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.test.ts index 9c7ff9e3acf7b..6ab9c4b599057 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.test.ts index d2714b44c2930..0a146fae457ef 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_host_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.test.ts index 3a591a1eb2b1a..003176c784c17 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.test.ts index fa3f49f7b1054..5121aab8bf8bf 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_bar.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.test.ts index a2ae91e0c0422..eff175a0b5466 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_destination_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.test.ts index e94efb88b58ad..cd9f68d632478 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/hosts/kpi_unique_ips_source_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.test.ts index e398b33f0570b..bb0d0cb5c9012 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/dns_top_domains.test.ts @@ -19,6 +19,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.test.ts index 9e766f03163d8..6c0cb3d3d8198 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_dns_queries.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.test.ts index ef921e3601373..6e2a66567f1e0 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_network_events.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.test.ts index d6c4eb3fadc25..f0b87c0ee221a 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_tls_handshakes.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.test.ts index ba0cd4f60fe99..414bc1263e93e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_flow_ids.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.test.ts index 7a19fa5e024fc..9ac8d9733d157 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.test.ts index 9b4cd751ee54b..25fc271e7ef62 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_bar.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.test.ts index 5c3479c53c410..a7fd2208bec47 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_destination_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.test.ts index a076dc40a46e4..6208d5c97bdc9 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/network/kpi_unique_private_ips_source_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.test.ts index 50b72daa8d532..a34e98b70e607 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.test.ts index fae4b63083906..affbdd4a77905 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_total_users_metric.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.test.ts index 6c9de837708e6..4c93280dd3b9e 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentication_metric_failure.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.test.ts index 3f00f93c24875..599ceb9745f53 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.test.ts index 6a6cd9cc7ad3b..2231459b347ed 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_bar.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.test.ts b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.test.ts index 367a883e93dec..3ab3de0592d77 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/lens_attributes/users/kpi_user_authentications_metric_success.test.ts @@ -17,6 +17,7 @@ jest.mock('../../../../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.test.tsx index 22fa8c774eebe..8ed7d40519ace 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.test.tsx @@ -35,6 +35,7 @@ describe('useLensAttributes', () => { dataViewId: 'security-solution-default', indicesExist: true, selectedPatterns: ['auditbeat-*'], + sourcererDataView: {}, }); (useRouteSpy as jest.Mock).mockReturnValue([ { @@ -237,6 +238,7 @@ describe('useLensAttributes', () => { dataViewId: 'security-solution-default', indicesExist: false, selectedPatterns: ['auditbeat-*'], + sourcererDataView: {}, }); const { result } = renderHook( () => @@ -255,6 +257,7 @@ describe('useLensAttributes', () => { dataViewId: 'security-solution-default', indicesExist: false, selectedPatterns: ['auditbeat-*'], + sourcererDataView: {}, }); const { result } = renderHook( () => @@ -273,6 +276,7 @@ describe('useLensAttributes', () => { dataViewId: 'security-solution-default', indicesExist: false, selectedPatterns: ['auditbeat-*'], + sourcererDataView: {}, }); const { result } = renderHook( () => @@ -294,6 +298,7 @@ describe('useLensAttributes', () => { dataViewId: 'security-solution-default', indicesExist: false, selectedPatterns: ['auditbeat-*'], + sourcererDataView: {}, }); const { result } = renderHook( () => diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts index 095f49d2f1e0e..98c59d415d447 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.test.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import type { DataProvider } from '../../../../common/types/timeline'; import { convertToBuildEsQuery, buildGlobalQuery } from '.'; -import { mockIndexPattern } from '../../mock'; +import { mockDataViewSpec } from '../../mock'; describe('convertToBuildEsQuery', () => { /** @@ -61,7 +61,7 @@ describe('convertToBuildEsQuery', () => { const [converted, _] = convertToBuildEsQuery({ config, queries: queryWithNestedFields, - indexPattern: mockIndexPattern, + dataViewSpec: mockDataViewSpec, filters, }); @@ -176,7 +176,7 @@ describe('convertToBuildEsQuery', () => { const [converted, _] = convertToBuildEsQuery({ config: configWithOverride, queries: queryWithNestedFields, - indexPattern: mockIndexPattern, + dataViewSpec: mockDataViewSpec, filters, }); diff --git a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts index b3f98a8483f30..c3ae79dd80e95 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kuery/index.ts @@ -14,6 +14,7 @@ import { } from '@kbn/es-query'; import { get, isEmpty } from 'lodash/fp'; import memoizeOne from 'memoize-one'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import { prepareKQLParam } from '../../../../common/utils/kql'; import type { BrowserFields } from '../../../../common/search_strategy'; import type { DataProvider, DataProvidersAnd } from '../../../../common/types'; @@ -29,7 +30,7 @@ export type PrimitiveOrArrayOfPrimitives = export interface CombineQueries { config: EsQueryConfig; dataProviders: DataProvider[]; - indexPattern: DataViewBase; + indexPattern?: DataViewSpec; browserFields: BrowserFields; filters: Filter[]; kqlQuery: Query; @@ -199,14 +200,18 @@ export const isDataProviderEmpty = (dataProviders: DataProvider[]) => { return isEmpty(dataProviders) || isEmpty(dataProviders.filter((d) => d.enabled === true)); }; +export const dataViewSpecToViewBase = (dataViewSpec?: DataViewSpec): DataViewBase => { + return { title: dataViewSpec?.title || '', fields: Object.values(dataViewSpec?.fields || {}) }; +}; + export const convertToBuildEsQuery = ({ config, - indexPattern, + dataViewSpec, queries, filters, }: { config: EsQueryConfig; - indexPattern: DataViewBase | undefined; + dataViewSpec: DataViewSpec | undefined; queries: Query[]; filters: Filter[]; }): [string, undefined] | [undefined, Error] => { @@ -214,7 +219,7 @@ export const convertToBuildEsQuery = ({ return [ JSON.stringify( buildEsQuery( - indexPattern, + dataViewSpecToViewBase(dataViewSpec), queries, filters.filter((f) => f.meta.disabled === false), { @@ -253,7 +258,7 @@ export const combineQueries = ({ const [filterQuery, kqlError] = convertToBuildEsQuery({ config, queries: [kuery], - indexPattern, + dataViewSpec: indexPattern, filters, }); @@ -281,7 +286,7 @@ export const combineQueries = ({ const [filterQuery, kqlError] = convertToBuildEsQuery({ config, queries: [kuery], - indexPattern, + dataViewSpec: indexPattern, filters, }); diff --git a/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts b/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts index cc04177139a89..ec042d0b01e2d 100644 --- a/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts +++ b/x-pack/plugins/security_solution/public/common/mock/index_pattern.ts @@ -110,3 +110,8 @@ export const mockIndexPattern: SecuritySolutionDataViewBase = { }; export const mockIndexNames = ['filebeat-*', 'auditbeat-*', 'packetbeat-*']; + +export const mockDataViewSpec = { + fields: Object.fromEntries(mockIndexPattern.fields.map((f) => [f.name, f])), + title: 'filebeat-*,auditbeat-*,packetbeat-*', +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.test.tsx index 3a221836e3a35..4ed02135143ff 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.test.tsx @@ -47,11 +47,11 @@ const coreStart = coreMock.createStart(); const mockUseSourcererDataView = useSourcererDataView as jest.Mock; mockUseSourcererDataView.mockReturnValue({ - indexPattern: { fields: [] }, missingPatterns: {}, selectedPatterns: {}, scopeSelectedPatterns: {}, loading: false, + sourcererDataView: {}, }); const mockUseRuleExecutionEvents = useExecutionResults as jest.Mock; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx index 048780b259d22..4546e55522ce5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx @@ -37,6 +37,7 @@ import type { AnalyticsServiceStart } from '@kbn/core-analytics-browser'; import type { I18nStart } from '@kbn/core-i18n-browser'; import type { ThemeServiceStart } from '@kbn/core-theme-browser'; +import { dataViewSpecToViewBase } from '../../../../../common/lib/kuery'; import { InputsModelId } from '../../../../../common/store/inputs/constants'; import { @@ -159,7 +160,7 @@ const ExecutionLogTableComponent: React.FC = ({ } = useRuleDetailsContext(); // Index for `add filter` action and toasts for errors - const { indexPattern } = useSourcererDataView(SourcererScopeName.detections); + const { sourcererDataView } = useSourcererDataView(SourcererScopeName.detections); const { addError, addSuccess, remove } = useAppToasts(); // QueryString, Filters, and TimeRange state @@ -232,9 +233,10 @@ const ExecutionLogTableComponent: React.FC = ({ const maxEvents = events?.total ?? 0; // Cache UUID field from data view as it can be expensive to iterate all data view fields - const uuidDataViewField = useMemo(() => { - return indexPattern.fields.find((f) => f.name === EXECUTION_UUID_FIELD_NAME); - }, [indexPattern]); + const uuidDataViewField = useMemo( + () => sourcererDataView.fields?.[EXECUTION_UUID_FIELD_NAME], + [sourcererDataView] + ); // Callbacks const onTableChangeCallback = useCallback( @@ -299,12 +301,18 @@ const ExecutionLogTableComponent: React.FC = ({ const onFilterByExecutionIdCallback = useCallback( (executionId: string, executionStart: string) => { - if (uuidDataViewField != null) { + const dataViewAsViewBase = dataViewSpecToViewBase(sourcererDataView); + + if ( + uuidDataViewField != null && + typeof uuidDataViewField !== 'undefined' && + dataViewAsViewBase + ) { // Update cached global query state with current state as a rollback point cachedGlobalQueryState.current = { filters, query, timerange }; // Create filter & daterange constraints const filter = buildFilter( - indexPattern, + dataViewAsViewBase, uuidDataViewField, FILTERS.PHRASE, false, @@ -350,18 +358,18 @@ const ExecutionLogTableComponent: React.FC = ({ } }, [ - addError, - addSuccess, - dispatch, - filterManager, + uuidDataViewField, filters, - indexPattern, query, - resetGlobalQueryState, - selectAlertsTab, timerange, - uuidDataViewField, + sourcererDataView, + dispatch, + filterManager, + selectAlertsTab, + addSuccess, + resetGlobalQueryState, startServices, + addError, ] ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 91ba4276a79b2..851d219ad43d3 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -759,7 +759,7 @@ const RuleDetailsPageComponent: React.FC = ({ hasIndexWrite={hasIndexWrite ?? false} loading={loading} renderChildComponent={renderGroupedAlertTable} - runtimeMappings={sourcererDataView?.runtimeFieldMap as RunTimeMappings} + runtimeMappings={sourcererDataView.runtimeFieldMap as RunTimeMappings} signalIndexName={signalIndexName} tableId={TableId.alertsOnRuleDetailsPage} to={to} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/index.test.tsx index 668f323d147cb..38d68f2af0ad6 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/index.test.tsx @@ -156,6 +156,7 @@ describe('ChartPanels', () => { indicesExist: true, indexPattern: {}, browserFields: mockBrowserFields, + sourcererDataView: {}, }); (useAlertsLocalStorage as jest.Mock).mockReturnValue({ diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.test.tsx index 17c7ce8195c0c..cf57c9d59b080 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.test.tsx @@ -159,6 +159,7 @@ describe('GroupedAlertsTable', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ ...sourcererDataView, selectedPatterns: ['myFakebeat-*'], + sourcererDataView: {}, }); mockUseQueryAlerts.mockImplementation((i) => { if (i.skip) { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx index 8b02530fec07a..a1cbdc8004727 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx @@ -67,7 +67,9 @@ const useStorage = (storage: Storage, tableId: string) => const GroupedAlertsTableComponent: React.FC = (props) => { const dispatch = useDispatch(); - const { indexPattern, selectedPatterns } = useSourcererDataView(SourcererScopeName.detections); + const { sourcererDataView, selectedPatterns } = useSourcererDataView( + SourcererScopeName.detections + ); const { services: { storage, telemetry }, @@ -102,6 +104,8 @@ const GroupedAlertsTableComponent: React.FC = (props) [dispatch, props.tableId] ); + const fields = useMemo(() => Object.values(sourcererDataView.fields || {}), [sourcererDataView]); + const { getGrouping, selectedGroups, setSelectedGroups } = useGrouping({ componentProps: { groupPanelRenderer: renderGroupPanel, @@ -110,7 +114,7 @@ const GroupedAlertsTableComponent: React.FC = (props) unit: defaultUnit, }, defaultGroupingOptions: getDefaultGroupingOptions(props.tableId), - fields: indexPattern.fields, + fields, groupingId: props.tableId, maxGroupingLevels: MAX_GROUPING_LEVELS, onGroupChange, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx index 4b8c912c61a65..c941f5ecf46ed 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx @@ -91,15 +91,15 @@ export const GroupedSubLevelComponent: React.FC = ({ const { services: { uiSettings }, } = useKibana(); - const { browserFields, indexPattern } = useSourcererDataView(SourcererScopeName.detections); + const { browserFields, sourcererDataView } = useSourcererDataView(SourcererScopeName.detections); const getGlobalQuery = useCallback( (customFilters: Filter[]) => { - if (browserFields != null && indexPattern != null) { + if (browserFields != null && sourcererDataView) { return combineQueries({ config: getEsQueryConfig(uiSettings), dataProviders: [], - indexPattern, + indexPattern: sourcererDataView, browserFields, filters: [ ...(defaultFilters ?? []), @@ -120,10 +120,10 @@ export const GroupedSubLevelComponent: React.FC = ({ from, globalFilters, globalQuery, - indexPattern, parentGroupingFilter, to, uiSettings, + sourcererDataView, ] ); 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 3b637340e01e4..0ca0e99bb7fd0 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 @@ -129,11 +129,7 @@ export const AlertsTableComponent: FC = ({ enableIpDetailsFlyout: true, onRuleChange, }); - const { - browserFields, - indexPattern: indexPatterns, - sourcererDataView, - } = useSourcererDataView(sourcererScope); + const { browserFields, sourcererDataView } = useSourcererDataView(sourcererScope); const license = useLicense(); const getGlobalFiltersQuerySelector = useMemo( @@ -167,11 +163,11 @@ export const AlertsTableComponent: FC = ({ } = useShallowEqualSelector((state: State) => eventsViewerSelector(state, tableId)); const combinedQuery = useMemo(() => { - if (browserFields != null && indexPatterns != null) { + if (browserFields != null && sourcererDataView) { return combineQueries({ config: getEsQueryConfig(uiSettings), dataProviders: [], - indexPattern: indexPatterns, + indexPattern: sourcererDataView, browserFields, filters: [...allFilters], kqlQuery: globalQuery, @@ -179,7 +175,7 @@ export const AlertsTableComponent: FC = ({ }); } return null; - }, [browserFields, globalQuery, indexPatterns, uiSettings, allFilters]); + }, [browserFields, globalQuery, sourcererDataView, uiSettings, allFilters]); useInvalidFilterQuery({ id: tableId, @@ -297,13 +293,13 @@ export const AlertsTableComponent: FC = ({ onUpdate: onAlertTableUpdate, cellContext, onLoaded: onLoad, - runtimeMappings: sourcererDataView?.runtimeFieldMap as RunTimeMappings, toolbarVisibility, // if records are too less, we don't want table to be of fixed height. // it should shrink to the content height. // Height setting enables/disables virtualization depending on fixed/undefined height values respectively. height: count >= 20 ? `${DEFAULT_DATA_GRID_HEIGHT}px` : undefined, initialPageSize: 50, + runtimeMappings: sourcererDataView.runtimeFieldMap as RunTimeMappings, }), [ triggersActionsUi.alertsTableConfigurationRegistry, @@ -317,9 +313,9 @@ export const AlertsTableComponent: FC = ({ onAlertTableUpdate, cellContext, onLoad, - sourcererDataView?.runtimeFieldMap, toolbarVisibility, count, + sourcererDataView.runtimeFieldMap, ] ); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx index 7399926f7e9a2..0086f40ffa44b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/use_add_bulk_to_timeline.tsx @@ -67,7 +67,6 @@ export const useAddBulkToTimelineAction = ({ const { browserFields, dataViewId, - indexPattern, sourcererDataView, // important to get selectedPatterns from useSourcererDataView // in order to include the exclude filters in the search that are not stored in the timeline @@ -96,13 +95,13 @@ export const useAddBulkToTimelineAction = ({ return combineQueries({ config: esQueryConfig, dataProviders: [], - indexPattern, + indexPattern: sourcererDataView, filters: combinedFilters, kqlQuery: { query: '', language: 'kuery' }, browserFields, kqlMode: 'filter', }); - }, [esQueryConfig, indexPattern, combinedFilters, browserFields]); + }, [esQueryConfig, sourcererDataView, combinedFilters, browserFields]); const filterQuery = useMemo(() => { if (!combinedQuery) return ''; @@ -120,7 +119,7 @@ export const useAddBulkToTimelineAction = ({ sort: timelineQuerySortField, indexNames: selectedPatterns, filterQuery, - runtimeMappings: sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.runtimeFieldMap as RunTimeMappings, limit: Math.min(BULK_ADD_TO_TIMELINE_LIMIT, totalCount), timerangeKind: 'absolute', }); diff --git a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx index 82d6a4726dbc2..d9683d9de1b04 100644 --- a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx @@ -72,9 +72,9 @@ describe('DetectionEngineFilters', () => { }, timeRange: { from: 'now-15m', to: 'now' }, onInit: jest.fn(), - indexPattern: { + dataViewSpec: { title: 'mock-title', - fields: [], + fields: {}, }, }; diff --git a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx index 126c86055aa4c..6c60aec51382e 100644 --- a/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx @@ -13,21 +13,24 @@ import { ControlGroupRenderer } from '@kbn/controls-plugin/public'; import type { AlertFilterControlsProps } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { useHistory } from 'react-router-dom'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import { useKibana } from '../../../common/lib/kibana'; import { DEFAULT_DETECTION_PAGE_FILTERS } from '../../../../common/constants'; import { URL_PARAM_KEY } from '../../../common/hooks/use_url_state'; import { useSpaceId } from '../../../common/hooks/use_space_id'; -import type { SecuritySolutionDataViewBase } from '../../../common/types'; import { SECURITY_ALERT_DATA_VIEW } from '../../constants'; export type DetectionEngineFiltersProps = Pick< AlertFilterControlsProps, 'filters' | 'onFiltersChange' | 'query' | 'timeRange' | 'onInit' > & { - indexPattern?: SecuritySolutionDataViewBase; + dataViewSpec?: DataViewSpec; }; -export const DetectionEngineFilters = ({ indexPattern, ...props }: DetectionEngineFiltersProps) => { +export const DetectionEngineFilters = ({ + dataViewSpec: indexPattern, + ...props +}: DetectionEngineFiltersProps) => { const { http, notifications, dataViews } = useKibana().services; const spaceId = useSpaceId(); const history = useHistory(); diff --git a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.test.tsx b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.test.tsx index 926109d90558d..6057410e1615e 100644 --- a/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/configurations/security_solution_detections/render_cell_value.test.tsx @@ -27,6 +27,7 @@ jest.mock('../../../sourcerer/containers', () => ({ defaultIndex: 'defaultIndex', loading: false, indicesExist: true, + sourcererDataView: {}, }), })); jest.mock('../../../common/components/guided_onboarding_tour/tour_step'); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts index 7d44864681f0e..ce653c82d7831 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.test.ts @@ -112,6 +112,7 @@ describe('useRuleFromTimeline', () => { ...mockSourcererScope, dataViewId: 'custom-data-view-id', selectedPatterns: ['awesome-*'], + sourcererDataView: {}, }); }); diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.test.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.test.tsx index 7334be4e2a466..d2ca9bd93198a 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.test.tsx @@ -74,6 +74,7 @@ describe('usePersistentControls', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ ...sourcererDataView, selectedPatterns: ['myFakebeat-*'], + sourcererDataView: {}, }); }); diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.tsx index 1cce1c8a34594..dbd47281c5f2a 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_persistent_controls.tsx @@ -35,7 +35,7 @@ export const getPersistentControlsHook = (tableId: TableId) => { services: { telemetry }, } = useKibana(); - const { indexPattern } = useSourcererDataView(SourcererScopeName.detections); + const { sourcererDataView } = useSourcererDataView(SourcererScopeName.detections); const groupId = useMemo(() => groupIdSelector(), []); const { options } = useDeepEqualSelector((state) => groupId(state, tableId)) ?? { options: [], @@ -60,10 +60,14 @@ export const getPersistentControlsHook = (tableId: TableId) => { [dispatch, trackGroupChange] ); + const fields = useMemo(() => { + return Object.values(sourcererDataView.fields || {}); + }, [sourcererDataView.fields]); + const groupSelector = useGetGroupSelectorStateless({ groupingId: tableId, onGroupChange, - fields: indexPattern.fields, + fields, defaultGroupingOptions: options, maxGroupingLevels: 3, }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index 18efc5fcbad7f..4f8b8a391ea87 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -212,8 +212,11 @@ describe('DetectionEnginePageComponent', () => { ]); (useSourcererDataView as jest.Mock).mockReturnValue({ indicesExist: true, - indexPattern: {}, browserFields: mockBrowserFields, + sourcererDataView: { + fields: {}, + title: '', + }, }); jest .spyOn(alertFilterControlsPackage, 'AlertFilterControls') 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 7784fbb5760c3..01aab96481d5a 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 @@ -151,11 +151,9 @@ const DetectionEnginePageComponent: React.FC = () FilterGroupHandler | undefined >(); - const { - sourcererDataView, - loading: isLoadingIndexPattern, - indexPattern, - } = useSourcererDataView(SourcererScopeName.detections); + const { sourcererDataView, loading: isLoadingIndexPattern } = useSourcererDataView( + SourcererScopeName.detections + ); const { formatUrl } = useFormatUrl(SecurityPageName.rules); @@ -314,10 +312,10 @@ const DetectionEnginePageComponent: React.FC = () mode: 'absolute', }} onInit={setDetectionPageFilterHandler} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} /> ), - [from, indexPattern, onFilterControlsChange, query, to, topLevelFilters] + [from, sourcererDataView, onFilterControlsChange, query, to, topLevelFilters] ); const renderAlertTable = useCallback( @@ -419,7 +417,7 @@ const DetectionEnginePageComponent: React.FC = () alertsDefaultFilters={alertsDefaultFilters} isLoadingIndexPattern={isChartPanelLoading} query={query} - runtimeMappings={sourcererDataView?.runtimeFieldMap as RunTimeMappings} + runtimeMappings={sourcererDataView.runtimeFieldMap as RunTimeMappings} signalIndexName={signalIndexName} updateDateRangeCallback={updateDateRangeCallback} /> @@ -435,7 +433,7 @@ const DetectionEnginePageComponent: React.FC = () hasIndexWrite={hasIndexWrite ?? false} loading={isAlertTableLoading} renderChildComponent={renderAlertTable} - runtimeMappings={sourcererDataView?.runtimeFieldMap as RunTimeMappings} + runtimeMappings={sourcererDataView.runtimeFieldMap as RunTimeMappings} signalIndexName={signalIndexName} tableId={TableId.alertsOnAlertsPage} to={to} diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_preview_risk_scores.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_preview_risk_scores.ts index 837358aa96170..96a4453815125 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_preview_risk_scores.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_preview_risk_scores.ts @@ -9,38 +9,50 @@ import dateMath from '@kbn/datemath'; import type { RiskScoresPreviewRequest } from '../../../../common/api/entity_analytics/risk_engine/preview_route.gen'; import { useEntityAnalyticsRoutes } from '../api'; +export type UseRiskScorePreviewParams = Omit & { + data_view_id?: string; +}; + export const useRiskScorePreview = ({ data_view_id: dataViewId, range, filter, -}: RiskScoresPreviewRequest) => { +}: UseRiskScorePreviewParams) => { const { fetchRiskScorePreview } = useEntityAnalyticsRoutes(); - return useQuery(['POST', 'FETCH_PREVIEW_RISK_SCORE', range, filter], async ({ signal }) => { - const params: RiskScoresPreviewRequest = { data_view_id: dataViewId }; - if (range) { - const startTime = dateMath.parse(range.start)?.utc().toISOString(); - const endTime = dateMath - .parse(range.end, { - roundUp: true, - }) - ?.utc() - .toISOString(); - - if (startTime && endTime) { - params.range = { - start: startTime, - end: endTime, - }; + return useQuery( + ['POST', 'FETCH_PREVIEW_RISK_SCORE', range, filter], + async ({ signal }) => { + if (!dataViewId) { + return; + } + + const params: RiskScoresPreviewRequest = { data_view_id: dataViewId }; + if (range) { + const startTime = dateMath.parse(range.start)?.utc().toISOString(); + const endTime = dateMath + .parse(range.end, { + roundUp: true, + }) + ?.utc() + .toISOString(); + + if (startTime && endTime) { + params.range = { + start: startTime, + end: endTime, + }; + } } - } - if (filter) { - params.filter = filter; - } + if (filter) { + params.filter = filter; + } - const response = await fetchRiskScorePreview({ signal, params }); + const response = await fetchRiskScorePreview({ signal, params }); - return response; - }); + return response; + }, + { enabled: !!dataViewId } + ); }; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx index b8f7870e23b56..9693bf13589ad 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/risk_score_preview_section.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState, useCallback, useMemo } from 'react'; +import React, { useState, useCallback, useMemo, useEffect } from 'react'; import type { DataView } from '@kbn/data-views-plugin/public'; import { EuiAccordion, @@ -148,18 +148,21 @@ const RiskEnginePreview = () => { bool: { must: [], filter: [], should: [], must_not: [] }, }); + const [dataViewsArray, setDataViewsArray] = useState([]); + const { unifiedSearch: { ui: { SearchBar }, }, + dataViews, } = useKibana().services; const { addError } = useAppToasts(); - const { indexPattern } = useSourcererDataView(SourcererScopeName.detections); + const { sourcererDataView } = useSourcererDataView(SourcererScopeName.detections); const { data, isLoading, refetch, isError } = useRiskScorePreview({ - data_view_id: indexPattern.title, // TODO @nkhristinin verify this is correct + data_view_id: sourcererDataView.title, filter: filters, range: { start: dateRange.from, @@ -190,6 +193,10 @@ const RiskEnginePreview = () => { [addError, setDateRange, setFilters] ); + useEffect(() => { + dataViews.create(sourcererDataView).then((dataView) => setDataViewsArray([dataView])); + }, [dataViews, sourcererDataView]); + if (isError) { return ( { {i18n.PREVIEW_DESCRIPTION} - {indexPattern && ( - - )} + diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/top_risk_score_contributors_alerts/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/top_risk_score_contributors_alerts/index.tsx index c5c534a6bc370..e75c081ebc010 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/top_risk_score_contributors_alerts/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/top_risk_score_contributors_alerts/index.tsx @@ -122,7 +122,7 @@ export const TopRiskScoreContributorsAlerts: React.FC ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_over_time_area.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_over_time_area.test.ts index aa2a2cd77ef4b..0212363ea9a65 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_over_time_area.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_over_time_area.test.ts @@ -17,6 +17,7 @@ jest.mock('../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts index af5564e576de8..2a00cb1691970 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts @@ -18,6 +18,7 @@ jest.mock('../../sourcerer/containers', () => ({ selectedPatterns: ['auditbeat-mytest-*'], dataViewId: 'security-solution-my-test', indicesExist: true, + sourcererDataView: {}, }), })); diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx index 8d89e580a97e8..53f006bac1d49 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx @@ -11,6 +11,7 @@ import useResizeObserver from 'use-resize-observer/polyfilled'; import { createMockStore, + mockDataViewSpec, mockGlobalState, mockIndexPattern, TestProviders, @@ -109,7 +110,7 @@ describe('body', () => { setQuery={jest.fn()} hostDetailsPagePath={hostDetailsPagePath} indexNames={[]} - indexPattern={mockIndexPattern} + dataViewSpec={mockDataViewSpec} type={HostsType.details} hostDetailsFilter={mockHostDetailsPageFilters} filterQuery={filterQuery} @@ -128,34 +129,32 @@ describe('body', () => { startDate: '2020-07-07T08:20:18.966Z', type: 'details', indexPattern: { - fields: [ - { name: '@timestamp', searchable: true, type: 'date', aggregatable: true }, - { name: '@version', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.ephemeral_id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.hostname', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.id', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test1', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test2', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test3', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test4', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test5', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test6', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test7', searchable: true, type: 'string', aggregatable: true }, - { name: 'agent.test8', searchable: true, type: 'string', aggregatable: true }, - { name: 'host.name', searchable: true, type: 'string', aggregatable: true }, - { + fields: { + '@timestamp': { searchable: true, type: 'date', aggregatable: true }, + '@version': { searchable: true, type: 'string', aggregatable: true }, + 'agent.ephemeral_id': { searchable: true, type: 'string', aggregatable: true }, + 'agent.hostname': { searchable: true, type: 'string', aggregatable: true }, + 'agent.id': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test1': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test2': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test3': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test4': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test5': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test6': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test7': { searchable: true, type: 'string', aggregatable: true }, + 'agent.test8': { searchable: true, type: 'string', aggregatable: true }, + 'host.name': { searchable: true, type: 'string', aggregatable: true }, + 'nestedField.firstAttributes': { aggregatable: false, - name: 'nestedField.firstAttributes', searchable: true, type: 'string', }, - { + 'nestedField.secondAttributes': { aggregatable: false, - name: 'nestedField.secondAttributes', searchable: true, type: 'string', }, - ], + }, title: 'filebeat-*,auditbeat-*,packetbeat-*', }, hostName: 'host-1', diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx index 4a758dadc5cbd..2938a0a6288fb 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx @@ -29,7 +29,7 @@ export const HostDetailsTabs = React.memo( detailName, filterQuery, indexNames, - indexPattern, + dataViewSpec: indexPattern, hostDetailsPagePath, hostDetailsFilter, }) => { diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx index 6e5b69f408263..ed0e436c7e69a 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/index.tsx @@ -21,6 +21,7 @@ import { buildEsQuery } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { dataTableSelectors, tableDefaults, TableId } from '@kbn/securitysolution-data-table'; import type { NarrowDateRange } from '../../../../common/components/ml/types'; +import { dataViewSpecToViewBase } from '../../../../common/lib/kuery'; import { useCalculateEntityRiskScore } from '../../../../entity_analytics/api/hooks/use_calculate_entity_risk_score'; import { useAssetCriticalityData, @@ -128,8 +129,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta [dispatch] ); - const { indexPattern, indicesExist, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const [loading, { inspect, hostDetails: hostOverview, id, refetch }] = useHostDetails({ endDate: to, startDate: from, @@ -142,7 +142,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta try { return [ buildEsQuery( - indexPattern, + dataViewSpecToViewBase(sourcererDataView), [query], [...hostDetailsPageFilters, ...globalFilters], getEsQueryConfig(uiSettings) @@ -151,7 +151,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta } catch (e) { return [undefined, e]; } - }, [globalFilters, indexPattern, query, uiSettings, hostDetailsPageFilters]); + }, [sourcererDataView, query, hostDetailsPageFilters, globalFilters, uiSettings]); const stringifiedAdditionalFilters = JSON.stringify(rawFilteredQuery); useInvalidFilterQuery({ @@ -315,7 +315,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta setQuery={setQuery} filterQuery={stringifiedAdditionalFilters} hostDetailsPagePath={hostDetailsPagePath} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} /> diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/types.ts b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/types.ts index dc5b3baccdc5c..fe23a0485dac8 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/details/types.ts +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/details/types.ts @@ -5,7 +5,8 @@ * 2.0. */ -import type { DataViewBase, Filter } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import type { HostsTableType } from '../../store/model'; import type { HostsQueryProps } from '../types'; import type { NavTab } from '../../../../common/components/navigation/types'; @@ -40,6 +41,6 @@ export type HostDetailsTabsProps = HostBodyComponentDispatchProps & indexNames: string[]; hostDetailsFilter: Filter[]; filterQuery?: string; - indexPattern: DataViewBase; + dataViewSpec?: DataViewSpec; type: hostsModel.HostsType; }; diff --git a/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx b/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx index 17d5bdd3a82f2..59d57aeca5d14 100644 --- a/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx +++ b/x-pack/plugins/security_solution/public/explore/hosts/pages/hosts.tsx @@ -104,27 +104,26 @@ const HostsComponent = () => { return globalFilters; }, [globalFilters, severitySelection, tabName]); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const [globalFilterQuery, kqlError] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: globalFilters, }), - [globalFilters, indexPattern, uiSettings, query] + [globalFilters, sourcererDataView, uiSettings, query] ); const [tabsFilterQuery] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: tabsFilters, }), - [indexPattern, query, tabsFilters, uiSettings] + [sourcererDataView, query, tabsFilters, uiSettings] ); useInvalidFilterQuery({ diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.test.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.test.tsx index 19b3f653b8f14..9807f4b336b96 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.test.tsx @@ -127,6 +127,7 @@ describe('Network Details', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ indicesExist: false, indexPattern: {}, + sourcererDataView: {}, }); global.fetch = jest.fn().mockImplementationOnce(() => Promise.resolve({ @@ -147,6 +148,7 @@ describe('Network Details', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, + sourcererDataView: {}, }); (useParams as jest.Mock).mockReturnValue({ detailName: ip, @@ -167,6 +169,7 @@ describe('Network Details', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ indicesExist: true, indexPattern: {}, + sourcererDataView: {}, }); (useParams as jest.Mock).mockReturnValue({ detailName: ip, @@ -191,6 +194,7 @@ describe('Network Details', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ indicesExist: false, indexPattern: {}, + sourcererDataView: {}, }); (useParams as jest.Mock).mockReturnValue({ detailName: ip, diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx index adcf8a21ba47c..0eb3fb36638b8 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/details/index.tsx @@ -13,6 +13,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiSpacer } from '@elasti import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { buildEsQuery } from '@kbn/es-query'; +import { dataViewSpecToViewBase } from '../../../../common/lib/kuery'; import { AlertsByStatus } from '../../../../overview/components/detection_response/alerts_by_status'; import { useSignalIndex } from '../../../../detections/containers/detection_engine/alerts/use_signal_index'; import { InputsModelId } from '../../../../common/store/inputs/constants'; @@ -104,8 +105,7 @@ const NetworkDetailsComponent: React.FC = () => { dispatch(setNetworkDetailsTablesActivePageToZero()); }, [detailName, dispatch]); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const ip = decodeIpv6(detailName); const networkDetailsFilter = useMemo(() => getNetworkDetailsPageFilter(ip), [ip]); @@ -114,7 +114,7 @@ const NetworkDetailsComponent: React.FC = () => { try { return [ buildEsQuery( - indexPattern, + dataViewSpecToViewBase(sourcererDataView), [query], [...networkDetailsFilter, ...globalFilters], getEsQueryConfig(uiSettings) @@ -123,7 +123,7 @@ const NetworkDetailsComponent: React.FC = () => { } catch (e) { return [undefined, e]; } - }, [globalFilters, indexPattern, networkDetailsFilter, query, uiSettings]); + }, [globalFilters, networkDetailsFilter, query, sourcererDataView, uiSettings]); const additionalFilters = useMemo( () => (rawFilteredQuery ? [rawFilteredQuery] : []), @@ -166,6 +166,10 @@ const NetworkDetailsComponent: React.FC = () => { [detailName, flowTarget] ); + const indexPattern = useMemo(() => { + return dataViewSpecToViewBase(sourcererDataView); + }, [sourcererDataView]); + return (
{indicesExist ? ( diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx index ca9d7d4a7b085..6e49c65454239 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx @@ -5,12 +5,13 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { Routes, Route } from '@kbn/shared-ux-router'; import { EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { TableId } from '@kbn/securitysolution-data-table'; +import { dataViewSpecToViewBase } from '../../../../common/lib/kuery'; import { FlowTargetSourceDest } from '../../../../../common/search_strategy/security_solution/network'; import { @@ -30,7 +31,9 @@ import { NetworkRouteType } from './types'; import { NETWORK_PATH } from '../../../../../common/constants'; export const NetworkRoutes = React.memo( - ({ type, to, filterQuery, isInitializing, from, indexPattern, indexNames, setQuery }) => { + ({ type, to, filterQuery, isInitializing, from, dataViewSpec, indexNames, setQuery }) => { + const index = useMemo(() => dataViewSpecToViewBase(dataViewSpec), [dataViewSpec]); + const networkAnomaliesFilterQuery = { bool: { should: [ @@ -61,7 +64,7 @@ export const NetworkRoutes = React.memo( const tabProps = { ...commonProps, - indexPattern, + indexPattern: index, }; const anomaliesProps = { diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/types.ts b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/types.ts index 2ed0756634707..339ad2fc71acc 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/explore/network/pages/navigation/types.ts @@ -5,9 +5,10 @@ * 2.0. */ -import type { DataViewBase } from '@kbn/es-query'; import type { Optional } from 'utility-types'; +import type { DataViewBase } from '@kbn/es-query'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import type { ESTermQuery } from '../../../../../common/typed_json'; import type { NavTab } from '../../../../common/components/navigation/types'; @@ -45,7 +46,7 @@ export type HttpQueryTabBodyProps = QueryTabBodyProps; export type NetworkRoutesProps = GlobalTimeArgs & { type: networkModel.NetworkType; filterQuery?: string | ESTermQuery; - indexPattern: DataViewBase; + dataViewSpec: DataViewSpec; indexNames: string[]; }; diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/network.test.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/network.test.tsx index e868a38266f80..4f44045cbf6f3 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/network.test.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/network.test.tsx @@ -221,6 +221,7 @@ describe('Network page - rendering', () => { selectedPatterns: [], indicesExist: true, indexPattern: { fields: [], title: 'title' }, + sourcererDataView: {}, }); const myStore = createMockStore(); const wrapper = mount( diff --git a/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx b/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx index 00a88da0cfcf5..0732b31805609 100644 --- a/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/pages/network.tsx @@ -88,8 +88,7 @@ const NetworkComponent = React.memo( return globalFilters; }, [tabName, globalFilters]); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const onSkipFocusBeforeEventsTable = useCallback(() => { containerElement.current @@ -117,14 +116,14 @@ const NetworkComponent = React.memo( const [filterQuery, kqlError] = convertToBuildEsQuery({ config: getEsQueryConfig(kibana.services.uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: globalFilters, }); const [tabsFilterQuery] = convertToBuildEsQuery({ config: getEsQueryConfig(kibana.services.uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: tabsFilters, }); @@ -175,7 +174,7 @@ const NetworkComponent = React.memo( - {capabilitiesFetched && !isInitializing ? ( + {capabilitiesFetched && !isInitializing && sourcererDataView ? ( <> @@ -187,7 +186,7 @@ const NetworkComponent = React.memo( filterQuery={tabsFilterQuery} from={from} isInitializing={isInitializing} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} indexNames={selectedPatterns} setQuery={setQuery} type={networkModel.NetworkType.page} diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx index a53eaf43269bf..6ac48dd527904 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -20,6 +20,7 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { Filter } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query'; import { dataTableSelectors, TableId } from '@kbn/securitysolution-data-table'; +import { dataViewSpecToViewBase } from '../../../../common/lib/kuery'; import { useCalculateEntityRiskScore } from '../../../../entity_analytics/api/hooks/use_calculate_entity_risk_score'; import { useAssetCriticalityData, @@ -115,14 +116,13 @@ const UsersDetailsComponent: React.FC = ({ [detailName] ); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const [rawFilteredQuery, kqlError] = useMemo(() => { try { return [ buildEsQuery( - indexPattern, + dataViewSpecToViewBase(sourcererDataView), [query], [...usersDetailsPageFilters, ...globalFilters], getEsQueryConfig(uiSettings) @@ -131,7 +131,7 @@ const UsersDetailsComponent: React.FC = ({ } catch (e) { return [undefined, e]; } - }, [globalFilters, indexPattern, query, uiSettings, usersDetailsPageFilters]); + }, [globalFilters, sourcererDataView, query, uiSettings, usersDetailsPageFilters]); const stringifiedAdditionalFilters = JSON.stringify(rawFilteredQuery); useInvalidFilterQuery({ @@ -293,7 +293,7 @@ const UsersDetailsComponent: React.FC = ({ filterQuery={stringifiedAdditionalFilters} from={from} indexNames={selectedPatterns} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} isInitializing={isInitializing} userDetailFilter={usersDetailsPageFilters} setQuery={setQuery} diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/details/types.ts b/x-pack/plugins/security_solution/public/explore/users/pages/details/types.ts index 002d1339a1898..8b531af663990 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/details/types.ts +++ b/x-pack/plugins/security_solution/public/explore/users/pages/details/types.ts @@ -7,7 +7,8 @@ import type { ActionCreator } from 'typescript-fsa'; -import type { DataViewBase, Filter, Query } from '@kbn/es-query'; +import { type DataViewSpec } from '@kbn/data-plugin/common'; +import type { Filter, Query } from '@kbn/es-query'; import type { UsersQueryProps } from '../types'; import type { NavTab } from '../../../../common/components/navigation/types'; @@ -47,6 +48,6 @@ export type UsersDetailsTabsProps = UserBodyComponentDispatchProps & indexNames: string[]; userDetailFilter: Filter[]; filterQuery?: string; - indexPattern: DataViewBase; + dataViewSpec?: DataViewSpec; type: usersModel.UsersType; }; diff --git a/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx b/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx index 61cd8888bfb4c..767d009aff16c 100644 --- a/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx +++ b/x-pack/plugins/security_solution/public/explore/users/pages/users.tsx @@ -98,27 +98,26 @@ const UsersComponent = () => { return globalFilters; }, [severitySelection, tabName, globalFilters]); - const { indicesExist, indexPattern, selectedPatterns, sourcererDataView } = - useSourcererDataView(); + const { indicesExist, selectedPatterns, sourcererDataView } = useSourcererDataView(); const [globalFiltersQuery, kqlError] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: globalFilters, }), - [globalFilters, indexPattern, uiSettings, query] + [globalFilters, sourcererDataView, uiSettings, query] ); const [tabsFilterQuery] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters: tabsFilters, }), - [indexPattern, query, tabsFilters, uiSettings] + [sourcererDataView, query, tabsFilters, uiSettings] ); useInvalidFilterQuery({ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx index b6c5dc0078b02..53936a5ed2e99 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx @@ -65,7 +65,9 @@ jest.mock('../../../../helper_hooks', () => ({ })); jest.mock('../../../../sourcerer/containers', () => ({ - useSourcererDataView: jest.fn().mockReturnValue({ selectedPatterns: ['index'] }), + useSourcererDataView: jest + .fn() + .mockReturnValue({ selectedPatterns: ['index'], sourcererDataView: {} }), })); jest.mock('../../../../common/components/ml/anomaly/anomaly_table_provider', () => ({ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx index 23f6969c36778..895ff3d1b7697 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.test.tsx @@ -88,7 +88,9 @@ jest.mock('../../../../helper_hooks', () => ({ })); jest.mock('../../../../sourcerer/containers', () => ({ - useSourcererDataView: jest.fn().mockReturnValue({ selectedPatterns: ['index'] }), + useSourcererDataView: jest + .fn() + .mockReturnValue({ selectedPatterns: ['index'], sourcererDataView: {} }), })); jest.mock('../../../../common/components/ml/anomaly/anomaly_table_provider', () => ({ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/session_view.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/session_view.test.tsx index 6db3c4fb4a90d..ff3a834225d68 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/session_view.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/session_view.test.tsx @@ -88,8 +88,7 @@ describe('', () => { loading: false, indicesExist: true, selectedPatterns: ['index'], - indexPattern: { fields: [], title: '' }, - sourcererDataView: undefined, + sourcererDataView: {}, }); }); it('renders session view correctly', () => { diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx index a2c53afb8c3f3..d4150c01d06a6 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.test.tsx @@ -80,7 +80,9 @@ jest.mock('../../../../common/components/ml/hooks/use_ml_capabilities'); const mockUseMlUserPermissions = useMlCapabilities as jest.Mock; jest.mock('../../../../sourcerer/containers', () => ({ - useSourcererDataView: jest.fn().mockReturnValue({ selectedPatterns: ['index'] }), + useSourcererDataView: jest + .fn() + .mockReturnValue({ selectedPatterns: ['index'], sourcererDataView: {} }), })); jest.mock('../../../../common/components/ml/anomaly/anomaly_table_provider', () => ({ diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.test.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.test.ts index e40cd74709cfd..17e564a1eb8ab 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.test.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.test.ts @@ -50,8 +50,7 @@ describe('useThreatIntelligenceDetails', () => { loading: false, indicesExist: true, selectedPatterns: [], - indexPattern: { fields: [], title: '' }, - sourcererDataView: undefined, + sourcererDataView: {}, }); jest diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.ts index a7b8256b502f5..7826d98b65a3a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/hooks/use_threat_intelligence_details.ts @@ -71,7 +71,7 @@ export const useThreatIntelligenceDetails = (): ThreatIntelligenceDetailsResult const [isEventDataLoading, eventData] = useTimelineEventsDetails({ indexName, eventId, - runtimeMappings: sourcererDataView.sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.sourcererDataView.runtimeFieldMap as RunTimeMappings, skip: !eventId, }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.test.tsx index de1020bac4d00..efa56c9e65720 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.test.tsx @@ -53,6 +53,7 @@ describe('useEventDetails', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ browserFields: {}, indexPattern: {}, + sourcererDataView: {}, }); (useTimelineEventsDetails as jest.Mock).mockReturnValue([false, [], {}, {}, jest.fn()]); jest.mocked(useGetFieldsData).mockReturnValue({ getFieldsData: (field: string) => field }); @@ -63,7 +64,7 @@ describe('useEventDetails', () => { expect(hookResult.result.current.dataAsNestedObject).toEqual({}); expect(hookResult.result.current.dataFormattedForFieldBrowser).toEqual([]); expect(hookResult.result.current.getFieldsData('test')).toEqual('test'); - expect(hookResult.result.current.indexPattern).toEqual({}); + expect('indexPattern' in hookResult.result.current).toEqual(true); expect(hookResult.result.current.loading).toEqual(false); expect(hookResult.result.current.refetchFlyoutData()).toEqual(undefined); expect(hookResult.result.current.searchHit).toEqual({}); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.ts b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.ts index 40acb8690ce64..b880e372d5bed 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/shared/hooks/use_event_details.ts @@ -8,7 +8,7 @@ import type { BrowserFields, TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; import { SecurityPageName } from '@kbn/security-solution-navigation'; -import type { DataViewBase } from '@kbn/es-query'; +import { type DataViewSpec } from '@kbn/data-plugin/common'; import { DEFAULT_ALERTS_INDEX, DEFAULT_PREVIEW_INDEX } from '../../../../../common/constants'; import type { RunTimeMappings } from '../../../../../common/api/search_strategy'; import { useSpaceId } from '../../../../common/hooks/use_space_id'; @@ -66,7 +66,7 @@ export interface UseEventDetailsResult { /** * Index pattern for rule details */ - indexPattern: DataViewBase; + indexPattern?: DataViewSpec; /** * Whether the data is loading */ @@ -102,7 +102,7 @@ export const useEventDetails = ({ useTimelineEventsDetails({ indexName: eventIndex, eventId: eventId ?? '', - runtimeMappings: sourcererDataView?.sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.sourcererDataView.runtimeFieldMap as RunTimeMappings, skip: !eventId, }); const { getFieldsData } = useGetFieldsData({ fieldsData: searchHit?.fields }); @@ -112,7 +112,7 @@ export const useEventDetails = ({ dataAsNestedObject, dataFormattedForFieldBrowser, getFieldsData, - indexPattern: sourcererDataView.indexPattern, + indexPattern: sourcererDataView.sourcererDataView, loading, refetchFlyoutData, searchHit, diff --git a/x-pack/plugins/security_solution/public/flyout/network_details/components/network_details.tsx b/x-pack/plugins/security_solution/public/flyout/network_details/components/network_details.tsx index b36ef2fd55854..715f6dfa43589 100644 --- a/x-pack/plugins/security_solution/public/flyout/network_details/components/network_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/network_details/components/network_details.tsx @@ -76,10 +76,10 @@ export const NetworkDetails = ({ services: { uiSettings }, } = useKibana(); - const { indicesExist, indexPattern, selectedPatterns } = useSourcererDataView(); + const { indicesExist, sourcererDataView, selectedPatterns } = useSourcererDataView(); const [filterQuery, kqlError] = convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters, }); diff --git a/x-pack/plugins/security_solution/public/kubernetes/pages/index.tsx b/x-pack/plugins/security_solution/public/kubernetes/pages/index.tsx index c2d84e543dc0f..55c8a4472379b 100644 --- a/x-pack/plugins/security_solution/public/kubernetes/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/kubernetes/pages/index.tsx @@ -25,12 +25,13 @@ import { convertToBuildEsQuery } from '../../common/lib/kuery'; import { useInvalidFilterQuery } from '../../common/hooks/use_invalid_filter_query'; import { SessionsView } from '../../common/components/sessions_viewer'; import { kubernetesSessionsHeaders } from './constants'; +import { dataViewSpecToIndexPattern } from './utils/data_view_spec_to_index_pattern'; export const KubernetesContainer = React.memo(() => { const { kubernetesSecurity, uiSettings } = useKibana().services; const { globalFullScreen } = useGlobalFullScreen(); - const { indexPattern, sourcererDataView, dataViewId } = useSourcererDataView(); + const { sourcererDataView, dataViewId } = useSourcererDataView(); const { from, to } = useGlobalTime(); const getGlobalFiltersQuerySelector = useMemo( @@ -45,11 +46,11 @@ export const KubernetesContainer = React.memo(() => { () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec: sourcererDataView, queries: [query], filters, }), - [filters, indexPattern, uiSettings, query] + [filters, sourcererDataView, uiSettings, query] ); useInvalidFilterQuery({ @@ -84,7 +85,7 @@ export const KubernetesContainer = React.memo(() => { ), - indexPattern, + indexPattern: dataViewSpecToIndexPattern(sourcererDataView), globalFilter: { filterQuery, startDate: from, diff --git a/x-pack/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts b/x-pack/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts new file mode 100644 index 0000000000000..f4cb604ec3d8f --- /dev/null +++ b/x-pack/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts @@ -0,0 +1,15 @@ +/* + * 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 { DataViewSpec } from '@kbn/data-plugin/common'; +import type { IndexPattern } from '@kbn/kubernetes-security-plugin/public/types'; + +export const dataViewSpecToIndexPattern = ( + dataViewSpec?: DataViewSpec +): IndexPattern | undefined => { + return dataViewSpec as IndexPattern | undefined; +}; diff --git a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx index 6bd427d547c86..68149045e798c 100644 --- a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.test.tsx @@ -10,7 +10,7 @@ import React from 'react'; import type { OverviewHostProps } from '../overview_host'; import type { OverviewNetworkProps } from '../overview_network'; -import { mockIndexPattern, TestProviders } from '../../../common/mock'; +import { mockDataViewSpec, TestProviders } from '../../../common/mock'; import { EventCounts } from '.'; @@ -24,7 +24,7 @@ describe('EventCounts', () => { filters: [], from, indexNames: [], - indexPattern: mockIndexPattern, + dataViewSpec: mockDataViewSpec, setQuery: jest.fn(), to, query: { diff --git a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx index 34692b8cc12d3..3f20d3365537f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/event_counts/index.tsx @@ -8,8 +8,8 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useMemo } from 'react'; -import type { DataViewBase, Filter, Query } from '@kbn/es-query'; -import { getEsQueryConfig } from '@kbn/data-plugin/common'; +import type { Filter, Query } from '@kbn/es-query'; +import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; import { ID as OverviewHostQueryId } from '../../containers/overview_host'; import { OverviewHost } from '../overview_host'; import { OverviewNetwork } from '../overview_network'; @@ -26,7 +26,7 @@ import { SecurityPageName } from '../../../../common/constants'; interface Props extends Pick { filters: Filter[]; indexNames: string[]; - indexPattern: DataViewBase; + dataViewSpec?: DataViewSpec; query: Query; } @@ -34,7 +34,7 @@ const EventCountsComponent: React.FC = ({ filters, from, indexNames, - indexPattern, + dataViewSpec, query, setQuery, to, @@ -45,22 +45,22 @@ const EventCountsComponent: React.FC = ({ () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec, queries: [query], filters: [...filters, ...fieldNameExistsFilter(SecurityPageName.hosts)], }), - [filters, indexPattern, query, uiSettings] + [dataViewSpec, filters, query, uiSettings] ); const [networkFilterQuery] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - indexPattern, + dataViewSpec, queries: [query], filters: [...filters, ...sourceOrDestinationIpExistsFilter], }), - [filters, indexPattern, uiSettings, query] + [uiSettings, dataViewSpec, query, filters] ); useInvalidFilterQuery({ diff --git a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index eb551d4ba20aa..a30ae72ed9b00 100644 --- a/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -9,9 +9,10 @@ import { Position } from '@elastic/charts'; import numeral from '@elastic/numeral'; import React, { useEffect, useMemo, useCallback } from 'react'; -import type { DataViewBase, Filter, Query } from '@kbn/es-query'; +import type { Filter, Query } from '@kbn/es-query'; import styled from 'styled-components'; import { EuiButton } from '@elastic/eui'; +import type { DataViewSpec } from '@kbn/data-plugin/common'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { DEFAULT_NUMBER_FORMAT, APP_UI_ID } from '../../../../common/constants'; import { SHOWING, UNIT } from '../../../common/components/events_viewer/translations'; @@ -46,7 +47,7 @@ interface Props extends Pick = ({ filters, from, headerChildren, - indexPattern, + dataViewSpec, onlyField, paddingSize, query, @@ -132,13 +133,13 @@ const EventsByDatasetComponent: React.FC = ({ if (filterQueryFromProps == null) { return convertToBuildEsQuery({ config: getEsQueryConfig(kibana.services.uiSettings), - indexPattern, + dataViewSpec, queries: [query], filters, }); } return [filterQueryFromProps]; - }, [filterQueryFromProps, kibana, indexPattern, query, filters]); + }, [filterQueryFromProps, kibana.services.uiSettings, dataViewSpec, query, filters]); useInvalidFilterQuery({ id: uniqueQueryId, diff --git a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx index 0450b922acb44..e70a0f8e51577 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/overview.tsx @@ -50,8 +50,7 @@ const OverviewComponent = () => { const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); const { from, deleteQuery, setQuery, to } = useGlobalTime(); - const { indicesExist, sourcererDataView, indexPattern, selectedPatterns } = - useSourcererDataView(); + const { indicesExist, sourcererDataView, selectedPatterns } = useSourcererDataView(); const endpointMetadataIndex = useMemo(() => { return [ENDPOINT_METADATA_INDEX]; @@ -114,7 +113,7 @@ const OverviewComponent = () => { deleteQuery={deleteQuery} filters={filters} from={from} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} query={query} queryType="overview" setQuery={setQuery} @@ -127,7 +126,7 @@ const OverviewComponent = () => { filters={filters} from={from} indexNames={selectedPatterns} - indexPattern={indexPattern} + dataViewSpec={sourcererDataView} query={query} setQuery={setQuery} to={to} diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/alerts_sourcerer.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/alerts_sourcerer.test.tsx index 60bbe58824e41..619f7e91eae82 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/alerts_sourcerer.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/alerts_sourcerer.test.tsx @@ -72,6 +72,7 @@ describe('sourcerer on alerts page or rules details page', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ ...sourcererDataView, indicesExist: true, + sourcererDataView: {}, }); render( diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx index 8b45d96669793..ad5a939b69995 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/index.tsx @@ -152,8 +152,8 @@ export const Sourcerer = React.memo(({ scope: scopeId } const { indicesExist, loading, sourcererDataView } = useSourcererDataView(scopeId); const activePatterns = useMemo( - () => (sourcererDataView?.title || '')?.split(',').filter(Boolean) as string[], - [sourcererDataView?.title] + () => (sourcererDataView.title || '')?.split(',').filter(Boolean) as string[], + [sourcererDataView.title] ); const [missingPatterns, setMissingPatterns] = useState( diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/sourcerer_integration.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/sourcerer_integration.test.tsx index d43a3a47ed267..5f21a814da363 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/sourcerer_integration.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/sourcerer_integration.test.tsx @@ -72,6 +72,7 @@ const patternListNoSignals = sortWithExcludesAtEnd( const sourcererDataView = { indicesExist: true, loading: false, + sourcererDataView: {}, }; describe('Sourcerer integration tests', () => { diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/timeline_sourcerer.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/timeline_sourcerer.test.tsx index ff86241164631..35a26856f4930 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/timeline_sourcerer.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/timeline_sourcerer.test.tsx @@ -56,6 +56,7 @@ const { id } = mockGlobalState.sourcerer.defaultDataView; const sourcererDataView = { indicesExist: true, loading: false, + sourcererDataView: {}, }; describe('timeline sourcerer', () => { diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.test.ts b/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.test.ts index 18e34ba2067a1..87345f80ef701 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.test.ts +++ b/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.test.ts @@ -40,7 +40,7 @@ describe('useGetScopedSourcererDataView', () => { it('should return undefined when no spec is provided', () => { mockGetSourcererDataView.mockReturnValueOnce({ ...mockSourcererScope, - sourcererDataView: undefined, + sourcererDataView: {}, }); const { result } = renderHookCustom({ sourcererScope: SourcererScopeName.timeline }); expect(result.current).toBeUndefined(); @@ -48,7 +48,7 @@ describe('useGetScopedSourcererDataView', () => { it('should return undefined when no spec is provided and should update the return when spec is updated to correct value', () => { mockGetSourcererDataView.mockReturnValueOnce({ ...mockSourcererScope, - sourcererDataView: undefined, + sourcererDataView: {}, }); const { rerender, result } = renderHookCustom({ sourcererScope: SourcererScopeName.timeline }); expect(result.current).toBeUndefined(); diff --git a/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx b/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx index 869b9d68e27ac..52b5ca9717e8d 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx @@ -30,7 +30,7 @@ export const useGetScopedSourcererDataView = ({ const { sourcererDataView } = useSourcererDataView(sourcererScope); const dataView = useMemo(() => { - if (sourcererDataView) { + if (Object.keys(sourcererDataView).length) { return new DataView({ spec: sourcererDataView, fieldFormats }); } else { return undefined; diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx index 8b0150efa6126..e712e780636e4 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/hooks.test.tsx @@ -698,7 +698,6 @@ describe('Sourcerer Hooks', () => { '-filebeat-*', '-packetbeat-*', ]); - expect(result.current.indexPattern).toHaveProperty('getName'); }); }); @@ -710,7 +709,7 @@ describe('Sourcerer Hooks', () => { } ); - expect(result.current.sourcererDataView?.title).toBe( + expect(result.current.sourcererDataView.title).toBe( 'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,traces-apm*,winlogbeat-*,-*elastic-cloud-logs-*' ); @@ -727,8 +726,8 @@ describe('Sourcerer Hooks', () => { await rerender(); - expect(result.current.sourcererDataView?.title).toBe(testPatterns.join(',')); - expect(result.current.sourcererDataView?.name).toBe(testPatterns.join(',')); + expect(result.current.sourcererDataView.title).toBe(testPatterns.join(',')); + expect(result.current.sourcererDataView.name).toBe(testPatterns.join(',')); }); }); }); diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/index.tsx b/x-pack/plugins/security_solution/public/sourcerer/containers/index.tsx index 9765a26e60b0e..9643e9272f8be 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/index.tsx @@ -7,6 +7,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; +import type { FieldSpec } from '@kbn/data-plugin/common'; import { sourcererSelectors } from '../store'; import type { SelectedDataView, SourcererDataView, RunTimeMappings } from '../store/model'; import { SourcererScopeName } from '../store/model'; @@ -56,8 +57,7 @@ export const useSourcererDataView = ( id: fetchIndexReturn.dataView?.id ?? null, loading: indexPatternsLoading, patternList: fetchIndexReturn.indexes, - indexFields: fetchIndexReturn.indexPatterns - .fields as SelectedDataView['indexPattern']['fields'], + indexFields: fetchIndexReturn.indexPatterns.fields as FieldSpec[], fields: fetchIndexReturn.dataView?.fields, }), [fetchIndexReturn, indexPatternsLoading] diff --git a/x-pack/plugins/security_solution/public/sourcerer/containers/mocks.ts b/x-pack/plugins/security_solution/public/sourcerer/containers/mocks.ts index 283f41bc8be67..4d331ebab65ff 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/containers/mocks.ts +++ b/x-pack/plugins/security_solution/public/sourcerer/containers/mocks.ts @@ -38,19 +38,6 @@ export const mockSourcererScope: SelectedDataView = { }, }, }, - indexPattern: { - fields: [ - { - aggregatable: false, - esTypes: undefined, - name: '_id', - searchable: true, - subType: undefined, - type: 'string', - }, - ], - title: mockPatterns.join(), - }, sourcererDataView: mockGlobalState.sourcerer.defaultDataView, selectedPatterns: mockPatterns, indicesExist: true, diff --git a/x-pack/plugins/security_solution/public/sourcerer/store/model.ts b/x-pack/plugins/security_solution/public/sourcerer/store/model.ts index 3b3f8c56b261c..807c74a9c3f8f 100644 --- a/x-pack/plugins/security_solution/public/sourcerer/store/model.ts +++ b/x-pack/plugins/security_solution/public/sourcerer/store/model.ts @@ -9,7 +9,6 @@ import type { BrowserFields } from '@kbn/timelines-plugin/common'; import { EMPTY_BROWSER_FIELDS } from '@kbn/timelines-plugin/common'; import type { DataViewSpec } from '@kbn/data-views-plugin/public'; import type { RuntimeFieldSpec, RuntimePrimitiveTypes } from '@kbn/data-views-plugin/common'; -import type { SecuritySolutionDataViewBase } from '../../common/types'; /** Uniquely identifies a Sourcerer Scope */ export enum SourcererScopeName { @@ -88,11 +87,6 @@ export interface SelectedDataView { */ browserFields: BrowserFields; dataViewId: string | null; // null if legacy pre-8.0 timeline - /** - * @deprecated use sourcererDataView - * DataViewBase with enhanced index fields used in timelines - */ - indexPattern: SecuritySolutionDataViewBase; /** do the selected indices exist */ indicesExist: boolean; /** is an update being made to the data view */ @@ -103,7 +97,7 @@ export interface SelectedDataView { * Easier to add this additional data rather than * try to extend the SelectedDataView type from DataView. */ - sourcererDataView: DataViewSpec | undefined; + sourcererDataView: DataViewSpec; } /** diff --git a/x-pack/plugins/security_solution/public/timelines/components/modal/actions/open_timeline_button.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/modal/actions/open_timeline_button.test.tsx index e0a48cebf4209..ffa8f0b1bb0b0 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/modal/actions/open_timeline_button.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/modal/actions/open_timeline_button.test.tsx @@ -62,7 +62,11 @@ describe('OpenTimelineButton', () => { it('should open the modal after clicking on the button', async () => { (useParams as jest.Mock).mockReturnValue({ tabName: TimelineTypeEnum.template }); (useStartTransaction as jest.Mock).mockReturnValue({ startTransaction: jest.fn() }); - (useSourcererDataView as jest.Mock).mockReturnValue({ dataViewId: '', selectedPatterns: [] }); + (useSourcererDataView as jest.Mock).mockReturnValue({ + dataViewId: '', + selectedPatterns: [], + sourcererDataView: {}, + }); (useTimelineStatus as jest.Mock).mockReturnValue({ timelineStatus: 'active', templateTimelineFilter: null, diff --git a/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.test.tsx index 228c6bc70584c..25eef44d1469c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.test.tsx @@ -59,6 +59,7 @@ describe('TimelineModalHeader', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ browserFields: {}, indexPattern: { fields: [], title: '' }, + sourcererDataView: {}, }); const { getByTestId, getByText } = renderTimelineModalHeader(); @@ -78,6 +79,7 @@ describe('TimelineModalHeader', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ browserFields: {}, indexPattern: { fields: [], title: '' }, + sourcererDataView: {}, }); (useKibana as jest.Mock).mockReturnValue({ services: { @@ -107,6 +109,7 @@ describe('TimelineModalHeader', () => { (useSourcererDataView as jest.Mock).mockReturnValue({ browserFields: {}, indexPattern: { fields: [], title: '' }, + sourcererDataView: {}, }); const spy = jest.spyOn(timelineActions, 'showTimeline'); diff --git a/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.tsx index e30e0c2cf2a10..7eccb11a35312 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/modal/header/index.tsx @@ -70,7 +70,7 @@ interface FlyoutHeaderPanelProps { export const TimelineModalHeader = React.memo( ({ timelineId, openToggleRef }) => { const dispatch = useDispatch(); - const { browserFields, indexPattern } = useSourcererDataView(SourcererScopeName.timeline); + const { browserFields, sourcererDataView } = useSourcererDataView(SourcererScopeName.timeline); const { cases, uiSettings } = useKibana().services; const esQueryConfig = useMemo(() => getEsQueryConfig(uiSettings), [uiSettings]); const userCasesPermissions = cases.helpers.canUseCases([APP_ID]); @@ -88,13 +88,21 @@ export const TimelineModalHeader = React.memo( combineQueries({ config: esQueryConfig, dataProviders, - indexPattern, + indexPattern: sourcererDataView, browserFields, filters: filters ? filters : [], kqlQuery: kqlQueryObj, kqlMode, }), - [browserFields, dataProviders, esQueryConfig, filters, indexPattern, kqlMode, kqlQueryObj] + [ + browserFields, + dataProviders, + esQueryConfig, + filters, + kqlMode, + kqlQueryObj, + sourcererDataView, + ] ); const isInspectDisabled = !isDataInTimeline || combinedQueries?.filterQuery === undefined; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx index 47d79c1ba71c3..dce963737fb5a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx @@ -32,7 +32,7 @@ interface KpiExpandedProps { } export const TimelineKpisContainer = ({ timelineId }: KpiExpandedProps) => { - const { browserFields, indexPattern, selectedPatterns } = useSourcererDataView( + const { browserFields, sourcererDataView, selectedPatterns } = useSourcererDataView( SourcererScopeName.timeline ); @@ -82,13 +82,13 @@ export const TimelineKpisContainer = ({ timelineId }: KpiExpandedProps) => { combineQueries({ config: esQueryConfig, dataProviders, - indexPattern, + indexPattern: sourcererDataView, browserFields, filters: filters ? filters : [], kqlQuery, kqlMode, }), - [browserFields, dataProviders, esQueryConfig, filters, indexPattern, kqlMode, kqlQuery] + [browserFields, dataProviders, esQueryConfig, filters, sourcererDataView, kqlMode, kqlQuery] ); const isBlankTimeline: boolean = useMemo( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx index 59373b5d790f5..54b5a4a9aae2f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx @@ -79,7 +79,7 @@ export const EqlQueryBarTimeline = memo(({ timelineId }: { timelineId: string }) const { loading: indexPatternsLoading, - indexPattern, + sourcererDataView, selectedPatterns, } = useSourcererDataView(SourcererScopeName.timeline); @@ -123,27 +123,23 @@ export const EqlQueryBarTimeline = memo(({ timelineId }: { timelineId: string }) const prevEqlQuery = useRef(''); - const optionsData = useMemo( - () => - isEmpty(indexPattern.fields) - ? { - keywordFields: [], - dateFields: [], - nonDateFields: [], - } - : { - keywordFields: indexPattern.fields - .filter((f) => f.esTypes?.includes('keyword')) - .map((f) => ({ label: f.name })), - dateFields: indexPattern.fields - .filter((f) => f.type === 'date') - .map((f) => ({ label: f.name })), - nonDateFields: indexPattern.fields - .filter((f) => f.type !== 'date') - .map((f) => ({ label: f.name })), - }, - [indexPattern] - ); + const optionsData = useMemo(() => { + const fields = Object.values(sourcererDataView.fields || {}); + + return isEmpty(fields) + ? { + keywordFields: [], + dateFields: [], + nonDateFields: [], + } + : { + keywordFields: fields + .filter((f) => f.esTypes?.includes('keyword')) + .map((f) => ({ label: f.name })), + dateFields: fields.filter((f) => f.type === 'date').map((f) => ({ label: f.name })), + nonDateFields: fields.filter((f) => f.type !== 'date').map((f) => ({ label: f.name })), + }; + }, [sourcererDataView]); useEffect(() => { const { index: indexField } = getFields(); @@ -206,7 +202,7 @@ export const EqlQueryBarTimeline = memo(({ timelineId }: { timelineId: string }) idAria: 'timelineEqlQueryBar', isDisabled: indexPatternsLoading, isLoading: indexPatternsLoading, - indexPattern, + indexPattern: sourcererDataView, dataTestSubj: 'timelineEqlQueryBar', }} config={{ diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx index 3ac5ba0cb5ac8..1bb39aa4796d2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx @@ -17,7 +17,10 @@ import { InputsModelId } from '../../../../common/store/inputs/constants'; import { useSourcererDataView } from '../../../../sourcerer/containers'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; -import { convertKueryToElasticSearchQuery } from '../../../../common/lib/kuery'; +import { + convertKueryToElasticSearchQuery, + dataViewSpecToViewBase, +} from '../../../../common/lib/kuery'; import type { KqlMode } from '../../../store/model'; import { useSavedQueryServices } from '../../../../common/utils/saved_query_services'; import type { DispatchUpdateReduxTime } from '../../../../common/components/super_date_picker'; @@ -107,7 +110,7 @@ export const QueryBarTimeline = memo( const [dateRangeTo, setDateRangTo] = useState( toStr != null ? toStr : new Date(to).toISOString() ); - const { browserFields, indexPattern } = useSourcererDataView(SourcererScopeName.timeline); + const { browserFields, sourcererDataView } = useSourcererDataView(SourcererScopeName.timeline); const [savedQuery, setSavedQuery] = useState(undefined); const [filterQueryConverted, setFilterQueryConverted] = useState({ query: filterQuery != null ? filterQuery.expression : '', @@ -115,6 +118,11 @@ export const QueryBarTimeline = memo( }); const queryBarFilters = useMemo(() => getNonDropAreaFilters(filters), [filters]); + const indexPattern = useMemo( + () => dataViewSpecToViewBase(sourcererDataView), + [sourcererDataView] + ); + const [dataProvidersDsl, setDataProvidersDsl] = useState( convertKueryToElasticSearchQuery(buildGlobalQuery(dataProviders, browserFields), indexPattern) ); @@ -259,6 +267,10 @@ export const QueryBarTimeline = memo( [dataProvidersDsl, savedQueryId, savedQueryServices] ); + if (!indexPattern) { + return null; + } + return ( ( services: { data }, } = useKibana(); - const { indexPattern } = useSourcererDataView(SourcererScopeName.timeline); + const { sourcererDataView } = useSourcererDataView(SourcererScopeName.timeline); const getIsDataProviderVisible = useMemo( () => timelineSelectors.dataProviderVisibilitySelector(), @@ -86,25 +86,22 @@ const StatefulSearchOrFilterComponent = React.memo( useEffect(() => { let dv: DataView; - if (isDataView(indexPattern)) { - setDataView(indexPattern); - } else if (!filterQuery) { - const createDataView = async () => { - try { - dv = await data.dataViews.create({ title: indexPattern.title }); - setDataView(dv); - } catch (error) { - addError(error, { title: i18n.ERROR_PROCESSING_INDEX_PATTERNS }); - } - }; - createDataView(); - } + const createDataView = async () => { + try { + dv = await data.dataViews.create(sourcererDataView); + setDataView(dv); + } catch (error) { + addError(error, { title: i18n.ERROR_PROCESSING_INDEX_PATTERNS }); + } + }; + createDataView(); + return () => { if (dv?.id) { data.dataViews.clearInstanceCache(dv?.id); } }; - }, [data.dataViews, indexPattern, filterQuery, addError]); + }, [data.dataViews, filterQuery, addError, sourcererDataView]); const arrDataView = useMemo(() => (dataView != null ? [dataView] : []), [dataView]); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx index e41d9017d49be..f83d783667e4b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx @@ -110,7 +110,7 @@ export const EqlTabContentComponent: React.FC = ({ indexNames: selectedPatterns, language: 'eql', limit: sampleSize, - runtimeMappings: sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.runtimeFieldMap as RunTimeMappings, skip: !canQueryTimeline(), startDate: start, timerangeKind, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx index 959d6a3b52c3e..fb488d7c6d21b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx @@ -138,7 +138,7 @@ export const PinnedTabContentComponent: React.FC = ({ fields: timelineQueryFields, limit: itemsPerPage, filterQuery, - runtimeMappings: sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.runtimeFieldMap as RunTimeMappings, skip: filterQuery === '', startDate: '', sort: timelineQuerySortField, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx index 478c13db7de73..d12c213b7f3e2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx @@ -86,7 +86,6 @@ export const QueryTabContentComponent: React.FC = ({ browserFields, dataViewId, loading: loadingSourcerer, - indexPattern, // important to get selectedPatterns from useSourcererDataView // in order to include the exclude filters in the search that are not stored in the timeline selectedPatterns, @@ -119,13 +118,13 @@ export const QueryTabContentComponent: React.FC = ({ return combineQueries({ config: esQueryConfig, dataProviders, - indexPattern, + indexPattern: sourcererDataView, browserFields, filters, kqlQuery, kqlMode, }); - }, [esQueryConfig, dataProviders, indexPattern, browserFields, filters, kqlQuery, kqlMode]); + }, [esQueryConfig, dataProviders, sourcererDataView, browserFields, filters, kqlQuery, kqlMode]); useInvalidFilterQuery({ id: timelineId, @@ -177,7 +176,7 @@ export const QueryTabContentComponent: React.FC = ({ indexNames: selectedPatterns, language: kqlQuery.language, limit: sampleSize, - runtimeMappings: sourcererDataView?.runtimeFieldMap as RunTimeMappings, + runtimeMappings: sourcererDataView.runtimeFieldMap as RunTimeMappings, skip: !canQueryTimeline, sort: timelineQuerySortField, startDate: start, diff --git a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx index 43a0eab5a5d49..ee7dfc19d59f5 100644 --- a/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/pages/timelines_page.test.tsx @@ -39,6 +39,7 @@ describe('TimelinesPage', () => { it('should render landing page if no indicesExist', () => { (useSourcererDataView as unknown as jest.Mock).mockReturnValue({ indicesExist: false, + sourcererDataView: {}, }); (useKibana as unknown as jest.Mock).mockReturnValue({}); @@ -52,6 +53,7 @@ describe('TimelinesPage', () => { it('should show the correct elements if user has crud', () => { (useSourcererDataView as unknown as jest.Mock).mockReturnValue({ indicesExist: true, + sourcererDataView: {}, }); (useKibana as unknown as jest.Mock).mockReturnValue({ services: { diff --git a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts index b6526cf76d456..354dfb94322f4 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts +++ b/x-pack/plugins/threat_intelligence/public/modules/query_bar/hooks/use_filter_in_out.ts @@ -59,10 +59,10 @@ export const useFilterInOut = ({ key, value, filterType, - sourcererDataView?.id + sourcererDataView.id ); filterManager.setFilters(newFilters); - }, [filterManager, filterType, key, sourcererDataView?.id, value]); + }, [filterManager, filterType, key, sourcererDataView.id, value]); if (!fieldAndValueValid(key, value)) { return {} as unknown as UseFilterInValue; diff --git a/x-pack/plugins/threat_intelligence/public/types.ts b/x-pack/plugins/threat_intelligence/public/types.ts index d1fdb8831e518..13d6320ba10b5 100644 --- a/x-pack/plugins/threat_intelligence/public/types.ts +++ b/x-pack/plugins/threat_intelligence/public/types.ts @@ -65,7 +65,7 @@ export interface LicenseAware { export type BrowserFields = Readonly>>; export interface SelectedDataView { - sourcererDataView: DataViewSpec | undefined; + sourcererDataView: DataViewSpec; indexPattern: SecuritySolutionDataViewBase; browserFields: BrowserFields; selectedPatterns: string[];