[SECURITY] [Timeline] Raw events not displayed (#72387)

* fix nav with no-data

* fix rules action alerts

* fix raw alert event type

* snapshot

* can only use network-only

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Patryk Kopycinski <contact@patrykkopycinski.com>
This commit is contained in:
Xavier Mouligneau 2020-07-20 11:14:50 -04:00 committed by GitHub
parent 66208fb73e
commit a62c62e118
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 65 additions and 67 deletions

View file

@ -195,7 +195,7 @@ exports[`apmUiEnabled 1`] = `
<span <span
id="aria-describedby.addSiemButtonLabel" id="aria-describedby.addSiemButtonLabel"
> >
Centralize security events for interactive investigation in ready-to-go visualizations. Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
</span> </span>
} }
footer={ footer={
@ -212,7 +212,7 @@ exports[`apmUiEnabled 1`] = `
</EuiButton> </EuiButton>
} }
textAlign="left" textAlign="left"
title="Security" title="SIEM + Endpoint Security"
titleSize="xs" titleSize="xs"
/> />
</EuiFlexItem> </EuiFlexItem>
@ -461,7 +461,7 @@ exports[`isNewKibanaInstance 1`] = `
<span <span
id="aria-describedby.addSiemButtonLabel" id="aria-describedby.addSiemButtonLabel"
> >
Centralize security events for interactive investigation in ready-to-go visualizations. Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
</span> </span>
} }
footer={ footer={
@ -478,7 +478,7 @@ exports[`isNewKibanaInstance 1`] = `
</EuiButton> </EuiButton>
} }
textAlign="left" textAlign="left"
title="Security" title="SIEM + Endpoint Security"
titleSize="xs" titleSize="xs"
/> />
</EuiFlexItem> </EuiFlexItem>
@ -758,7 +758,7 @@ exports[`mlEnabled 1`] = `
<span <span
id="aria-describedby.addSiemButtonLabel" id="aria-describedby.addSiemButtonLabel"
> >
Centralize security events for interactive investigation in ready-to-go visualizations. Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
</span> </span>
} }
footer={ footer={
@ -775,7 +775,7 @@ exports[`mlEnabled 1`] = `
</EuiButton> </EuiButton>
} }
textAlign="left" textAlign="left"
title="Security" title="SIEM + Endpoint Security"
titleSize="xs" titleSize="xs"
/> />
</EuiFlexItem> </EuiFlexItem>
@ -1060,7 +1060,7 @@ exports[`render 1`] = `
<span <span
id="aria-describedby.addSiemButtonLabel" id="aria-describedby.addSiemButtonLabel"
> >
Centralize security events for interactive investigation in ready-to-go visualizations. Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.
</span> </span>
} }
footer={ footer={
@ -1077,7 +1077,7 @@ exports[`render 1`] = `
</EuiButton> </EuiButton>
} }
textAlign="left" textAlign="left"
title="Security" title="SIEM + Endpoint Security"
titleSize="xs" titleSize="xs"
/> />
</EuiFlexItem> </EuiFlexItem>

View file

