From 6760c3394d3573cef7c97ef56af0b5940cc2912e Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Fri, 17 Jan 2020 19:22:22 -0500 Subject: [PATCH] [SIEM] Detections add alert & signal tab (#55127) * add alert on detections * review I + fix unit test * review II * review III * review IV + bug fixes found during review * review VI --- .../public/components/alerts_viewer/index.tsx | 7 +- .../components/alerts_viewer/translations.ts | 6 +- .../public/components/link_to/link_to.tsx | 7 ++ .../link_to/redirect_to_detection_engine.tsx | 19 ++- .../components/matrix_histogram/index.tsx | 5 +- .../anomalies_query_tab_body/index.tsx | 17 ++- .../containers/matrix_histogram/index.tsx | 1 - .../containers/matrix_histogram/utils.ts | 12 +- .../components/signals/translations.ts | 2 +- .../signals_histogram_panel/config.ts | 21 ++-- .../signals_histogram_panel/index.tsx | 2 +- .../signals_histogram/index.tsx | 2 +- .../detection_engine/detection_engine.tsx | 116 +++++++++++++----- .../public/pages/detection_engine/index.tsx | 16 ++- .../detection_engine/rules/details/index.tsx | 47 ++++--- .../detection_engine/rules/translations.ts | 2 +- .../pages/detection_engine/translations.ts | 6 +- .../public/pages/detection_engine/types.ts | 10 ++ .../authentications_query_tab_body.tsx | 3 +- .../navigation/events_query_tab_body.tsx | 5 +- .../siem/public/pages/hosts/translations.ts | 21 ---- .../network/navigation/dns_query_tab_body.tsx | 3 +- .../siem/public/pages/network/translations.ts | 4 - .../overview/alerts_by_category/index.tsx | 31 ++--- .../overview/events_by_dataset/index.tsx | 12 +- .../public/pages/overview/translations.ts | 4 + 26 files changed, 240 insertions(+), 141 deletions(-) create mode 100644 x-pack/legacy/plugins/siem/public/pages/detection_engine/types.ts diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx index 87d83f7f2972c1..0b99a8b059df79 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/index.tsx @@ -16,11 +16,11 @@ import { MatrixHistogramGqlQuery } from '../../containers/matrix_histogram/index const ID = 'alertsOverTimeQuery'; export const alertsStackByOptions: MatrixHistogramOption[] = [ { - text: i18n.CATEGORY, + text: 'event.category', value: 'event.category', }, { - text: i18n.MODULE, + text: 'event.module', value: 'event.module', }, ]; @@ -54,7 +54,6 @@ export const AlertsView = ({ <> diff --git a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts index 8c6248e38c057d..408c406a854be4 100644 --- a/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts +++ b/x-pack/legacy/plugins/siem/public/components/alerts_viewer/translations.ts @@ -14,10 +14,14 @@ export const TOTAL_COUNT_OF_ALERTS = i18n.translate('xpack.siem.alertsView.total defaultMessage: 'alerts match the search criteria', }); -export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.alertsView.alertsDocumentType', { +export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.alertsView.alertsTableTitle', { defaultMessage: 'Alerts', }); +export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.alertsView.alertsGraphTitle', { + defaultMessage: 'Alert detection frequency', +}); + export const ALERTS_STACK_BY_MODULE = i18n.translate( 'xpack.siem.alertsView.alertsStackByOptions.module', { diff --git a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx index 7c15af3fe642ad..0519f5c7c956b3 100644 --- a/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx +++ b/x-pack/legacy/plugins/siem/public/components/link_to/link_to.tsx @@ -20,6 +20,7 @@ import { RedirectToHostsPage, RedirectToHostDetailsPage } from './redirect_to_ho import { RedirectToNetworkPage } from './redirect_to_network'; import { RedirectToOverviewPage } from './redirect_to_overview'; import { RedirectToTimelinesPage } from './redirect_to_timelines'; +import { DetectionEngineTab } from '../../pages/detection_engine/types'; interface LinkToPageProps { match: RouteMatch<{}>; @@ -63,6 +64,12 @@ export const LinkToPage = React.memo(({ match }) => ( path={`${match.url}/:pageName(${SiemPageName.detectionEngine})`} strict /> + ; export const DETECTION_ENGINE_PAGE_NAME = 'detection-engine'; export const RedirectToDetectionEnginePage = ({ + match: { + params: { tabName }, + }, location: { search }, -}: DetectionEngineComponentProps) => ( - -); +}: DetectionEngineComponentProps) => { + const defaultSelectedTab = DetectionEngineTab.signals; + const selectedTab = tabName ? tabName : defaultSelectedTab; + const to = `/${DETECTION_ENGINE_PAGE_NAME}/${selectedTab}${search}`; + + return ; +}; export const RedirectToRulesPage = ({ location: { search } }: DetectionEngineComponentProps) => { return ; @@ -28,7 +37,7 @@ export const RedirectToRulesPage = ({ location: { search } }: DetectionEngineCom export const RedirectToCreateRulePage = ({ location: { search }, }: DetectionEngineComponentProps) => { - return ; + return ; }; export const RedirectToRuleDetailsPage = ({ @@ -44,6 +53,8 @@ export const RedirectToEditRulePage = ({ location: { search } }: DetectionEngine }; export const getDetectionEngineUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}`; +export const getDetectionEngineAlertUrl = () => + `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/${DetectionEngineTab.alerts}`; export const getRulesUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules`; export const getCreateRuleUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules/create-rule`; export const getRuleDetailsUrl = () => `#/link-to/${DETECTION_ENGINE_PAGE_NAME}/rules/rule-details`; diff --git a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx index 56ebbb06f3eb98..cdd62c430a50cc 100644 --- a/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/matrix_histogram/index.tsx @@ -46,12 +46,12 @@ export const MatrixHistogramComponent: React.FC { + useEffect(() => { + return () => { + if (deleteQuery) { + deleteQuery({ id: ID }); + } + }; + }, []); + const [, siemJobs] = useSiemJobs(true); const [anomalyScore] = useUiSetting$(DEFAULT_ANOMALY_SCORE); @@ -51,21 +59,12 @@ export const AnomaliesQueryTabBody = ({ ip ); - useEffect(() => { - return () => { - if (deleteQuery) { - deleteQuery({ id: ID }); - } - }; - }, []); - return ( <> void; errorMessage: string; headerChildren?: React.ReactNode; hideHistogramIfEmpty?: boolean; diff --git a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts index 9cda9d8f6115f5..1df1aec76627ce 100644 --- a/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts +++ b/x-pack/legacy/plugins/siem/public/containers/matrix_histogram/utils.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { getOr } from 'lodash/fp'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { MatrixHistogramDataTypes, MatrixHistogramQueryProps, @@ -35,7 +35,7 @@ export const useQuery = ({ }: MatrixHistogramQueryProps) => { const [defaultIndex] = useUiSetting$(DEFAULT_INDEX_KEY); const [, dispatchToaster] = useStateToaster(); - const [refetch, setRefetch] = useState(); + const refetch = useRef(); const [loading, setLoading] = useState(false); const [data, setData] = useState(null); const [inspect, setInspect] = useState(null); @@ -71,7 +71,7 @@ export const useQuery = ({ return apolloClient .query({ query, - fetchPolicy: 'cache-first', + fetchPolicy: 'network-only', variables: matrixHistogramVariables, context: { fetchOptions: { @@ -103,9 +103,7 @@ export const useQuery = ({ } ); } - setRefetch(() => { - fetchData(); - }); + refetch.current = fetchData; fetchData(); return () => { isSubscribed = false; @@ -122,5 +120,5 @@ export const useQuery = ({ endDate, ]); - return { data, loading, inspect, totalCount, refetch }; + return { data, loading, inspect, totalCount, refetch: refetch.current }; }; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts index d1ba946be41de1..c262f907c98763 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals/translations.ts @@ -11,7 +11,7 @@ export const PAGE_TITLE = i18n.translate('xpack.siem.detectionEngine.pageTitle', }); export const SIGNALS_TABLE_TITLE = i18n.translate('xpack.siem.detectionEngine.signals.tableTitle', { - defaultMessage: 'All signals', + defaultMessage: 'Signals', }); export const SIGNALS_DOCUMENT_TYPE = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts index f329780b075e3f..d475fd155ea25d 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/config.ts @@ -4,18 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import * as i18n from './translations'; import { SignalsHistogramOption } from './types'; export const signalsHistogramOptions: SignalsHistogramOption[] = [ - { text: i18n.STACK_BY_RISK_SCORES, value: 'signal.rule.risk_score' }, - { text: i18n.STACK_BY_SEVERITIES, value: 'signal.rule.severity' }, - { text: i18n.STACK_BY_DESTINATION_IPS, value: 'destination.ip' }, - { text: i18n.STACK_BY_ACTIONS, value: 'event.action' }, - { text: i18n.STACK_BY_CATEGORIES, value: 'event.category' }, - { text: i18n.STACK_BY_HOST_NAMES, value: 'host.name' }, - { text: i18n.STACK_BY_RULE_TYPES, value: 'signal.rule.type' }, - { text: i18n.STACK_BY_RULE_NAMES, value: 'signal.rule.name' }, - { text: i18n.STACK_BY_SOURCE_IPS, value: 'source.ip' }, - { text: i18n.STACK_BY_USERS, value: 'user.name' }, + { text: 'signal.rule.risk_score', value: 'signal.rule.risk_score' }, + { text: 'signal.rule.severity', value: 'signal.rule.severity' }, + { text: 'destination.ip', value: 'destination.ip' }, + { text: 'event.action', value: 'event.action' }, + { text: 'event.category', value: 'event.category' }, + { text: 'host.name', value: 'host.name' }, + { text: 'signal.rule.type', value: 'signal.rule.type' }, + { text: 'signal.rule.name', value: 'signal.rule.name' }, + { text: 'source.ip', value: 'source.ip' }, + { text: 'user.name', value: 'user.name' }, ]; diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx index fda40f5f9fa5db..64bc7ba24c6895 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/index.tsx @@ -46,7 +46,7 @@ export const SignalsHistogramPanel = memo( filters, query, from, - legendPosition = 'bottom', + legendPosition = 'right', loadingInitial = false, showLinkToSignals = false, showTotalSignalsCount = false, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx index 218fcc3a70f79f..d4db8cc7c37e87 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/components/signals_histogram_panel/signals_histogram/index.tsx @@ -44,7 +44,7 @@ export const SignalsHistogram = React.memo( from, query, filters, - legendPosition = 'bottom', + legendPosition = 'right', loadingInitial, setTotalSignalsCount, stackByField, diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx index 388f667f47fe12..26a9ad128b1dc1 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/detection_engine.tsx @@ -4,27 +4,31 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiButton, EuiSpacer } from '@elastic/eui'; -import React, { useCallback } from 'react'; +import { EuiButton, EuiSpacer, EuiTab, EuiTabs } from '@elastic/eui'; +import React, { useCallback, useMemo } from 'react'; +import { useParams } from 'react-router-dom'; import { StickyContainer } from 'react-sticky'; - import { connect } from 'react-redux'; import { ActionCreator } from 'typescript-fsa'; + +import { Query } from '../../../../../../../src/plugins/data/common/query'; +import { esFilters } from '../../../../../../../src/plugins/data/common/es_query'; + +import { GlobalTime } from '../../containers/global_time'; +import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; +import { AlertsTable } from '../../components/alerts_viewer/alerts_table'; import { FiltersGlobal } from '../../components/filters_global'; import { HeaderPage } from '../../components/header_page'; +import { DETECTION_ENGINE_PAGE_NAME } from '../../components/link_to/redirect_to_detection_engine'; import { SiemSearchBar } from '../../components/search_bar'; import { WrapperPage } from '../../components/wrapper_page'; -import { GlobalTime } from '../../containers/global_time'; -import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; -import { SpyRoute } from '../../utils/route/spy_routes'; - -import { Query } from '../../../../../../../src/plugins/data/common/query'; -import { esFilters } from '../../../../../../../src/plugins/data/common/es_query'; import { State } from '../../store'; import { inputsSelectors } from '../../store/inputs'; import { setAbsoluteRangeDatePicker as dispatchSetAbsoluteRangeDatePicker } from '../../store/inputs/actions'; +import { SpyRoute } from '../../utils/route/spy_routes'; import { InputsModelId } from '../../store/inputs/constants'; import { InputsRange } from '../../store/inputs/model'; +import { AlertsByCategory } from '../overview/alerts_by_category'; import { useSignalInfo } from './components/signals_info'; import { SignalsTable } from './components/signals'; import { NoWriteSignalsCallOut } from './components/no_write_signals_callout'; @@ -35,6 +39,7 @@ import { DetectionEngineEmptyPage } from './detection_engine_empty_page'; import { DetectionEngineNoIndex } from './detection_engine_no_signal_index'; import { DetectionEngineUserUnauthenticated } from './detection_engine_user_unauthenticated'; import * as i18n from './translations'; +import { DetectionEngineTab } from './types'; interface ReduxProps { filters: esFilters.Filter[]; @@ -51,8 +56,22 @@ export interface DispatchProps { type DetectionEngineComponentProps = ReduxProps & DispatchProps; +const detectionsTabs = [ + { + id: DetectionEngineTab.signals, + name: i18n.SIGNAL, + disabled: false, + }, + { + id: DetectionEngineTab.alerts, + name: i18n.ALERT, + disabled: false, + }, +]; + const DetectionEngineComponent = React.memo( ({ filters, query, setAbsoluteRangeDatePicker }) => { + const { tabName = DetectionEngineTab.signals } = useParams(); const { loading, isSignalIndexExists, @@ -87,6 +106,25 @@ const DetectionEngineComponent = React.memo( ); } + + const tabs = useMemo( + () => ( + + {detectionsTabs.map(tab => ( + + {tab.name} + + ))} + + ), + [detectionsTabs, tabName] + ); + return ( <> {hasIndexWrite != null && !hasIndexWrite && } @@ -99,7 +137,6 @@ const DetectionEngineComponent = React.memo( @@ -117,26 +154,49 @@ const DetectionEngineComponent = React.memo( - {({ to, from }) => ( + {({ to, from, deleteQuery, setQuery }) => ( <> - + {tabs} - + {tabName === DetectionEngineTab.signals && ( + <> + + + + + )} + {tabName === DetectionEngineTab.alerts && ( + <> + + + + + )} )} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx index c4e83429aebdbf..7a0b8df85416c4 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/index.tsx @@ -7,12 +7,13 @@ import React from 'react'; import { Redirect, Route, Switch, RouteComponentProps } from 'react-router-dom'; +import { ManageUserInfo } from './components/user_info'; import { CreateRuleComponent } from './rules/create'; import { DetectionEngine } from './detection_engine'; import { EditRuleComponent } from './rules/edit'; import { RuleDetails } from './rules/details'; import { RulesComponent } from './rules'; -import { ManageUserInfo } from './components/user_info'; +import { DetectionEngineTab } from './types'; const detectionEnginePath = `/:pageName(detection-engine)`; @@ -21,7 +22,11 @@ type Props = Partial> & { url: string }; export const DetectionEngineContainer = React.memo(() => ( - + @@ -30,7 +35,7 @@ export const DetectionEngineContainer = React.memo(() => ( - + @@ -39,7 +44,10 @@ export const DetectionEngineContainer = React.memo(() => ( ( - + )} /> diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx index 099006a34920c0..86d7178e73c608 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/details/index.tsx @@ -12,6 +12,7 @@ import { EuiSpacer, EuiHealth, EuiTab, + EuiTabs, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { memo, useCallback, useMemo, useState } from 'react'; @@ -78,14 +79,19 @@ export interface DispatchProps { }>; } +enum RuleDetailTabs { + signals = 'signals', + failures = 'failures', +} + const ruleDetailTabs = [ { - id: 'signal', + id: RuleDetailTabs.signals, name: detectionI18n.SIGNAL, disabled: false, }, { - id: 'failure', + id: RuleDetailTabs.failures, name: i18n.FAILURE_HISTORY_TAB, disabled: false, }, @@ -106,7 +112,7 @@ const RuleDetailsComponent = memo( } = useUserInfo(); const { ruleId } = useParams(); const [isLoading, rule] = useRule(ruleId); - const [ruleDetailTab, setRuleDetailTab] = useState('signal'); + const [ruleDetailTab, setRuleDetailTab] = useState(RuleDetailTabs.signals); const { aboutRuleData, defineRuleData, scheduleRuleData } = getStepsData({ rule, detailsView: true, @@ -187,22 +193,27 @@ const RuleDetailsComponent = memo( : 'subdued'; const tabs = useMemo( - () => - ruleDetailTabs.map(tab => ( - setRuleDetailTab(tab.id)} - isSelected={tab.id === ruleDetailTab} - disabled={tab.disabled} - key={tab.name} - > - {tab.name} - - )), + () => ( + + {ruleDetailTabs.map(tab => ( + setRuleDetailTab(tab.id)} + isSelected={tab.id === ruleDetailTab} + disabled={tab.disabled} + key={tab.id} + > + {tab.name} + + ))} + + ), [ruleDetailTabs, ruleDetailTab, setRuleDetailTab] ); const ruleError = useMemo( () => - rule?.status === 'failed' && ruleDetailTab === 'signal' && rule?.last_failure_at != null ? ( + rule?.status === 'failed' && + ruleDetailTab === RuleDetailTabs.signals && + rule?.last_failure_at != null ? ( ( {ruleError} {tabs} - {ruleDetailTab === 'signal' && ( + {ruleDetailTab === RuleDetailTabs.signals && ( <> @@ -381,7 +392,9 @@ const RuleDetailsComponent = memo( )} )} - {ruleDetailTab === 'failure' && } + {ruleDetailTab === RuleDetailTabs.failures && ( + + )} )} diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts index aeeef925d60e56..30b50c8cce2092 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/rules/translations.ts @@ -22,7 +22,7 @@ export const ADD_NEW_RULE = i18n.translate('xpack.siem.detectionEngine.rules.add }); export const PAGE_TITLE = i18n.translate('xpack.siem.detectionEngine.rules.pageTitle', { - defaultMessage: 'Rules', + defaultMessage: 'Signal detection rules', }); export const REFRESH = i18n.translate('xpack.siem.detectionEngine.rules.allRules.refreshTitle', { diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts index e5f830d3a49b0e..d1935b4fd581da 100644 --- a/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/translations.ts @@ -22,8 +22,12 @@ export const SIGNAL = i18n.translate('xpack.siem.detectionEngine.signalTitle', { defaultMessage: 'Signals', }); +export const ALERT = i18n.translate('xpack.siem.detectionEngine.alertTitle', { + defaultMessage: 'Third-party alerts', +}); + export const BUTTON_MANAGE_RULES = i18n.translate('xpack.siem.detectionEngine.buttonManageRules', { - defaultMessage: 'Manage rules', + defaultMessage: 'Manage signal detection rules', }); export const PANEL_SUBTITLE_SHOWING = i18n.translate( diff --git a/x-pack/legacy/plugins/siem/public/pages/detection_engine/types.ts b/x-pack/legacy/plugins/siem/public/pages/detection_engine/types.ts new file mode 100644 index 00000000000000..d529d99ad3ad4b --- /dev/null +++ b/x-pack/legacy/plugins/siem/public/pages/detection_engine/types.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +export enum DetectionEngineTab { + signals = 'signals', + alerts = 'alerts', +} diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/authentications_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/authentications_query_tab_body.tsx index 0bb95632963160..0109eeef914635 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/authentications_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/authentications_query_tab_body.tsx @@ -25,7 +25,7 @@ const AuthenticationTableManage = manageQuery(AuthenticationTable); const ID = 'authenticationsOverTimeQuery'; const authStackByOptions: MatrixHistogramOption[] = [ { - text: i18n.NAVIGATION_AUTHENTICATIONS_STACK_BY_EVENT_TYPE, + text: 'event.type', value: 'event.type', }, ]; @@ -71,7 +71,6 @@ export const AuthenticationsQueryTabBody = ({ isAuthenticationsHistogram={true} dataKey="AuthenticationsHistogram" defaultStackByOption={authStackByOptions[0]} - deleteQuery={deleteQuery} endDate={endDate} errorMessage={i18n.ERROR_FETCHING_AUTHENTICATIONS_DATA} filterQuery={filterQuery} diff --git a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx index a07cbc8484a1b4..85bca90cc8e04a 100644 --- a/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/hosts/navigation/events_query_tab_body.tsx @@ -20,11 +20,11 @@ const EVENTS_HISTOGRAM_ID = 'eventsOverTimeQuery'; export const eventsStackByOptions: MatrixHistogramOption[] = [ { - text: i18n.NAVIGATION_EVENTS_STACK_BY_EVENT_ACTION, + text: 'event.action', value: 'event.action', }, { - text: i18n.NAVIGATION_EVENTS_STACK_BY_EVENT_DATASET, + text: 'event.dataset', value: 'event.dataset', }, ]; @@ -50,7 +50,6 @@ export const EventsQueryTabBody = ({ void; filters?: esFilters.Filter[]; from: number; + hideHeaderChildren?: boolean; indexPattern: IIndexPattern; query?: Query; setAbsoluteRangeDatePicker: SetAbsoluteRangeDatePicker; @@ -60,14 +60,24 @@ export const AlertsByCategory = React.memo( deleteQuery, filters = NO_FILTERS, from, + hideHeaderChildren = false, indexPattern, query = DEFAULT_QUERY, setAbsoluteRangeDatePicker, setQuery, to, }) => { + useEffect(() => { + return () => { + if (deleteQuery) { + deleteQuery({ id: ID }); + } + }; + }, []); + const kibana = useKibana(); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); + const updateDateRangeCallback = useCallback( (min: number, max: number) => { setAbsoluteRangeDatePicker!({ id: 'global', from: min, to: max }); @@ -76,17 +86,11 @@ export const AlertsByCategory = React.memo( ); const alertsCountViewAlertsButton = useMemo( () => ( - - {i18n.VIEW_ALERTS} - + {i18n.VIEW_ALERTS} ), [] ); - const getTitle = useCallback( - (option: MatrixHistogramOption) => i18n.ALERTS_COUNT_BY(option.text), - [] - ); const getSubtitle = useCallback( (totalCount: number) => `${SHOWING}: ${numeral(totalCount).format(defaultNumberFormat)} ${UNIT(totalCount)}`, @@ -96,7 +100,6 @@ export const AlertsByCategory = React.memo( return ( ( queries: [query], filters, })} - headerChildren={alertsCountViewAlertsButton} + headerChildren={hideHeaderChildren ? null : alertsCountViewAlertsButton} id={ID} isAlertsHistogram={true} legendPosition={'right'} @@ -115,7 +118,7 @@ export const AlertsByCategory = React.memo( sourceId="default" stackByOptions={alertsStackByOptions} startDate={from} - title={getTitle} + title={i18n.ALERTS_GRAPH_TITLE} subtitle={getSubtitle} type={HostsType.page} updateDateRange={updateDateRangeCallback} diff --git a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx index 52084c4bfc2804..191b4a25926955 100644 --- a/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/overview/events_by_dataset/index.tsx @@ -6,7 +6,7 @@ import { EuiButton } from '@elastic/eui'; import numeral from '@elastic/numeral'; -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo } from 'react'; import { esFilters, IIndexPattern, Query } from 'src/plugins/data/public'; import styled from 'styled-components'; @@ -66,8 +66,17 @@ export const EventsByDataset = React.memo( setQuery, to, }) => { + useEffect(() => { + return () => { + if (deleteQuery) { + deleteQuery({ id: ID }); + } + }; + }, []); + const kibana = useKibana(); const [defaultNumberFormat] = useUiSetting$(DEFAULT_NUMBER_FORMAT); + const updateDateRangeCallback = useCallback( (min: number, max: number) => { setAbsoluteRangeDatePicker!({ id: 'global', from: min, to: max }); @@ -96,7 +105,6 @@ export const EventsByDataset = React.memo( return ( defaultMessage: 'Alerts count by {groupByField}', }); +export const ALERTS_GRAPH_TITLE = i18n.translate('xpack.siem.overview.alertsGraphTitle', { + defaultMessage: 'Alert detection frequency', +}); + export const EVENTS_COUNT_BY = (groupByField: string) => i18n.translate('xpack.siem.overview.eventsCountByTitle', { values: { groupByField },