From fb6fe9bd7264473cc93cf1a139704bf0225f80ca Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Thu, 4 Nov 2021 14:51:32 -0600 Subject: [PATCH 1/5] [Security Solution] [Sourcerer] [Feature Branch] Update to use Kibana Data Views (#114806) --- docs/api/dashboard-api.asciidoc | 2 +- docs/api/dashboard/export-dashboard.asciidoc | 2 +- docs/api/dashboard/import-dashboard.asciidoc | 2 +- .../src/field/index.tsx | 34 +- .../fetcher/index_patterns_fetcher.test.ts | 36 +- .../server/fetcher/index_patterns_fetcher.ts | 44 +- .../pages/alerts/alerts_table_t_grid.tsx | 2 + .../security_solution/common/constants.ts | 16 +- .../detection_engine/get_query_filter.ts | 4 +- .../search_strategy/index_fields/index.ts | 88 +-- .../timeline/events/last_event_time/index.ts | 1 + .../common/search_strategy/timeline/index.ts | 3 + .../security_solution/common/test/index.ts | 2 +- .../common/types/timeline/index.ts | 4 +- .../common/types/timeline/store.ts | 9 +- .../security_solution/cypress/cypress.json | 7 +- .../cypress/downloads/timelines_export.ndjson | 1 + .../integration/cases/privileges.spec.ts | 190 +----- .../data_sources/sourcerer.spec.ts | 43 +- .../detection_alerts/alerts_details.spec.ts | 2 + .../event_correlation_rule.spec.ts | 4 +- .../indicator_match_rule.spec.ts | 2 +- .../detection_rules/sorting.spec.ts | 3 +- .../ml/ml_conditional_links.spec.ts | 27 +- .../integration/timelines/creation.spec.ts | 2 +- .../cypress/integration/urls/state.spec.ts | 13 +- .../cypress/objects/timeline.ts | 2 + .../cypress/screens/sourcerer.ts | 6 +- .../security_solution/cypress/tasks/alerts.ts | 6 + .../security_solution/cypress/tasks/login.ts | 6 +- .../cypress/tasks/privileges.ts | 186 +++++ .../cypress/urls/navigation.ts | 1 + .../public/app/home/index.tsx | 5 +- .../template_wrapper/bottom_bar/index.tsx | 8 +- .../cases/components/case_view/helpers.ts | 4 +- .../cases/components/case_view/index.tsx | 9 +- .../drag_drop_context_wrapper.test.tsx.snap | 1 + .../alert_summary_view.test.tsx.snap | 4 +- .../event_details/table/field_name_cell.tsx | 4 +- .../table/field_value_cell.test.tsx | 4 + .../events_viewer/events_viewer.test.tsx | 16 +- .../events_viewer/events_viewer.tsx | 14 +- .../common/components/events_viewer/index.tsx | 15 +- .../components/exceptions/helpers.test.tsx | 6 +- .../common/components/exceptions/helpers.tsx | 8 +- .../hover_actions/actions/show_top_n.tsx | 5 +- .../use_hover_action_items.test.tsx | 2 +- .../hover_actions/use_hover_action_items.tsx | 4 +- .../common/components/navigation/helpers.ts | 4 +- .../navigation/tab_navigation/types.ts | 4 +- .../common/components/query_bar/index.tsx | 6 +- .../components/search_bar/index.test.tsx | 66 +- .../common/components/search_bar/index.tsx | 33 +- .../components/sourcerer/index.test.tsx | 494 +++++++++++--- .../common/components/sourcerer/index.tsx | 225 ++++--- .../common/components/sourcerer/selectors.tsx | 36 - .../components/sourcerer/translations.ts | 9 +- .../threat_match/entry_item.test.tsx | 14 +- .../components/threat_match/entry_item.tsx | 11 +- .../components/threat_match/helpers.test.tsx | 13 +- .../components/threat_match/helpers.tsx | 19 +- .../components/threat_match/index.test.tsx | 34 +- .../common/components/threat_match/index.tsx | 7 +- .../threat_match/list_item.test.tsx | 38 +- .../components/threat_match/list_item.tsx | 6 +- .../common/components/threat_match/types.ts | 6 +- .../public/common/components/top_n/index.tsx | 10 +- .../common/components/top_n/selectors.tsx | 23 +- .../public/common/components/top_n/top_n.tsx | 15 +- .../common/components/url_state/helpers.ts | 15 +- .../url_state/initialize_redux_by_url.tsx | 9 +- .../url_state/normalize_time_range.test.ts | 26 +- .../components/url_state/test_dependencies.ts | 2 - .../common/components/url_state/types.ts | 18 +- .../containers/kuery_autocompletion/index.tsx | 85 --- .../common/containers/source/index.test.tsx | 109 +++ .../public/common/containers/source/index.tsx | 126 +--- .../public/common/containers/source/mock.ts | 20 +- .../containers/source/use_data_view.tsx | 120 ++++ .../public/common/containers/sourcerer/api.ts | 32 + .../containers/sourcerer/index.test.tsx | 248 +++++-- .../common/containers/sourcerer/index.tsx | 253 +++++-- .../sourcerer/use_signal_helpers.test.tsx | 95 +++ .../sourcerer/use_signal_helpers.tsx | 92 +++ .../public/common/lib/keury/index.ts | 11 +- .../public/common/mock/global_state.ts | 80 ++- .../public/common/mock/index_pattern.ts | 4 +- .../public/common/mock/timeline_results.ts | 2 + .../public/common/store/reducer.test.ts | 49 +- .../public/common/store/reducer.ts | 54 +- .../public/common/store/sourcerer/actions.ts | 42 +- .../common/store/sourcerer/helpers.test.ts | 278 ++++++-- .../public/common/store/sourcerer/helpers.ts | 144 +++- .../public/common/store/sourcerer/model.ts | 138 ++-- .../public/common/store/sourcerer/reducer.ts | 124 ++-- .../common/store/sourcerer/selectors.test.ts | 75 --- .../common/store/sourcerer/selectors.ts | 118 ++-- .../security_solution/public/common/types.ts | 10 + .../use_show_pages_with_empty_view.test.tsx | 2 +- .../use_show_pages_with_empty_view.tsx | 4 +- .../components/alerts_table/actions.test.tsx | 1 + .../components/alerts_table/index.tsx | 4 +- .../rules/autocomplete_field/index.tsx | 6 +- .../rules/description_step/helpers.test.tsx | 4 +- .../rules/description_step/index.tsx | 14 +- .../rules/description_step/types.ts | 10 +- .../components/rules/query_bar/index.tsx | 12 +- .../rules/risk_score_mapping/index.tsx | 14 +- .../rules/severity_mapping/index.tsx | 14 +- .../rules/step_define_rule/index.tsx | 5 +- .../rules/step_define_rule/translations.tsx | 14 - .../rules/threatmatch_input/index.tsx | 7 +- .../detection_engine.test.tsx | 4 +- .../detection_engine/detection_engine.tsx | 24 +- .../rules/details/index.test.tsx | 4 +- .../detection_engine/rules/details/index.tsx | 350 +++++----- .../public/hosts/pages/details/index.tsx | 4 +- .../public/hosts/pages/details/types.ts | 4 +- .../public/hosts/pages/hosts.test.tsx | 12 +- .../public/hosts/pages/hosts.tsx | 4 +- .../pages/endpoint_hosts/store/action.ts | 4 +- .../pages/endpoint_hosts/store/middleware.ts | 8 +- .../management/pages/endpoint_hosts/types.ts | 4 +- .../embeddables/embedded_map.test.tsx | 4 +- .../components/embeddables/embedded_map.tsx | 19 +- .../components/embeddables/selector.test.tsx | 26 - .../components/embeddables/selector.tsx | 36 - .../network_top_countries_table/columns.tsx | 7 +- .../network_top_countries_table/index.tsx | 4 +- .../network/pages/details/index.test.tsx | 6 +- .../public/network/pages/details/index.tsx | 4 +- .../public/network/pages/details/types.ts | 4 +- .../public/network/pages/navigation/types.ts | 6 +- .../public/network/pages/network.test.tsx | 10 +- .../public/network/pages/network.tsx | 4 +- .../components/alerts_by_category/index.tsx | 10 +- .../components/event_counts/index.tsx | 10 +- .../components/events_by_dataset/index.tsx | 10 +- .../public/overview/pages/overview.test.tsx | 18 +- .../public/overview/pages/overview.tsx | 4 +- .../public/overview/pages/summary.tsx | 90 --- .../security_solution/public/plugin.tsx | 59 +- .../components/flyout/header/index.test.tsx | 6 +- .../components/flyout/header/index.tsx | 6 +- .../components/graph_overlay/index.test.tsx | 7 +- .../components/graph_overlay/index.tsx | 14 +- .../components/open_timeline/helpers.test.ts | 637 +++--------------- .../components/open_timeline/helpers.ts | 3 +- .../components/open_timeline/index.tsx | 16 +- .../open_timeline/note_previews/index.tsx | 13 +- .../__snapshots__/index.test.tsx.snap | 6 + .../side_panel/event_details/index.tsx | 4 + .../expandable_host.test.tsx.snap | 10 +- .../host_details/expandable_host.test.tsx | 30 +- .../host_details/expandable_host.tsx | 20 +- .../components/side_panel/index.test.tsx | 1 + .../timelines/components/side_panel/index.tsx | 4 + .../network_details/expandable_network.tsx | 4 +- .../__snapshots__/index.test.tsx.snap | 1 + .../body/column_headers/helpers.test.ts | 1 + .../suricata_row_renderer.test.tsx.snap | 1 + .../__snapshots__/zeek_details.test.tsx.snap | 1 + .../zeek_row_renderer.test.tsx.snap | 1 + .../timeline/data_providers/index.test.tsx | 8 - .../timeline/data_providers/index.tsx | 4 +- .../timeline/eql_tab_content/index.test.tsx | 6 +- .../timeline/eql_tab_content/index.tsx | 24 +- .../timelines/components/timeline/helpers.tsx | 5 +- .../components/timeline/index.test.tsx | 2 +- .../timelines/components/timeline/index.tsx | 6 +- .../timeline/notes_tab_content/index.tsx | 17 +- .../pinned_tab_content/index.test.tsx | 4 +- .../timeline/pinned_tab_content/index.tsx | 18 +- .../properties/use_create_timeline.test.tsx | 9 +- .../properties/use_create_timeline.tsx | 25 +- .../timeline/query_bar/eql/index.tsx | 4 +- .../components/timeline/query_bar/index.tsx | 5 +- .../timeline/query_tab_content/index.test.tsx | 6 +- .../timeline/query_tab_content/index.tsx | 25 +- .../search_or_filter/pick_events.test.tsx | 100 ++- .../timeline/search_or_filter/pick_events.tsx | 288 ++++---- .../timeline/search_or_filter/selectors.tsx | 44 -- .../timelines/containers/details/index.tsx | 6 +- .../timelines/containers/index.test.tsx | 1 + .../public/timelines/containers/index.tsx | 13 +- .../timelines/containers/kpis/index.tsx | 8 +- .../timelines/pages/timelines_page.test.tsx | 2 +- .../public/timelines/pages/timelines_page.tsx | 4 +- .../timelines/store/timeline/actions.ts | 5 +- .../timelines/store/timeline/defaults.ts | 1 + .../timelines/store/timeline/epic.test.ts | 2 + .../public/timelines/store/timeline/epic.ts | 5 +- .../public/timelines/store/timeline/model.ts | 1 + .../timelines/store/timeline/reducer.test.ts | 4 + .../timelines/store/timeline/reducer.ts | 5 +- .../public/ueba/pages/details/index.tsx | 4 +- .../public/ueba/pages/details/types.ts | 4 +- .../public/ueba/pages/ueba.tsx | 4 +- .../security_solution/server/client/client.ts | 5 +- .../rules/prepackaged_timelines/index.ndjson | 2 +- .../rules/prepackaged_timelines/threat.json | 2 +- .../detections_admin/detections_role.json | 2 + .../roles_users/hunter/detections_role.json | 2 + .../scripts/roles_users/index.ts | 5 + .../platform_engineer/detections_role.json | 2 + .../roles_users/reader/detections_role.json | 2 + .../rule_author/detections_role.json | 2 + .../soc_manager/detections_role.json | 2 + .../t1_analyst/detections_role.json | 2 + .../t2_analyst/detections_role.json | 2 + .../server/lib/sourcerer/routes/helpers.ts | 26 + .../server/lib/sourcerer/routes/index.test.ts | 169 +++++ .../server/lib/sourcerer/routes/index.ts | 119 ++++ .../server/lib/sourcerer/routes/schema.ts | 12 + .../timeline/__mocks__/create_timelines.ts | 2 + .../server/lib/timeline/constants.ts | 5 + .../server/lib/timeline/routes/README.md | 4 + .../create_timelines/helpers.test.ts | 10 +- .../convert_saved_object_to_savedtimeline.ts | 7 +- .../saved_object/timelines/field_migrator.ts | 5 +- .../saved_object/timelines/index.test.ts | 52 ++ .../timelines/pick_saved_timeline.test.ts | 1 + .../timelines/create_timelines_schema.ts | 2 + .../plugins/security_solution/server/mocks.ts | 1 + .../security_solution/server/plugin.ts | 3 +- .../security_solution/server/routes/index.ts | 10 +- x-pack/plugins/timelines/common/constants.ts | 2 + x-pack/plugins/timelines/common/index.ts | 2 + .../search_strategy/index_fields/index.ts | 44 +- .../timeline/events/all/index.ts | 8 +- .../timeline/events/last_event_time/index.ts | 3 +- .../common/search_strategy/timeline/index.ts | 2 + .../public/components/t_grid/helpers.tsx | 5 +- .../components/t_grid/integrated/index.tsx | 15 +- .../components/t_grid/standalone/index.tsx | 4 + .../public/components/utils/keury/index.ts | 11 +- .../timelines/public/container/index.tsx | 16 +- .../public/container/source/index.tsx | 8 +- .../timelines/public/mock/browser_fields.ts | 10 + .../timelines/public/mock/global_state.ts | 1 + .../timelines/public/mock/index_pattern.ts | 36 +- .../public/mock/mock_timeline_data.ts | 1 + .../plugins/timelines/public/mock/t_grid.tsx | 3 +- .../timelines/public/store/t_grid/defaults.ts | 1 + .../timelines/public/store/t_grid/model.ts | 4 + x-pack/plugins/timelines/server/plugin.ts | 2 +- .../index_fields/index.test.ts | 82 ++- .../search_strategy/index_fields/index.ts | 163 +++-- .../timeline/eql/helpers.test.ts | 85 +-- .../events/all/query.events_all.dsl.ts | 4 +- .../timeline/factory/events/details/index.ts | 18 +- .../details/query.events_details.dsl.test.ts | 8 +- .../details/query.events_details.dsl.ts | 22 +- .../server/search_strategy/timeline/index.ts | 1 - .../translations/translations/ja-JP.json | 11 - .../translations/translations/zh-CN.json | 11 - .../security_solution/timeline_migrations.ts | 1 - .../applications/timelines_test/index.tsx | 1 + 258 files changed, 4519 insertions(+), 3154 deletions(-) create mode 100644 x-pack/plugins/security_solution/cypress/downloads/timelines_export.ndjson create mode 100644 x-pack/plugins/security_solution/cypress/tasks/privileges.ts delete mode 100644 x-pack/plugins/security_solution/public/common/components/sourcerer/selectors.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/containers/kuery_autocompletion/index.tsx create mode 100644 x-pack/plugins/security_solution/public/common/containers/source/use_data_view.tsx create mode 100644 x-pack/plugins/security_solution/public/common/containers/sourcerer/api.ts create mode 100644 x-pack/plugins/security_solution/public/common/containers/sourcerer/use_signal_helpers.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/containers/sourcerer/use_signal_helpers.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/store/sourcerer/selectors.test.ts delete mode 100644 x-pack/plugins/security_solution/public/network/components/embeddables/selector.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/network/components/embeddables/selector.tsx delete mode 100644 x-pack/plugins/security_solution/public/overview/pages/summary.tsx delete mode 100644 x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/selectors.tsx create mode 100644 x-pack/plugins/security_solution/server/lib/sourcerer/routes/helpers.ts create mode 100644 x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/sourcerer/routes/index.ts create mode 100644 x-pack/plugins/security_solution/server/lib/sourcerer/routes/schema.ts diff --git a/docs/api/dashboard-api.asciidoc b/docs/api/dashboard-api.asciidoc index 94511c3154fe0..e6f54dd9156ec 100644 --- a/docs/api/dashboard-api.asciidoc +++ b/docs/api/dashboard-api.asciidoc @@ -1,7 +1,7 @@ [[dashboard-api]] == Import and export dashboard APIs -deprecated::[7.15.0,These experimental APIs have been deprecated in favor of <> and <>.] +deprecated::[7.15.0,Both of these APIs have been deprecated in favor of <> and <>.] Import and export dashboards with the corresponding saved objects, such as visualizations, saved searches, and index patterns. diff --git a/docs/api/dashboard/export-dashboard.asciidoc b/docs/api/dashboard/export-dashboard.asciidoc index 098ec976569bd..3a20eff0a54d2 100644 --- a/docs/api/dashboard/export-dashboard.asciidoc +++ b/docs/api/dashboard/export-dashboard.asciidoc @@ -6,7 +6,7 @@ deprecated::[7.15.0,Use <> instead.] -experimental[] Export dashboards and corresponding saved objects. +Export dashboards and corresponding saved objects. [[dashboard-api-export-request]] ==== Request diff --git a/docs/api/dashboard/import-dashboard.asciidoc b/docs/api/dashboard/import-dashboard.asciidoc index 41eb47500c8d7..e4817d6cb7ee9 100644 --- a/docs/api/dashboard/import-dashboard.asciidoc +++ b/docs/api/dashboard/import-dashboard.asciidoc @@ -6,7 +6,7 @@ deprecated::[7.15.0,Use <> instead.] -experimental[] Import dashboards and corresponding saved objects. +Import dashboards and corresponding saved objects. [[dashboard-api-import-request]] ==== Request diff --git a/packages/kbn-securitysolution-autocomplete/src/field/index.tsx b/packages/kbn-securitysolution-autocomplete/src/field/index.tsx index 69408e919bb1e..a89e0a096b673 100644 --- a/packages/kbn-securitysolution-autocomplete/src/field/index.tsx +++ b/packages/kbn-securitysolution-autocomplete/src/field/index.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useMemo, useState } from 'react'; import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { IndexPatternBase, IndexPatternFieldBase } from '@kbn/es-query'; +import { DataViewBase, DataViewFieldBase } from '@kbn/es-query'; import { getGenericComboBoxProps, @@ -20,14 +20,14 @@ const AS_PLAIN_TEXT = { asPlainText: true }; interface OperatorProps { fieldInputWidth?: number; fieldTypeFilter?: string[]; - indexPattern: IndexPatternBase | undefined; + indexPattern: DataViewBase | undefined; isClearable: boolean; isDisabled: boolean; isLoading: boolean; isRequired?: boolean; - onChange: (a: IndexPatternFieldBase[]) => void; + onChange: (a: DataViewFieldBase[]) => void; placeholder: string; - selectedField: IndexPatternFieldBase | undefined; + selectedField: DataViewFieldBase | undefined; } export const FieldComponent: React.FC = ({ @@ -56,7 +56,7 @@ export const FieldComponent: React.FC = ({ const handleValuesChange = useCallback( (newOptions: EuiComboBoxOptionOption[]): void => { - const newValues: IndexPatternFieldBase[] = newOptions.map( + const newValues: DataViewFieldBase[] = newOptions.map( ({ label }) => availableFields[labels.indexOf(label)] ); onChange(newValues); @@ -94,13 +94,13 @@ export const FieldComponent: React.FC = ({ FieldComponent.displayName = 'Field'; interface ComboBoxFields { - availableFields: IndexPatternFieldBase[]; - selectedFields: IndexPatternFieldBase[]; + availableFields: DataViewFieldBase[]; + selectedFields: DataViewFieldBase[]; } const getComboBoxFields = ( - indexPattern: IndexPatternBase | undefined, - selectedField: IndexPatternFieldBase | undefined, + indexPattern: DataViewBase | undefined, + selectedField: DataViewFieldBase | undefined, fieldTypeFilter: string[] ): ComboBoxFields => { const existingFields = getExistingFields(indexPattern); @@ -113,29 +113,27 @@ const getComboBoxFields = ( const getComboBoxProps = (fields: ComboBoxFields): GetGenericComboBoxPropsReturn => { const { availableFields, selectedFields } = fields; - return getGenericComboBoxProps({ + return getGenericComboBoxProps({ getLabel: (field) => field.name, options: availableFields, selectedOptions: selectedFields, }); }; -const getExistingFields = (indexPattern: IndexPatternBase | undefined): IndexPatternFieldBase[] => { +const getExistingFields = (indexPattern: DataViewBase | undefined): DataViewFieldBase[] => { return indexPattern != null ? indexPattern.fields : []; }; -const getSelectedFields = ( - selectedField: IndexPatternFieldBase | undefined -): IndexPatternFieldBase[] => { +const getSelectedFields = (selectedField: DataViewFieldBase | undefined): DataViewFieldBase[] => { return selectedField ? [selectedField] : []; }; const getAvailableFields = ( - existingFields: IndexPatternFieldBase[], - selectedFields: IndexPatternFieldBase[], + existingFields: DataViewFieldBase[], + selectedFields: DataViewFieldBase[], fieldTypeFilter: string[] -): IndexPatternFieldBase[] => { - const fieldsByName = new Map(); +): DataViewFieldBase[] => { + const fieldsByName = new Map(); existingFields.forEach((f) => fieldsByName.set(f.name, f)); selectedFields.forEach((f) => fieldsByName.set(f.name, f)); diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts index a65d4d551cf7c..1a8b705480258 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.test.ts @@ -5,7 +5,6 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { IndexPatternsFetcher } from '.'; import { ElasticsearchClient } from 'kibana/server'; import * as indexNotFoundException from './index_not_found_exception.json'; @@ -15,36 +14,36 @@ describe('Index Pattern Fetcher - server', () => { let esClient: ElasticsearchClient; const emptyResponse = { body: { - count: 0, + indices: [], }, }; const response = { body: { - count: 1115, + indices: ['b'], + fields: [{ name: 'foo' }, { name: 'bar' }, { name: 'baz' }], }, }; const patternList = ['a', 'b', 'c']; beforeEach(() => { + jest.clearAllMocks(); esClient = { - count: jest.fn().mockResolvedValueOnce(emptyResponse).mockResolvedValue(response), + fieldCaps: jest.fn().mockResolvedValueOnce(emptyResponse).mockResolvedValue(response), } as unknown as ElasticsearchClient; indexPatterns = new IndexPatternsFetcher(esClient); }); - it('Removes pattern without matching indices', async () => { const result = await indexPatterns.validatePatternListActive(patternList); expect(result).toEqual(['b', 'c']); }); - it('Returns all patterns when all match indices', async () => { esClient = { - count: jest.fn().mockResolvedValue(response), + fieldCaps: jest.fn().mockResolvedValue(response), } as unknown as ElasticsearchClient; indexPatterns = new IndexPatternsFetcher(esClient); const result = await indexPatterns.validatePatternListActive(patternList); expect(result).toEqual(patternList); }); - it('Removes pattern when "index_not_found_exception" error is thrown', async () => { + it('Removes pattern when error is thrown', async () => { class ServerError extends Error { public body?: Record; constructor( @@ -56,9 +55,8 @@ describe('Index Pattern Fetcher - server', () => { this.body = errBody; } } - esClient = { - count: jest + fieldCaps: jest .fn() .mockResolvedValueOnce(response) .mockRejectedValue( @@ -69,4 +67,22 @@ describe('Index Pattern Fetcher - server', () => { const result = await indexPatterns.validatePatternListActive(patternList); expect(result).toEqual([patternList[0]]); }); + it('When allowNoIndices is false, run validatePatternListActive', async () => { + const fieldCapsMock = jest.fn(); + esClient = { + fieldCaps: fieldCapsMock.mockResolvedValue(response), + } as unknown as ElasticsearchClient; + indexPatterns = new IndexPatternsFetcher(esClient); + await indexPatterns.getFieldsForWildcard({ pattern: patternList }); + expect(fieldCapsMock.mock.calls).toHaveLength(4); + }); + it('When allowNoIndices is true, do not run validatePatternListActive', async () => { + const fieldCapsMock = jest.fn(); + esClient = { + fieldCaps: fieldCapsMock.mockResolvedValue(response), + } as unknown as ElasticsearchClient; + indexPatterns = new IndexPatternsFetcher(esClient, true); + await indexPatterns.getFieldsForWildcard({ pattern: patternList }); + expect(fieldCapsMock.mock.calls).toHaveLength(1); + }); }); diff --git a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts index 7dae85c920ebf..c054d547e956f 100644 --- a/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts +++ b/src/plugins/data_views/server/fetcher/index_patterns_fetcher.ts @@ -36,12 +36,10 @@ interface FieldSubType { export class IndexPatternsFetcher { private elasticsearchClient: ElasticsearchClient; private allowNoIndices: boolean; - constructor(elasticsearchClient: ElasticsearchClient, allowNoIndices: boolean = false) { this.elasticsearchClient = elasticsearchClient; this.allowNoIndices = allowNoIndices; } - /** * Get a list of field objects for an index pattern that may contain wildcards * @@ -60,23 +58,22 @@ export class IndexPatternsFetcher { }): Promise { const { pattern, metaFields, fieldCapsOptions, type, rollupIndex } = options; const patternList = Array.isArray(pattern) ? pattern : pattern.split(','); + const allowNoIndices = fieldCapsOptions + ? fieldCapsOptions.allow_no_indices + : this.allowNoIndices; let patternListActive: string[] = patternList; // if only one pattern, don't bother with validation. We let getFieldCapabilities fail if the single pattern is bad regardless - if (patternList.length > 1) { + if (patternList.length > 1 && !allowNoIndices) { patternListActive = await this.validatePatternListActive(patternList); } const fieldCapsResponse = await getFieldCapabilities( this.elasticsearchClient, - // if none of the patterns are active, pass the original list to get an error - patternListActive.length > 0 ? patternListActive : patternList, + patternListActive, metaFields, { - allow_no_indices: fieldCapsOptions - ? fieldCapsOptions.allow_no_indices - : this.allowNoIndices, + allow_no_indices: allowNoIndices, } ); - if (type === 'rollup' && rollupIndex) { const rollupFields: FieldDescriptor[] = []; const rollupIndexCapabilities = getCapabilitiesForRollupIndices( @@ -87,13 +84,11 @@ export class IndexPatternsFetcher { ).body )[rollupIndex].aggs; const fieldCapsResponseObj = keyBy(fieldCapsResponse, 'name'); - // Keep meta fields metaFields!.forEach( (field: string) => fieldCapsResponseObj[field] && rollupFields.push(fieldCapsResponseObj[field]) ); - return mergeCapabilitiesWithFields( rollupIndexCapabilities, fieldCapsResponseObj, @@ -137,23 +132,20 @@ export class IndexPatternsFetcher { async validatePatternListActive(patternList: string[]) { const result = await Promise.all( patternList - .map((pattern) => - this.elasticsearchClient.count({ - index: pattern, - }) - ) - .map((p) => - p.catch((e) => { - if (e.body.error.type === 'index_not_found_exception') { - return { body: { count: 0 } }; - } - throw e; - }) - ) + .map(async (index) => { + const searchResponse = await this.elasticsearchClient.fieldCaps({ + index, + fields: '_id', + ignore_unavailable: true, + allow_no_indices: false, + }); + return searchResponse.body.indices.length > 0; + }) + .map((p) => p.catch(() => false)) ); return result.reduce( - (acc: string[], { body: { count } }, patternListIndex) => - count > 0 ? [...acc, patternList[patternListIndex]] : acc, + (acc: string[], isValid, patternListIndex) => + isValid ? [...acc, patternList[patternListIndex]] : acc, [] ); } diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx index ace01aa851ce8..13ef1c7725a3d 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_table_t_grid.tsx @@ -412,6 +412,8 @@ export function AlertsTableTGrid(props: AlertsTableTGridProps) { }, renderCellValue: getRenderCellValue({ setFlyoutAlert }), rowRenderers: NO_ROW_RENDER, + // TODO: implement Kibana data view runtime fields in observability + runtimeMappings: {}, start: rangeFrom, setRefetch, sort: [ diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 2772c3de51065..584f3ed334d89 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -11,8 +11,16 @@ import type { TransformConfigSchema } from './transforms/types'; import { ENABLE_CASE_CONNECTOR } from '../../cases/common'; import { METADATA_TRANSFORMS_PATTERN } from './endpoint/constants'; +/** + * as const + * + * The const assertion ensures that type widening does not occur + * https://mariusschulz.com/blog/literal-type-widening-in-typescript + * Please follow this convention when adding to this file + */ + export const APP_ID = 'securitySolution' as const; -export const APP_UI_ID = 'securitySolutionUI'; +export const APP_UI_ID = 'securitySolutionUI' as const; export const CASES_FEATURE_ID = 'securitySolutionCases' as const; export const SERVER_APP_ID = 'siem' as const; export const APP_NAME = 'Security' as const; @@ -26,6 +34,8 @@ export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const; export const DEFAULT_DARK_MODE = 'theme:darkMode' as const; export const DEFAULT_INDEX_KEY = 'securitySolution:defaultIndex' as const; export const DEFAULT_NUMBER_FORMAT = 'format:number:defaultPattern' as const; +export const DEFAULT_DATA_VIEW_ID = 'security-solution' as const; +export const DEFAULT_TIME_FIELD = '@timestamp' as const; export const DEFAULT_TIME_RANGE = 'timepicker:timeDefaults' as const; export const DEFAULT_REFRESH_RATE_INTERVAL = 'timepicker:refreshIntervalDefaults' as const; export const DEFAULT_APP_TIME_RANGE = 'securitySolution:timeDefaults' as const; @@ -51,7 +61,6 @@ export const DEFAULT_TIMEPICKER_QUICK_RANGES = 'timepicker:quickRanges' as const export const DEFAULT_TRANSFORMS = 'securitySolution:transforms' as const; export const SCROLLING_DISABLED_CLASS_NAME = 'scrolling-disabled' as const; export const GLOBAL_HEADER_HEIGHT = 96 as const; // px -export const GLOBAL_HEADER_HEIGHT_WITH_GLOBAL_BANNER = 128 as const; // px export const FILTERS_GLOBAL_HEIGHT = 109 as const; // px export const FULL_SCREEN_TOGGLED_CLASS_NAME = 'fullScreenToggled' as const; export const NO_ALERT_INDEX = 'no-alert-index-049FC71A-4C2C-446F-9901-37XMC5024C51' as const; @@ -268,6 +277,7 @@ export const TIMELINE_PREPACKAGED_URL = `${TIMELINE_URL}/_prepackaged` as const; export const NOTE_URL = '/api/note' as const; export const PINNED_EVENT_URL = '/api/pinned_event' as const; +export const SOURCERER_API_URL = '/api/sourcerer' as const; /** * Default signals index key for kibana.dev.yml @@ -355,7 +365,7 @@ export const ELASTIC_NAME = 'estc' as const; export const METADATA_TRANSFORM_STATS_URL = `/api/transform/transforms/${METADATA_TRANSFORMS_PATTERN}/_stats`; -export const RISKY_HOSTS_INDEX_PREFIX = 'ml_host_risk_score_latest_'; +export const RISKY_HOSTS_INDEX_PREFIX = 'ml_host_risk_score_latest_' as const; export const TRANSFORM_STATES = { ABORTING: 'aborting', diff --git a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts index 033e979d2814c..42c10614975eb 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/get_query_filter.ts @@ -11,7 +11,7 @@ import type { CreateExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; import { buildExceptionFilter } from '@kbn/securitysolution-list-utils'; -import { Filter, EsQueryConfig, IndexPatternBase, buildEsQuery } from '@kbn/es-query'; +import { Filter, EsQueryConfig, DataViewBase, buildEsQuery } from '@kbn/es-query'; import { ESBoolQuery } from '../typed_json'; import { Query, Index, TimestampOverrideOrUndefined } from './schemas/common/schemas'; @@ -24,7 +24,7 @@ export const getQueryFilter = ( lists: Array, excludeExceptions: boolean = true ): ESBoolQuery => { - const indexPattern: IndexPatternBase = { + const indexPattern: DataViewBase = { fields: [], title: index.join(), }; diff --git a/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts b/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts index be5fd3b5c4dc5..35fd5e81b096f 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/index_fields/index.ts @@ -5,79 +5,15 @@ * 2.0. */ -import type { IFieldSubType } from '@kbn/es-query'; - -import type { - IEsSearchRequest, - IEsSearchResponse, - IIndexPattern, -} from '../../../../../../src/plugins/data/common'; -import type { DocValueFields, Maybe } from '../common'; - -interface FieldInfo { - category: string; - description?: string; - example?: string | number; - format?: string; - name: string; - type?: string; -} - -export interface IndexField { - /** Where the field belong */ - category: string; - /** Example of field's value */ - example?: Maybe; - /** whether the field's belong to an alias index */ - indexes: Array>; - /** The name of the field */ - name: string; - /** The type of the field's values as recognized by Kibana */ - type: string; - /** Whether the field's values can be efficiently searched for */ - searchable: boolean; - /** Whether the field's values can be aggregated */ - aggregatable: boolean; - /** Description of the field */ - description?: Maybe; - format?: Maybe; - /** the elastic type as mapped in the index */ - esTypes?: string[]; - subType?: IFieldSubType; - readFromDocValues: boolean; -} - -export type BeatFields = Record; - -export interface IndexFieldsStrategyRequest extends IEsSearchRequest { - indices: string[]; - onlyCheckIfIndicesExist: boolean; -} - -export interface IndexFieldsStrategyResponse extends IEsSearchResponse { - indexFields: IndexField[]; - indicesExist: string[]; -} - -export interface BrowserField { - aggregatable: boolean; - category: string; - description: string | null; - example: string | number | null; - fields: Readonly>>; - format: string; - indexes: string[]; - name: string; - searchable: boolean; - type: string; - subType?: IFieldSubType; -} - -export type BrowserFields = Readonly>>; - -export const EMPTY_BROWSER_FIELDS = {}; -export const EMPTY_DOCVALUE_FIELD: DocValueFields[] = []; -export const EMPTY_INDEX_PATTERN: IIndexPattern = { - fields: [], - title: '', -}; +export { + FieldInfo, + IndexField, + BeatFields, + IndexFieldsStrategyRequest, + IndexFieldsStrategyResponse, + BrowserField, + BrowserFields, + EMPTY_BROWSER_FIELDS, + EMPTY_DOCVALUE_FIELD, + EMPTY_INDEX_FIELDS, +} from '../../../../timelines/common'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/last_event_time/index.ts b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/last_event_time/index.ts index 39f23a63c8afe..d6735b59c229d 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/timeline/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/timeline/events/last_event_time/index.ts @@ -10,6 +10,7 @@ export { LastEventIndexKey } from '../../../../../../timelines/common'; export type { LastTimeDetails, TimelineEventsLastEventTimeStrategyResponse, + TimelineKpiStrategyRequest, TimelineKpiStrategyResponse, TimelineEventsLastEventTimeRequestOptions, } from '../../../../../../timelines/common'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts b/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts index 548560ac5cb8c..2d94a36a937d5 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/timeline/index.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchRequest } from '../../../../../../src/plugins/data/common'; import { ESQuery } from '../../typed_json'; import { @@ -41,6 +42,7 @@ export interface TimelineRequestBasicOptions extends IEsSearchRequest { defaultIndex: string[]; docValueFields?: DocValueFields[]; factoryQueryType?: TimelineFactoryQueryTypes; + runtimeMappings: MappingRuntimeFields; } export interface TimelineRequestSortField extends SortField { @@ -171,6 +173,7 @@ export interface SortTimelineInput { export interface TimelineInput { columns?: Maybe; dataProviders?: Maybe; + dataViewId?: Maybe; description?: Maybe; eqlOptions?: Maybe; eventType?: Maybe; diff --git a/x-pack/plugins/security_solution/common/test/index.ts b/x-pack/plugins/security_solution/common/test/index.ts index 6d5df76b306a3..53261d54e84b0 100644 --- a/x-pack/plugins/security_solution/common/test/index.ts +++ b/x-pack/plugins/security_solution/common/test/index.ts @@ -7,12 +7,12 @@ // For the source of these roles please consult the PR these were introduced https://github.com/elastic/kibana/pull/81866#issue-511165754 export enum ROLES { + soc_manager = 'soc_manager', reader = 'reader', t1_analyst = 't1_analyst', t2_analyst = 't2_analyst', hunter = 'hunter', rule_author = 'rule_author', - soc_manager = 'soc_manager', platform_engineer = 'platform_engineer', detections_admin = 'detections_admin', } diff --git a/x-pack/plugins/security_solution/common/types/timeline/index.ts b/x-pack/plugins/security_solution/common/types/timeline/index.ts index c0046f7535db8..60fd126e6fd85 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/index.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/index.ts @@ -272,6 +272,7 @@ export type TimelineTypeLiteralWithNull = runtimeTypes.TypeOf; +export type TimelineWithoutExternalRefs = Omit; /* * Timeline IDs @@ -719,6 +720,7 @@ export interface TimelineResult { created?: Maybe; createdBy?: Maybe; dataProviders?: Maybe; + dataViewId?: Maybe; dateRange?: Maybe; description?: Maybe; eqlOptions?: Maybe; diff --git a/x-pack/plugins/security_solution/common/types/timeline/store.ts b/x-pack/plugins/security_solution/common/types/timeline/store.ts index 03cf0c39378e5..75cd44ba2b7d7 100644 --- a/x-pack/plugins/security_solution/common/types/timeline/store.ts +++ b/x-pack/plugins/security_solution/common/types/timeline/store.ts @@ -38,19 +38,20 @@ export interface SortColumnTimeline { } export interface TimelinePersistInput { - id: string; + columns: ColumnHeaderOptions[]; dataProviders?: DataProvider[]; + dataViewId: string; dateRange?: { start: string; end: string; }; + defaultColumns?: ColumnHeaderOptions[]; excludedRowRendererIds?: RowRendererId[]; expandedDetail?: TimelineExpandedDetail; filters?: Filter[]; - columns: ColumnHeaderOptions[]; - defaultColumns?: ColumnHeaderOptions[]; - itemsPerPage?: number; + id: string; indexNames: string[]; + itemsPerPage?: number; kqlQuery?: { filterQuery: SerializedFilterQuery | null; }; diff --git a/x-pack/plugins/security_solution/cypress/cypress.json b/x-pack/plugins/security_solution/cypress/cypress.json index 6a9a240af5873..8c27309becf08 100644 --- a/x-pack/plugins/security_solution/cypress/cypress.json +++ b/x-pack/plugins/security_solution/cypress/cypress.json @@ -12,5 +12,10 @@ "video": false, "videosFolder": "../../../target/kibana-security-solution/cypress/videos", "viewportHeight": 900, - "viewportWidth": 1440 + "viewportWidth": 1440, + "env": { + "protocol": "http", + "hostname": "localhost", + "configport": "5601" + } } diff --git a/x-pack/plugins/security_solution/cypress/downloads/timelines_export.ndjson b/x-pack/plugins/security_solution/cypress/downloads/timelines_export.ndjson new file mode 100644 index 0000000000000..8cf76734ad876 --- /dev/null +++ b/x-pack/plugins/security_solution/cypress/downloads/timelines_export.ndjson @@ -0,0 +1 @@ +{"savedObjectId":"46cca0e0-2580-11ec-8e56-9dafa0b0343b","version":"WzIyNjIzNCwxXQ==","columns":[{"id":"@timestamp"},{"id":"user.name"},{"id":"event.category"},{"id":"event.action"},{"id":"host.name"}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"host.name: *","kind":"kuery"}}},"dateRange":{"start":"1514809376000","end":"1577881376000"},"description":"This is the best timeline","title":"Security Timeline","created":1633399341550,"createdBy":"elastic","updated":1633399341550,"updatedBy":"elastic","savedQueryId":null,"dataViewId":null,"timelineType":"default","sort":[],"eventNotes":[],"globalNotes":[],"pinnedEventIds":[]} diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/privileges.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/privileges.spec.ts index 23016ecc512b1..0337cd3bd6e17 100644 --- a/x-pack/plugins/security_solution/cypress/integration/cases/privileges.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/cases/privileges.spec.ts @@ -18,184 +18,28 @@ import { filterStatusOpen, } from '../../tasks/create_new_case'; import { - constructUrlWithUser, - getEnvAuth, + loginAndWaitForHostDetailsPage, loginWithUserAndWaitForPageWithoutDateRange, + logout, } from '../../tasks/login'; +import { + createUsersAndRoles, + deleteUsersAndRoles, + secAll, + secAllUser, + secReadCasesAllUser, + secReadCasesAll, +} from '../../tasks/privileges'; import { CASES_URL } from '../../urls/navigation'; - -interface User { - username: string; - password: string; - description?: string; - roles: string[]; -} - -interface UserInfo { - username: string; - full_name: string; - email: string; -} - -interface FeaturesPrivileges { - [featureId: string]: string[]; -} - -interface ElasticsearchIndices { - names: string[]; - privileges: string[]; -} - -interface ElasticSearchPrivilege { - cluster?: string[]; - indices?: ElasticsearchIndices[]; -} - -interface KibanaPrivilege { - spaces: string[]; - base?: string[]; - feature?: FeaturesPrivileges; -} - -interface Role { - name: string; - privileges: { - elasticsearch?: ElasticSearchPrivilege; - kibana?: KibanaPrivilege[]; - }; -} - -const secAll: Role = { - name: 'sec_all_role', - privileges: { - elasticsearch: { - indices: [ - { - names: ['*'], - privileges: ['all'], - }, - ], - }, - kibana: [ - { - feature: { - siem: ['all'], - securitySolutionCases: ['all'], - actions: ['all'], - actionsSimulators: ['all'], - }, - spaces: ['*'], - }, - ], - }, -}; - -const secAllUser: User = { - username: 'sec_all_user', - password: 'password', - roles: [secAll.name], -}; - -const secReadCasesAll: Role = { - name: 'sec_read_cases_all_role', - privileges: { - elasticsearch: { - indices: [ - { - names: ['*'], - privileges: ['all'], - }, - ], - }, - kibana: [ - { - feature: { - siem: ['read'], - securitySolutionCases: ['all'], - actions: ['all'], - actionsSimulators: ['all'], - }, - spaces: ['*'], - }, - ], - }, -}; - -const secReadCasesAllUser: User = { - username: 'sec_read_cases_all_user', - password: 'password', - roles: [secReadCasesAll.name], -}; - +import { openSourcerer } from '../../tasks/sourcerer'; const usersToCreate = [secAllUser, secReadCasesAllUser]; const rolesToCreate = [secAll, secReadCasesAll]; - -const getUserInfo = (user: User): UserInfo => ({ - username: user.username, - full_name: user.username.replace('_', ' '), - email: `${user.username}@elastic.co`, -}); - -const createUsersAndRoles = (users: User[], roles: Role[]) => { - const envUser = getEnvAuth(); - for (const role of roles) { - cy.log(`Creating role: ${JSON.stringify(role)}`); - cy.request({ - body: role.privileges, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'PUT', - url: constructUrlWithUser(envUser, `/api/security/role/${role.name}`), - }) - .its('status') - .should('eql', 204); - } - - for (const user of users) { - const userInfo = getUserInfo(user); - cy.log(`Creating user: ${JSON.stringify(user)}`); - cy.request({ - body: { - username: user.username, - password: user.password, - roles: user.roles, - full_name: userInfo.full_name, - email: userInfo.email, - }, - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'POST', - url: constructUrlWithUser(envUser, `/internal/security/users/${user.username}`), - }) - .its('status') - .should('eql', 200); - } -}; - -const deleteUsersAndRoles = (users: User[], roles: Role[]) => { - const envUser = getEnvAuth(); - for (const user of users) { - cy.log(`Deleting user: ${JSON.stringify(user)}`); - cy.request({ - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'DELETE', - url: constructUrlWithUser(envUser, `/internal/security/users/${user.username}`), - failOnStatusCode: false, - }) - .its('status') - .should('oneOf', [204, 404]); - } - - for (const role of roles) { - cy.log(`Deleting role: ${JSON.stringify(role)}`); - cy.request({ - headers: { 'kbn-xsrf': 'cypress-creds-via-config' }, - method: 'DELETE', - url: constructUrlWithUser(envUser, `/api/security/role/${role.name}`), - failOnStatusCode: false, - }) - .its('status') - .should('oneOf', [204, 404]); - } +// needed to generate index pattern +const visitSecuritySolution = () => { + loginAndWaitForHostDetailsPage(); + openSourcerer(); + logout(); }; const testCase: TestCaseWithoutTimeline = { @@ -205,11 +49,11 @@ const testCase: TestCaseWithoutTimeline = { reporter: 'elastic', owner: 'securitySolution', }; - describe('Cases privileges', () => { before(() => { cleanKibana(); createUsersAndRoles(usersToCreate, rolesToCreate); + visitSecuritySolution(); }); after(() => { diff --git a/x-pack/plugins/security_solution/cypress/integration/data_sources/sourcerer.spec.ts b/x-pack/plugins/security_solution/cypress/integration/data_sources/sourcerer.spec.ts index 26c366e981d44..bd7acc38c1021 100644 --- a/x-pack/plugins/security_solution/cypress/integration/data_sources/sourcerer.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/data_sources/sourcerer.spec.ts @@ -5,7 +5,10 @@ * 2.0. */ -import { loginAndWaitForPage } from '../../tasks/login'; +import { + loginAndWaitForPage, + loginWithUserAndWaitForPageWithoutDateRange, +} from '../../tasks/login'; import { HOSTS_URL } from '../../urls/navigation'; import { waitForAllHostsToBeLoaded } from '../../tasks/hosts/all_hosts'; @@ -28,20 +31,34 @@ import { openTimelineUsingToggle } from '../../tasks/security_main'; import { populateTimeline } from '../../tasks/timeline'; import { SERVER_SIDE_EVENT_COUNT } from '../../screens/timeline'; import { cleanKibana } from '../../tasks/common'; +import { createUsersAndRoles, secReadCasesAll, secReadCasesAllUser } from '../../tasks/privileges'; +import { TOASTER } from '../../screens/configure_cases'; +const usersToCreate = [secReadCasesAllUser]; +const rolesToCreate = [secReadCasesAll]; // Skipped at the moment as this has flake due to click handler issues. This has been raised with team members // and the code is being re-worked and then these tests will be unskipped -describe.skip('Sourcerer', () => { - before(() => { +describe('Sourcerer', () => { + beforeEach(() => { cleanKibana(); }); - - beforeEach(() => { - cy.clearLocalStorage(); - loginAndWaitForPage(HOSTS_URL); + describe('permissions', () => { + before(() => { + createUsersAndRoles(usersToCreate, rolesToCreate); + }); + it(`role(s) ${secReadCasesAllUser.roles.join()} shows error when user does not have permissions`, () => { + loginWithUserAndWaitForPageWithoutDateRange(HOSTS_URL, secReadCasesAllUser); + cy.get(TOASTER).should('have.text', 'Write role required to generate data'); + }); }); + // Originially written in December 2020, flakey from day1 + // has always been skipped with intentions to fix, see note at top of file + describe.skip('Default scope', () => { + beforeEach(() => { + cy.clearLocalStorage(); + loginAndWaitForPage(HOSTS_URL); + }); - describe('Default scope', () => { it('has SIEM index patterns selected on initial load', () => { openSourcerer(); isSourcererSelection(`auditbeat-*`); @@ -52,7 +69,7 @@ describe.skip('Sourcerer', () => { isSourcererOptions([`metrics-*`, `logs-*`]); }); - it('selected KIP gets added to sourcerer', () => { + it('selected DATA_VIEW gets added to sourcerer', () => { setSourcererOption(`metrics-*`); openSourcerer(); isSourcererSelection(`metrics-*`); @@ -75,8 +92,14 @@ describe.skip('Sourcerer', () => { isNotSourcererSelection(`metrics-*`); }); }); + // Originially written in December 2020, flakey from day1 + // has always been skipped with intentions to fix + describe.skip('Timeline scope', () => { + beforeEach(() => { + cy.clearLocalStorage(); + loginAndWaitForPage(HOSTS_URL); + }); - describe('Timeline scope', () => { const alertPatterns = ['.siem-signals-default']; const rawPatterns = ['auditbeat-*']; const allPatterns = [...alertPatterns, ...rawPatterns]; diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts index 803ff4b4d0d80..033a12dd9de3e 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts @@ -9,6 +9,7 @@ import { ALERT_FLYOUT, CELL_TEXT, JSON_TEXT, TABLE_ROWS } from '../../screens/al import { expandFirstAlert, + refreshAlerts, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, } from '../../tasks/alerts'; @@ -32,6 +33,7 @@ describe('Alert details with unmapped fields', () => { createCustomRuleActivated(getUnmappedRule()); loginAndWaitForPageWithoutDateRange(ALERTS_URL); waitForAlertsPanelToBeLoaded(); + refreshAlerts(); expandFirstAlert(); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts index 10f556a11bf60..171d224cc32d3 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts @@ -70,7 +70,7 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; import { ALERTS_URL } from '../../urls/navigation'; -describe.skip('Detection rules, EQL', () => { +describe('Detection rules, EQL', () => { const expectedUrls = getEqlRule().referenceUrls.join(''); const expectedFalsePositives = getEqlRule().falsePositivesExamples.join(''); const expectedTags = getEqlRule().tags.join(''); @@ -169,7 +169,7 @@ describe.skip('Detection rules, EQL', () => { }); }); -describe.skip('Detection rules, sequence EQL', () => { +describe('Detection rules, sequence EQL', () => { const expectedNumberOfRules = 1; const expectedNumberOfSequenceAlerts = '1 alert'; diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts index 02621ea49e906..378de8f0bc593 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts @@ -114,7 +114,7 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; import { goBackToAllRulesTable } from '../../tasks/rule_details'; import { ALERTS_URL, RULE_CREATION } from '../../urls/navigation'; -import { DEFAULT_THREAT_MATCH_QUERY } from '../../../common/constants'; +const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d"'; describe('indicator match', () => { describe('Detection rules, Indicator Match', () => { diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts index ef3d3a82d40bd..92f9e8180d50c 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts @@ -34,7 +34,6 @@ import { waitForRuleToChangeStatus, } from '../../tasks/alerts_detection_rules'; import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login'; -import { DEFAULT_RULE_REFRESH_INTERVAL_VALUE } from '../../../common/constants'; import { ALERTS_URL } from '../../urls/navigation'; import { createCustomRule } from '../../tasks/api_calls/rules'; @@ -46,6 +45,8 @@ import { getNewThresholdRule, } from '../../objects/rule'; +const DEFAULT_RULE_REFRESH_INTERVAL_VALUE = 60000; + describe('Alerts detection rules', () => { beforeEach(() => { cleanKibana(); diff --git a/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts b/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts index 89a0d5a660b97..f9d78ba12a5ea 100644 --- a/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/ml/ml_conditional_links.spec.ts @@ -98,7 +98,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlNetworkSingleIpNullKqlQuery); cy.url().should( 'include', - 'app/security/network/ip/127.0.0.1/source?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + 'app/security/network/ip/127.0.0.1/source?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -106,7 +106,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlNetworkSingleIpKqlQuery); cy.url().should( 'include', - '/app/security/network/ip/127.0.0.1/source?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/network/ip/127.0.0.1/source?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -114,7 +114,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlNetworkMultipleIpNullKqlQuery); cy.url().should( 'include', - 'app/security/network/flows?query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + 'app/security/network/flows?query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -122,7 +122,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlNetworkMultipleIpKqlQuery); cy.url().should( 'include', - '/app/security/network/flows?query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/network/flows?query=(language:kuery,query:%27((source.ip:%20%22127.0.0.1%22%20or%20destination.ip:%20%22127.0.0.1%22)%20or%20(source.ip:%20%22127.0.0.2%22%20or%20destination.ip:%20%22127.0.0.2%22))%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -130,15 +130,16 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlNetworkNullKqlQuery); cy.url().should( 'include', - '/app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/network/flows?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); it('redirects from a $ip$ with a value for the query', () => { loginAndWaitForPageWithoutDateRange(mlNetworkKqlQuery); + cy.url().should( 'include', - '/app/security/network/flows?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + `/app/security/network/flows?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-08-28T11:00:00.000Z%27,kind:absolute,to:%272019-08-28T13:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))` ); }); @@ -146,7 +147,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostSingleHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -154,7 +155,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostSingleHostKqlQueryVariable); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/siem-windows/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -162,7 +163,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostSingleHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/siem-windows/anomalies?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/siem-windows/anomalies?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -170,7 +171,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostMultiHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/anomalies?query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -178,7 +179,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostMultiHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/anomalies?query=(language:kuery,query:%27(host.name:%20%22siem-windows%22%20or%20host.name:%20%22siem-suricata%22)%20and%20((process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22))%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -186,7 +187,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostVariableHostNullKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/anomalies?timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); @@ -194,7 +195,7 @@ describe('ml conditional links', () => { loginAndWaitForPageWithoutDateRange(mlHostVariableHostKqlQuery); cy.url().should( 'include', - '/app/security/hosts/anomalies?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:!(%27auditbeat-*%27))' + '/app/security/hosts/anomalies?query=(language:kuery,query:%27(process.name:%20%22conhost.exe%22%20or%20process.name:%20%22sc.exe%22)%27)&timerange=(global:(linkTo:!(timeline),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)),timeline:(linkTo:!(global),timerange:(from:%272019-06-06T06:00:00.000Z%27,kind:absolute,to:%272019-06-07T05:59:59.999Z%27)))&sourcerer=(default:(id:security-solution-default,selectedPatterns:!(%27auditbeat-*%27)))' ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts index fb41aec91b6c4..cbff911e5d982 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts @@ -121,7 +121,6 @@ describe('Create a timeline from a template', () => { loginAndWaitForPageWithoutDateRange(TIMELINE_TEMPLATES_URL); waitForTimelinesPanelToBeLoaded(); }); - it('Should have the same query and open the timeline modal', () => { selectCustomTemplates(); cy.wait('@timeline', { timeout: 100000 }); @@ -132,5 +131,6 @@ describe('Create a timeline from a template', () => { cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible'); cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description); cy.get(TIMELINE_QUERY).should('have.text', getTimeline().query); + closeTimeline(); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts index 73eb141f1ce3d..28fe1294e6f01 100644 --- a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts @@ -182,11 +182,10 @@ describe('url state', () => { loginAndWaitForPageWithoutDateRange(ABSOLUTE_DATE_RANGE.url); kqlSearch('source.ip: "10.142.0.9" {enter}'); navigateFromHeaderTo(HOSTS); - cy.get(NETWORK).should( 'have.attr', 'href', - `/app/security/network?query=(language:kuery,query:'source.ip:%20%2210.142.0.9%22%20')&sourcerer=(default:!(\'auditbeat-*\'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')))` + `/app/security/network?query=(language:kuery,query:'source.ip:%20%2210.142.0.9%22%20')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2019-08-01T20:33:29.186Z')))` ); }); @@ -199,12 +198,12 @@ describe('url state', () => { cy.get(HOSTS).should( 'have.attr', 'href', - `/app/security/hosts?query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&sourcerer=(default:!(\'auditbeat-*\'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` + `/app/security/hosts?query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` ); cy.get(NETWORK).should( 'have.attr', 'href', - `/app/security/network?query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&sourcerer=(default:!(\'auditbeat-*\'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` + `/app/security/network?query=(language:kuery,query:'host.name:%20%22siem-kibana%22%20')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` ); cy.get(HOSTS_NAMES).first().should('have.text', 'siem-kibana'); @@ -215,21 +214,21 @@ describe('url state', () => { cy.get(ANOMALIES_TAB).should( 'have.attr', 'href', - "/app/security/hosts/siem-kibana/anomalies?sourcerer=(default:!('auditbeat-*'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')" + "/app/security/hosts/siem-kibana/anomalies?sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))&query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')" ); cy.get(BREADCRUMBS) .eq(1) .should( 'have.attr', 'href', - `/app/security/hosts?query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&sourcerer=(default:!(\'auditbeat-*\'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` + `/app/security/hosts?query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` ); cy.get(BREADCRUMBS) .eq(2) .should( 'have.attr', 'href', - `/app/security/hosts/siem-kibana?query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&sourcerer=(default:!(\'auditbeat-*\'))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` + `/app/security/hosts/siem-kibana?query=(language:kuery,query:'agent.type:%20%22auditbeat%22%20')&sourcerer=(default:(id:security-solution-default,selectedPatterns:!('auditbeat-*')))&timerange=(global:(linkTo:!(timeline),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')),timeline:(linkTo:!(global),timerange:(from:'2019-08-01T20:03:29.186Z',kind:absolute,to:'2020-01-01T21:33:29.186Z')))` ); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/timeline.ts b/x-pack/plugins/security_solution/cypress/objects/timeline.ts index f3d9bc1b9ef1a..70b8c1b400d51 100644 --- a/x-pack/plugins/security_solution/cypress/objects/timeline.ts +++ b/x-pack/plugins/security_solution/cypress/objects/timeline.ts @@ -87,6 +87,7 @@ export const expectedExportedTimelineTemplate = ( }, }, }, + dataViewId: timelineTemplateBody.dataViewId, dateRange: { start: timelineTemplateBody.dateRange?.start, end: timelineTemplateBody.dateRange?.end, @@ -127,6 +128,7 @@ export const expectedExportedTimeline = (timelineResponse: Cypress.Response