@ -81,12 +81,12 @@ const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => {
const siemData = { const siemData = {
title: intl.formatMessage({ title: intl.formatMessage({
id: 'home.addData.securitySolution.nameTitle', id: 'home.addData.securitySolution.nameTitle',
defaultMessage: 'Security', defaultMessage: 'SIEM + Endpoint Security',
}), }),
description: intl.formatMessage({ description: intl.formatMessage({
id: 'home.addData.securitySolution.nameDescription', id: 'home.addData.securitySolution.nameDescription',
defaultMessage: defaultMessage:
'Centralize security events for interactive investigation in ready-to-go visualizations.', 'Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.',
}), }),
ariaDescribedby: 'aria-describedby.addSiemButtonLabel', ariaDescribedby: 'aria-describedby.addSiemButtonLabel',
}; };

View file

@ -63,26 +63,19 @@ export const HeaderGlobal = React.memo<HeaderGlobalProps>(({ hideDetectionEngine
<EuiFlexGroup alignItems="center" responsive={false}> <EuiFlexGroup alignItems="center" responsive={false}>
<FlexItem grow={false}> <FlexItem grow={false}>
<LinkAnchor onClick={goToOverview} href={getAppOverviewUrl(search)}> <LinkAnchor onClick={goToOverview} href={getAppOverviewUrl(search)}>
<EuiIcon aria-label={i18n.SIEM} type="logoSecurity" size="l" /> <EuiIcon aria-label={i18n.SECURITY_SOLUTION} type="logoSecurity" size="l" />
</LinkAnchor> </LinkAnchor>
</FlexItem> </FlexItem>
<FlexItem component="nav"> <FlexItem component="nav">
{indicesExist ? ( <SiemNavigation
<SiemNavigation display="condensed"
display="condensed" navTabs={
navTabs={ hideDetectionEngine
hideDetectionEngine ? pickBy((_, key) => key !== SecurityPageName.detections, navTabs)
? pickBy((_, key) => key !== SecurityPageName.detections, navTabs) : navTabs
: navTabs }
} />
/>
) : (
<SiemNavigation
display="condensed"
navTabs={pickBy((_, key) => key === SecurityPageName.overview, navTabs)}
/>
)}
</FlexItem> </FlexItem>
</EuiFlexGroup> </EuiFlexGroup>
</FlexItem> </FlexItem>

View file

@ -6,9 +6,12 @@
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
export const SIEM = i18n.translate('xpack.securitySolution.headerGlobal.siem', { export const SECURITY_SOLUTION = i18n.translate(
defaultMessage: 'SIEM', 'xpack.securitySolution.headerGlobal.securitySolution',
}); {
defaultMessage: 'Security solution',
}
);
export const BUTTON_ADD_DATA = i18n.translate('xpack.securitySolution.headerGlobal.buttonAddData', { export const BUTTON_ADD_DATA = i18n.translate('xpack.securitySolution.headerGlobal.buttonAddData', {
defaultMessage: 'Add data', defaultMessage: 'Add data',

View file

@ -7,6 +7,7 @@
import { act, renderHook } from '@testing-library/react-hooks'; import { act, renderHook } from '@testing-library/react-hooks';
import { useWithSource, indicesExistOrDataTemporarilyUnavailable } from '.'; import { useWithSource, indicesExistOrDataTemporarilyUnavailable } from '.';
import { NO_ALERT_INDEX } from '../../../../common/constants';
import { mockBrowserFields, mockIndexFields, mocksSource } from './mock'; import { mockBrowserFields, mockIndexFields, mocksSource } from './mock';
jest.mock('../../lib/kibana'); jest.mock('../../lib/kibana');
@ -79,6 +80,17 @@ describe('Index Fields & Browser Fields', () => {
}); });
}); });
test('Make sure we are not querying for NO_ALERT_INDEX and it is not includes in the index pattern', async () => {
const { result, waitForNextUpdate } = renderHook(() =>
useWithSource('default', [NO_ALERT_INDEX])
);
await waitForNextUpdate();
return expect(result.current.indexPattern.title).toEqual(
'apm-*-transaction*,auditbeat-*,endgame-*,filebeat-*,logs-*,packetbeat-*,winlogbeat-*'
);
});
describe('indicesExistOrDataTemporarilyUnavailable', () => { describe('indicesExistOrDataTemporarilyUnavailable', () => {
test('it returns true when undefined', () => { test('it returns true when undefined', () => {
let undefVar; let undefVar;

View file

@ -11,7 +11,7 @@ import { useEffect, useMemo, useState } from 'react';
import memoizeOne from 'memoize-one'; import memoizeOne from 'memoize-one';
import { IIndexPattern } from 'src/plugins/data/public'; import { IIndexPattern } from 'src/plugins/data/public';
import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { DEFAULT_INDEX_KEY, NO_ALERT_INDEX } from '../../../../common/constants';
import { useUiSetting$ } from '../../lib/kibana'; import { useUiSetting$ } from '../../lib/kibana';
import { IndexField, SourceQuery } from '../../../graphql/types'; import { IndexField, SourceQuery } from '../../../graphql/types';
@ -126,8 +126,9 @@ export const useWithSource = (
) => { ) => {
const [configIndex] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY); const [configIndex] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY);
const defaultIndex = useMemo<string[]>(() => { const defaultIndex = useMemo<string[]>(() => {
if (indexToAdd != null && !isEmpty(indexToAdd)) { const filterIndexAdd = (indexToAdd ?? []).filter((item) => item !== NO_ALERT_INDEX);
return onlyCheckIndexToAdd ? indexToAdd : [...configIndex, ...indexToAdd]; if (!isEmpty(filterIndexAdd)) {
return onlyCheckIndexToAdd ? filterIndexAdd : [...configIndex, ...filterIndexAdd];
} }
return configIndex; return configIndex;
}, [configIndex, indexToAdd, onlyCheckIndexToAdd]); }, [configIndex, indexToAdd, onlyCheckIndexToAdd]);
@ -138,7 +139,7 @@ export const useWithSource = (
errorMessage: null, errorMessage: null,
indexPattern: getIndexFields(defaultIndex.join(), []), indexPattern: getIndexFields(defaultIndex.join(), []),
indicesExist: indicesExistOrDataTemporarilyUnavailable(undefined), indicesExist: indicesExistOrDataTemporarilyUnavailable(undefined),
loading: false, loading: true,
}); });
const apolloClient = useApolloClient(); const apolloClient = useApolloClient();
@ -155,7 +156,7 @@ export const useWithSource = (
try { try {
const result = await apolloClient.query<SourceQuery.Query, SourceQuery.Variables>({ const result = await apolloClient.query<SourceQuery.Query, SourceQuery.Variables>({
query: sourceQuery, query: sourceQuery,
fetchPolicy: 'cache-first', fetchPolicy: 'network-only',
variables: { variables: {
sourceId, sourceId,
defaultIndex, defaultIndex,

View file

@ -48,7 +48,6 @@ const PrePackagedRulesPromptComponent: React.FC<PrePackagedRulesPromptProps> = (
return ( return (
<EmptyPrompt <EmptyPrompt
iconType="securityAnalyticsApp"
title={<h2>{i18n.PRE_BUILT_TITLE}</h2>} title={<h2>{i18n.PRE_BUILT_TITLE}</h2>}
body={<p>{i18n.PRE_BUILT_MSG}</p>} body={<p>{i18n.PRE_BUILT_MSG}</p>}
actions={ actions={

View file

@ -33,7 +33,6 @@ import { useKibana } from '../../../../common/lib/kibana';
import { getSchema } from './schema'; import { getSchema } from './schema';
import * as I18n from './translations'; import * as I18n from './translations';
import { APP_ID } from '../../../../../common/constants'; import { APP_ID } from '../../../../../common/constants';
import { SecurityPageName } from '../../../../app/types';
interface StepRuleActionsProps extends RuleStepProps { interface StepRuleActionsProps extends RuleStepProps {
defaultValues?: ActionsStepRule | null; defaultValues?: ActionsStepRule | null;
@ -86,16 +85,13 @@ const StepRuleActionsComponent: FC<StepRuleActionsProps> = ({
}); });
const { submit } = form; const { submit } = form;
// TO DO need to make sure that logic is still valid const kibanaAbsoluteUrl = useMemo(
const kibanaAbsoluteUrl = useMemo(() => { () =>
const url = application.getUrlForApp(`${APP_ID}:${SecurityPageName.detections}`, { application.getUrlForApp(`${APP_ID}`, {
absolute: true, absolute: true,
}); }),
if (url != null && url.includes('app/security/alerts')) { [application]
return url.replace('app/security/alerts', 'app/security'); );
}
return url;
}, [application]);
const onSubmit = useCallback( const onSubmit = useCallback(
async (enabled: boolean) => { async (enabled: boolean) => {

View file

@ -70,7 +70,7 @@ export const useFetchIndexPatterns = (defaultIndices: string[] = []): Return =>
apolloClient apolloClient
.query<SourceQuery.Query, SourceQuery.Variables>({ .query<SourceQuery.Query, SourceQuery.Variables>({
query: sourceQuery, query: sourceQuery,
fetchPolicy: 'cache-first', fetchPolicy: 'network-only',
variables: { variables: {
sourceId: 'default', sourceId: 'default',
defaultIndex: indices, defaultIndex: indices,

View file

@ -138,10 +138,9 @@ export const StatefulFieldsBrowserComponent: React.FC<FieldBrowserProps> = ({
setShow(false); setShow(false);
}, []); }, []);
// only merge in the default category if the field browser is visible // only merge in the default category if the field browser is visible
const browserFieldsWithDefaultCategory = useMemo( const browserFieldsWithDefaultCategory = useMemo(() => {
() => (show ? mergeBrowserFieldsWithDefaultCategory(browserFields) : {}), return show ? mergeBrowserFieldsWithDefaultCategory(browserFields) : {};
[show, browserFields] }, [show, browserFields]);
);
return ( return (
<FieldsBrowserButtonContainer data-test-subj="fields-browser-button-container"> <FieldsBrowserButtonContainer data-test-subj="fields-browser-button-container">

View file

@ -78,8 +78,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
serializedQuery: convertKueryToElasticSearchQuery(expression, indexPattern), serializedQuery: convertKueryToElasticSearchQuery(expression, indexPattern),
}, },
}), }),
// eslint-disable-next-line react-hooks/exhaustive-deps [applyKqlFilterQuery, indexPattern, timelineId]
[indexPattern, timelineId]
); );
const setFilterQueryDraftFromKueryExpression = useCallback( const setFilterQueryDraftFromKueryExpression = useCallback(
@ -91,8 +90,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
expression, expression,
}, },
}), }),
// eslint-disable-next-line react-hooks/exhaustive-deps [timelineId, setKqlFilterQueryDraft]
[timelineId]
); );
const setFiltersInTimeline = useCallback( const setFiltersInTimeline = useCallback(
@ -101,8 +99,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
id: timelineId, id: timelineId,
filters: newFilters, filters: newFilters,
}), }),
// eslint-disable-next-line react-hooks/exhaustive-deps [timelineId, setFilters]
[timelineId]
); );
const setSavedQueryInTimeline = useCallback( const setSavedQueryInTimeline = useCallback(
@ -111,8 +108,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
id: timelineId, id: timelineId,
savedQueryId: newSavedQueryId, savedQueryId: newSavedQueryId,
}), }),
// eslint-disable-next-line react-hooks/exhaustive-deps [timelineId, setSavedQueryId]
[timelineId]
); );
const handleUpdateEventType = useCallback( const handleUpdateEventType = useCallback(
@ -121,8 +117,7 @@ const StatefulSearchOrFilterComponent = React.memo<Props>(
id: timelineId, id: timelineId,
eventType: newEventType, eventType: newEventType,
}), }),
// eslint-disable-next-line react-hooks/exhaustive-deps [timelineId, updateEventType]
[timelineId]
); );
return ( return (

View file

@ -9,13 +9,13 @@ import { getNotificationResultsLink } from './utils';
describe('utils', () => { describe('utils', () => {
it('getNotificationResultsLink', () => { it('getNotificationResultsLink', () => {
const resultLink = getNotificationResultsLink({ const resultLink = getNotificationResultsLink({
kibanaSiemAppUrl: 'http://localhost:5601/app/siem', kibanaSiemAppUrl: 'http://localhost:5601/app/security',
id: 'notification-id', id: 'notification-id',
from: '00000', from: '00000',
to: '1111', to: '1111',
}); });
expect(resultLink).toEqual( expect(resultLink).toEqual(
`http://localhost:5601/app/siem#/detections/rules/id/notification-id?timerange=(global:(linkTo:!(timeline),timerange:(from:00000,kind:absolute,to:1111)),timeline:(linkTo:!(global),timerange:(from:00000,kind:absolute,to:1111)))` `http://localhost:5601/app/security/detections/rules/id/notification-id?timerange=(global:(linkTo:!(timeline),timerange:(from:00000,kind:absolute,to:1111)),timeline:(linkTo:!(global),timerange:(from:00000,kind:absolute,to:1111)))`
); );
}); });
}); });

View file

@ -4,8 +4,10 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import { APP_PATH } from '../../../../common/constants';
export const getNotificationResultsLink = ({ export const getNotificationResultsLink = ({
kibanaSiemAppUrl = '/app/siem', kibanaSiemAppUrl = APP_PATH,
id, id,
from, from,
to, to,
@ -17,5 +19,5 @@ export const getNotificationResultsLink = ({
}) => { }) => {
if (from == null || to == null) return ''; if (from == null || to == null) return '';
return `${kibanaSiemAppUrl}#/detections/rules/id/${id}?timerange=(global:(linkTo:!(timeline),timerange:(from:${from},kind:absolute,to:${to})),timeline:(linkTo:!(global),timerange:(from:${from},kind:absolute,to:${to})))`; return `${kibanaSiemAppUrl}/detections/rules/id/${id}?timerange=(global:(linkTo:!(timeline),timerange:(from:${from},kind:absolute,to:${to})),timeline:(linkTo:!(global),timerange:(from:${from},kind:absolute,to:${to})))`;
}; };

View file

@ -14067,7 +14067,6 @@
"xpack.securitySolution.header.editableTitle.editButtonAria": "クリックすると {title} を編集できます", "xpack.securitySolution.header.editableTitle.editButtonAria": "クリックすると {title} を編集できます",
"xpack.securitySolution.header.editableTitle.save": "保存", "xpack.securitySolution.header.editableTitle.save": "保存",
"xpack.securitySolution.headerGlobal.buttonAddData": "データの追加", "xpack.securitySolution.headerGlobal.buttonAddData": "データの追加",
"xpack.securitySolution.headerGlobal.siem": "Security",
"xpack.securitySolution.headerPage.pageSubtitle": "前回のイベント: {beat}", "xpack.securitySolution.headerPage.pageSubtitle": "前回のイベント: {beat}",
"xpack.securitySolution.hooks.useAddToTimeline.addedFieldMessage": "{fieldOrValue}をタイムラインに追加しました", "xpack.securitySolution.hooks.useAddToTimeline.addedFieldMessage": "{fieldOrValue}をタイムラインに追加しました",
"xpack.securitySolution.host.details.architectureLabel": "アーキテクチャー", "xpack.securitySolution.host.details.architectureLabel": "アーキテクチャー",

View file

@ -14073,7 +14073,6 @@
"xpack.securitySolution.header.editableTitle.editButtonAria": "通过单击,可以编辑 {title}", "xpack.securitySolution.header.editableTitle.editButtonAria": "通过单击,可以编辑 {title}",
"xpack.securitySolution.header.editableTitle.save": "保存", "xpack.securitySolution.header.editableTitle.save": "保存",
"xpack.securitySolution.headerGlobal.buttonAddData": "添加数据", "xpack.securitySolution.headerGlobal.buttonAddData": "添加数据",
"xpack.securitySolution.headerGlobal.siem": "Security",
"xpack.securitySolution.headerPage.pageSubtitle": "最后事件:{beat}", "xpack.securitySolution.headerPage.pageSubtitle": "最后事件:{beat}",
"xpack.securitySolution.hooks.useAddToTimeline.addedFieldMessage": "已将 {fieldOrValue} 添加到时间线", "xpack.securitySolution.hooks.useAddToTimeline.addedFieldMessage": "已将 {fieldOrValue} 添加到时间线",
"xpack.securitySolution.host.details.architectureLabel": "架构", "xpack.securitySolution.host.details.architectureLabel": "架构",