mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* generic histogram container * generic histogram container * rename params * fix inspect * fix update with timerange * clean up props * send stackByField to server side * fix inspect button * helper node xavier * fix DNS histogram * fix DNS query params * move utils for fetch data into containers * cleanup graphql template on client side * rename grqphql data * i18n * fix type * fix i18n * fix i18n * fix subtitle * fix subtitle * fix i18n * fix for reviews * fix types * remove unused test * fix integration Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
7038ce28bf
commit
f95f3f39b9
80 changed files with 1423 additions and 1625 deletions
|
@ -3,57 +3,74 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { noop } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
|
||||
import React, { useEffect, useCallback } from 'react';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { manageQuery } from '../page/manage_query';
|
||||
import { AlertsOverTimeHistogram } from '../page/hosts/alerts_over_time';
|
||||
import { AlertsComponentsQueryProps } from './types';
|
||||
import { AlertsOverTimeQuery } from '../../containers/alerts/alerts_over_time';
|
||||
import { hostsModel } from '../../store/model';
|
||||
import { AlertsTable } from './alerts_table';
|
||||
|
||||
const AlertsOverTimeManage = manageQuery(AlertsOverTimeHistogram);
|
||||
import { AlertsComponentsQueryProps } from './types';
|
||||
import { AlertsTable } from './alerts_table';
|
||||
import * as i18n from './translations';
|
||||
import { MatrixHistogramOption } from '../matrix_histogram/types';
|
||||
import { MatrixHistogramContainer } from '../../containers/matrix_histogram';
|
||||
import { MatrixHistogramGqlQuery } from '../../containers/matrix_histogram/index.gql_query';
|
||||
const ID = 'alertsOverTimeQuery';
|
||||
const alertsStackByOptions: MatrixHistogramOption[] = [
|
||||
{
|
||||
text: i18n.ALERTS_STACK_BY_MODULE,
|
||||
value: 'event.module',
|
||||
},
|
||||
];
|
||||
const dataKey = 'AlertsHistogram';
|
||||
|
||||
export const AlertsView = ({
|
||||
defaultFilters,
|
||||
deleteQuery,
|
||||
endDate,
|
||||
filterQuery,
|
||||
pageFilters,
|
||||
skip,
|
||||
setQuery,
|
||||
skip,
|
||||
startDate,
|
||||
type,
|
||||
updateDateRange = noop,
|
||||
}: AlertsComponentsQueryProps) => (
|
||||
<>
|
||||
<AlertsOverTimeQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
type={hostsModel.HostsType.page}
|
||||
>
|
||||
{({ alertsOverTime, loading, id, inspect, refetch, totalCount }) => (
|
||||
<AlertsOverTimeManage
|
||||
data={alertsOverTime!}
|
||||
endDate={endDate}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
loading={loading}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
startDate={startDate}
|
||||
totalCount={totalCount}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
)}
|
||||
</AlertsOverTimeQuery>
|
||||
<EuiSpacer size="l" />
|
||||
<AlertsTable endDate={endDate} startDate={startDate} pageFilters={pageFilters} />
|
||||
</>
|
||||
);
|
||||
}: AlertsComponentsQueryProps) => {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (deleteQuery) {
|
||||
deleteQuery({ id: ID });
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const getSubtitle = useCallback(
|
||||
(totalCount: number) => `${i18n.SHOWING}: ${totalCount} ${i18n.UNIT(totalCount)}`,
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MatrixHistogramContainer
|
||||
dataKey={dataKey}
|
||||
deleteQuery={deleteQuery}
|
||||
defaultStackByOption={alertsStackByOptions[0]}
|
||||
endDate={endDate}
|
||||
errorMessage={i18n.ERROR_FETCHING_ALERTS_DATA}
|
||||
filterQuery={filterQuery}
|
||||
id={ID}
|
||||
isAlertsHistogram={true}
|
||||
query={MatrixHistogramGqlQuery}
|
||||
setQuery={setQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
stackByOptions={alertsStackByOptions}
|
||||
startDate={startDate}
|
||||
subtitle={getSubtitle}
|
||||
title={i18n.ALERTS_DOCUMENT_TYPE}
|
||||
type={type}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
<EuiSpacer size="l" />
|
||||
<AlertsTable endDate={endDate} startDate={startDate} pageFilters={pageFilters} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
AlertsView.displayName = 'AlertsView';
|
||||
|
|
|
@ -6,14 +6,38 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const ALERTS_DOCUMENT_TYPE = i18n.translate('xpack.siem.hosts.alertsDocumentType', {
|
||||
export const ALERTS_DOCUMENT_TYPE = i18n.translate('xpack.siem.alertsView.alertsDocumentType', {
|
||||
defaultMessage: 'Alerts',
|
||||
});
|
||||
|
||||
export const TOTAL_COUNT_OF_ALERTS = i18n.translate('xpack.siem.hosts.totalCountOfAlerts', {
|
||||
export const TOTAL_COUNT_OF_ALERTS = i18n.translate('xpack.siem.alertsView.totalCountOfAlerts', {
|
||||
defaultMessage: 'alerts match the search criteria',
|
||||
});
|
||||
|
||||
export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.hosts.alertsDocumentType', {
|
||||
export const ALERTS_TABLE_TITLE = i18n.translate('xpack.siem.alertsView.alertsDocumentType', {
|
||||
defaultMessage: 'Alerts',
|
||||
});
|
||||
|
||||
export const ALERTS_STACK_BY_MODULE = i18n.translate(
|
||||
'xpack.siem.alertsView.alertsStackByOptions.module',
|
||||
{
|
||||
defaultMessage: 'module',
|
||||
}
|
||||
);
|
||||
|
||||
export const SHOWING = i18n.translate('xpack.siem.alertsView.showing', {
|
||||
defaultMessage: 'Showing',
|
||||
});
|
||||
|
||||
export const UNIT = (totalCount: number) =>
|
||||
i18n.translate('xpack.siem.alertsView.unit', {
|
||||
values: { totalCount },
|
||||
defaultMessage: `{totalCount, plural, =1 {alert} other {alerts}}`,
|
||||
});
|
||||
|
||||
export const ERROR_FETCHING_ALERTS_DATA = i18n.translate(
|
||||
'xpack.siem.alertsView.errorFetchingAlertsData',
|
||||
{
|
||||
defaultMessage: 'Failed to query alerts data',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { esFilters } from '../../../../../../../src/plugins/data/common';
|
||||
import { HostsComponentsQueryProps } from '../../pages/hosts/navigation/types';
|
||||
import { NetworkComponentQueryProps } from '../../pages/network/navigation/types';
|
||||
import { MatrixHistogramOption } from '../matrix_histogram/types';
|
||||
|
||||
type CommonQueryProps = HostsComponentsQueryProps | NetworkComponentQueryProps;
|
||||
export interface AlertsComponentsQueryProps
|
||||
|
@ -22,5 +23,7 @@ export interface AlertsComponentsQueryProps
|
|||
| 'updateDateRange'
|
||||
> {
|
||||
pageFilters: esFilters.Filter[];
|
||||
stackByOptions?: MatrixHistogramOption[];
|
||||
defaultFilters?: esFilters.Filter[];
|
||||
defaultStackByOption?: MatrixHistogramOption;
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { MatrixHistogramBasicProps } from '../matrix_histogram/types';
|
||||
import { MatrixOverTimeHistogramData } from '../../graphql/types';
|
||||
import { MatrixHistogram } from '../matrix_histogram';
|
||||
import * as i18n from './translation';
|
||||
|
||||
export const AnomaliesOverTimeHistogram = (
|
||||
props: MatrixHistogramBasicProps<MatrixOverTimeHistogramData>
|
||||
) => {
|
||||
const dataKey = 'anomaliesOverTime';
|
||||
const { totalCount } = props;
|
||||
const subtitle = `${i18n.SHOWING}: ${totalCount.toLocaleString()} ${i18n.UNIT(totalCount)}`;
|
||||
const { ...matrixOverTimeProps } = props;
|
||||
|
||||
return (
|
||||
<MatrixHistogram
|
||||
title={i18n.ANOMALIES_COUNT_FREQUENCY_BY_ACTION}
|
||||
subtitle={subtitle}
|
||||
dataKey={dataKey}
|
||||
{...matrixOverTimeProps}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const ANOMALIES_COUNT_FREQUENCY_BY_ACTION = i18n.translate(
|
||||
'xpack.siem.anomaliesOverTime.anomaliesCountFrequencyByJobTile',
|
||||
{
|
||||
defaultMessage: 'Anomalies count by job',
|
||||
}
|
||||
);
|
||||
|
||||
export const SHOWING = i18n.translate('xpack.siem.anomaliesOverTime.showing', {
|
||||
defaultMessage: 'Showing',
|
||||
});
|
||||
|
||||
export const UNIT = (totalCount: number) =>
|
||||
i18n.translate('xpack.siem.anomaliesOverTime.unit', {
|
||||
values: { totalCount },
|
||||
defaultMessage: `{totalCount, plural, =1 {anomaly} other {anomalies}}`,
|
||||
});
|
|
@ -14,6 +14,7 @@ import {
|
|||
ScaleType,
|
||||
SettingsSpecProps,
|
||||
TickFormatter,
|
||||
Position,
|
||||
} from '@elastic/charts';
|
||||
import styled from 'styled-components';
|
||||
import { useUiSetting } from '../../lib/kibana';
|
||||
|
@ -35,6 +36,7 @@ export interface ChartData {
|
|||
|
||||
export interface ChartSeriesConfigs {
|
||||
customHeight?: number;
|
||||
customSeriesColors?: string[];
|
||||
series?: {
|
||||
xScaleType?: ScaleType | undefined;
|
||||
yScaleType?: ScaleType | undefined;
|
||||
|
@ -105,6 +107,7 @@ export const chartDefaultSettings = {
|
|||
showLegend: false,
|
||||
showLegendDisplayValue: false,
|
||||
debug: false,
|
||||
legendPosition: Position.Bottom,
|
||||
};
|
||||
|
||||
export const getChartHeight = (customHeight?: number, autoSizerHeight?: number): string => {
|
||||
|
|
|
@ -10,6 +10,7 @@ import { shallow } from 'enzyme';
|
|||
import React from 'react';
|
||||
|
||||
import { MatrixHistogram } from '.';
|
||||
import { MatrixHistogramGqlQuery as mockQuery } from '../../containers/matrix_histogram/index.gql_query';
|
||||
|
||||
jest.mock('../../lib/kibana');
|
||||
|
||||
|
@ -31,18 +32,27 @@ jest.mock('../charts/barchart', () => {
|
|||
};
|
||||
});
|
||||
|
||||
describe('Load More Events Table Component', () => {
|
||||
describe('Matrix Histogram Component', () => {
|
||||
const mockMatrixOverTimeHistogramProps = {
|
||||
data: [],
|
||||
dataKey: 'mockDataKey',
|
||||
defaultIndex: ['defaultIndex'],
|
||||
defaultStackByOption: { text: 'text', value: 'value' },
|
||||
endDate: new Date('2019-07-18T20:00:00.000Z').valueOf(),
|
||||
errorMessage: 'error',
|
||||
id: 'mockId',
|
||||
loading: true,
|
||||
updateDateRange: () => {},
|
||||
isInspected: false,
|
||||
isPtrIncluded: false,
|
||||
query: mockQuery,
|
||||
setQuery: jest.fn(),
|
||||
skip: false,
|
||||
sourceId: 'default',
|
||||
stackByField: 'mockStackByField',
|
||||
stackByOptions: [{ text: 'text', value: 'value' }],
|
||||
startDate: new Date('2019-07-18T19:00: 00.000Z').valueOf(),
|
||||
subtitle: 'mockSubtitle',
|
||||
totalCount: -1,
|
||||
title: 'mockTitle',
|
||||
updateDateRange: jest.fn(),
|
||||
};
|
||||
describe('rendering', () => {
|
||||
test('it renders EuiLoadingContent on initialLoad', () => {
|
||||
|
|
|
@ -4,38 +4,65 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
|
||||
import darkTheme from '@elastic/eui/dist/eui_theme_dark.json';
|
||||
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
|
||||
import { EuiLoadingContent } from '@elastic/eui';
|
||||
import { EuiLoadingContent, EuiSelect } from '@elastic/eui';
|
||||
import { noop } from 'lodash/fp';
|
||||
import * as i18n from './translations';
|
||||
import { BarChart } from '../charts/barchart';
|
||||
import { HeaderSection } from '../header_section';
|
||||
import { ChartSeriesData } from '../charts/common';
|
||||
import { DEFAULT_DARK_MODE } from '../../../common/constants';
|
||||
import { useUiSetting$ } from '../../lib/kibana';
|
||||
import { Loader } from '../loader';
|
||||
import { Panel } from '../panel';
|
||||
import { getBarchartConfigs, getCustomChartData } from '../../components/matrix_histogram/utils';
|
||||
import { useQuery } from '../../containers/matrix_histogram/utils';
|
||||
import {
|
||||
MatrixHistogramProps,
|
||||
MatrixHistogramOption,
|
||||
HistogramAggregation,
|
||||
MatrixHistogramQueryProps,
|
||||
} from './types';
|
||||
import { generateTablePaginationOptions } from '../paginated_table/helpers';
|
||||
import { ChartSeriesData } from '../charts/common';
|
||||
import { InspectButtonContainer } from '../inspect';
|
||||
import { getBarchartConfigs, getCustomChartData } from './utils';
|
||||
import { MatrixHistogramProps, MatrixHistogramDataTypes } from './types';
|
||||
|
||||
export const MatrixHistogramComponent: React.FC<MatrixHistogramProps<MatrixHistogramDataTypes>> = ({
|
||||
data,
|
||||
export const MatrixHistogramComponent: React.FC<MatrixHistogramProps &
|
||||
MatrixHistogramQueryProps> = ({
|
||||
activePage,
|
||||
|
||||
dataKey,
|
||||
defaultStackByOption,
|
||||
endDate,
|
||||
errorMessage,
|
||||
filterQuery,
|
||||
hideHistogramIfEmpty = false,
|
||||
id,
|
||||
loading,
|
||||
isAlertsHistogram,
|
||||
isAnomaliesHistogram,
|
||||
isAuthenticationsHistogram,
|
||||
isDNSHistogram,
|
||||
isEventsType,
|
||||
isPtrIncluded,
|
||||
isInspected,
|
||||
legendPosition,
|
||||
limit,
|
||||
mapping,
|
||||
query,
|
||||
scaleType = ScaleType.Time,
|
||||
setQuery,
|
||||
showLegend,
|
||||
skip,
|
||||
stackByOptions,
|
||||
startDate,
|
||||
subtitle,
|
||||
title,
|
||||
totalCount,
|
||||
updateDateRange,
|
||||
yTickFormatter,
|
||||
showLegend,
|
||||
sort,
|
||||
}) => {
|
||||
const barchartConfigs = getBarchartConfigs({
|
||||
from: startDate,
|
||||
|
@ -44,24 +71,117 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps<MatrixHisto
|
|||
scaleType,
|
||||
yTickFormatter,
|
||||
showLegend,
|
||||
legendPosition,
|
||||
});
|
||||
const [showInspect, setShowInspect] = useState(false);
|
||||
const [darkMode] = useUiSetting$<boolean>(DEFAULT_DARK_MODE);
|
||||
const [loadingInitial, setLoadingInitial] = useState(false);
|
||||
|
||||
const barChartData: ChartSeriesData[] = getCustomChartData(data, mapping);
|
||||
const handleOnMouseEnter = useCallback(() => {
|
||||
if (!showInspect) {
|
||||
setShowInspect(true);
|
||||
}
|
||||
}, [showInspect, setShowInspect]);
|
||||
const handleOnMouseLeave = useCallback(() => {
|
||||
if (showInspect) {
|
||||
setShowInspect(false);
|
||||
}
|
||||
}, [showInspect, setShowInspect]);
|
||||
|
||||
const [selectedStackByOption, setSelectedStackByOption] = useState<MatrixHistogramOption>(
|
||||
defaultStackByOption
|
||||
);
|
||||
const [subtitleWithCounts, setSubtitle] = useState<string>('');
|
||||
const [hideHistogram, setHideHistogram] = useState<boolean>(hideHistogramIfEmpty);
|
||||
const [barChartData, setBarChartData] = useState<ChartSeriesData[] | null>(null);
|
||||
const setSelectedChartOptionCallback = useCallback(
|
||||
(event: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
setSelectedStackByOption(
|
||||
stackByOptions?.find(co => co.value === event.target.value) ?? defaultStackByOption
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
const getPagination = () =>
|
||||
activePage != null && limit != null
|
||||
? generateTablePaginationOptions(activePage, limit)
|
||||
: undefined;
|
||||
|
||||
const { data, loading, inspect, totalCount, refetch = noop } = useQuery<{}, HistogramAggregation>(
|
||||
{
|
||||
dataKey,
|
||||
endDate,
|
||||
errorMessage,
|
||||
filterQuery,
|
||||
query,
|
||||
skip,
|
||||
startDate,
|
||||
sort,
|
||||
title,
|
||||
isAlertsHistogram,
|
||||
isAnomaliesHistogram,
|
||||
isAuthenticationsHistogram,
|
||||
isDNSHistogram,
|
||||
isEventsType,
|
||||
isInspected,
|
||||
isPtrIncluded,
|
||||
pagination: useMemo(() => getPagination(), [activePage, limit]),
|
||||
stackByField: selectedStackByOption.value,
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (totalCount >= 0 && loadingInitial) {
|
||||
setLoadingInitial(false);
|
||||
if (subtitle != null)
|
||||
setSubtitle(typeof subtitle === 'function' ? subtitle(totalCount) : subtitle);
|
||||
|
||||
if (totalCount <= 0) {
|
||||
if (hideHistogramIfEmpty) {
|
||||
setHideHistogram(true);
|
||||
} else {
|
||||
setHideHistogram(false);
|
||||
}
|
||||
} else {
|
||||
setHideHistogram(false);
|
||||
}
|
||||
}, [loading, loadingInitial, totalCount]);
|
||||
|
||||
return (
|
||||
<InspectButtonContainer show={!loadingInitial}>
|
||||
<Panel data-test-subj={`${dataKey}Panel`} loading={loading}>
|
||||
<HeaderSection id={id} title={title} subtitle={!loadingInitial && subtitle} />
|
||||
setBarChartData(getCustomChartData(data, mapping));
|
||||
|
||||
{loadingInitial ? (
|
||||
setQuery({ id, inspect, loading, refetch });
|
||||
}, [
|
||||
subtitle,
|
||||
setSubtitle,
|
||||
setHideHistogram,
|
||||
setBarChartData,
|
||||
setQuery,
|
||||
hideHistogramIfEmpty,
|
||||
totalCount,
|
||||
isInspected,
|
||||
loading,
|
||||
data,
|
||||
]);
|
||||
|
||||
return !hideHistogram ? (
|
||||
<InspectButtonContainer show={showInspect}>
|
||||
<Panel
|
||||
data-test-subj={`${id}Panel`}
|
||||
loading={loading}
|
||||
onMouseEnter={handleOnMouseEnter}
|
||||
onMouseLeave={handleOnMouseLeave}
|
||||
>
|
||||
<HeaderSection
|
||||
id={id}
|
||||
title={title}
|
||||
subtitle={!loading && (totalCount >= 0 ? subtitleWithCounts : null)}
|
||||
>
|
||||
{stackByOptions && (
|
||||
<EuiSelect
|
||||
onChange={setSelectedChartOptionCallback}
|
||||
options={stackByOptions}
|
||||
prepend={i18n.STACK_BY}
|
||||
value={selectedStackByOption?.value}
|
||||
/>
|
||||
)}
|
||||
</HeaderSection>
|
||||
{loading ? (
|
||||
<EuiLoadingContent data-test-subj="initialLoadingPanelMatrixOverTime" lines={10} />
|
||||
) : (
|
||||
<>
|
||||
|
@ -80,7 +200,7 @@ export const MatrixHistogramComponent: React.FC<MatrixHistogramProps<MatrixHisto
|
|||
)}
|
||||
</Panel>
|
||||
</InspectButtonContainer>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export const MatrixHistogram = React.memo(MatrixHistogramComponent);
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const NETWORK_DNS_HISTOGRAM = i18n.translate('xpack.siem.DNS.histogramTitle', {
|
||||
defaultMessage: 'Top DNS domains bytes count',
|
||||
});
|
||||
export const STACK_BY = i18n.translate(
|
||||
'xpack.siem.components.histogram.stackByOptions.stackByLabel',
|
||||
{
|
||||
defaultMessage: 'Stack by',
|
||||
}
|
||||
);
|
|
@ -4,29 +4,119 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
import { MatrixOverTimeHistogramData, MatrixOverOrdinalHistogramData } from '../../graphql/types';
|
||||
import { AuthMatrixDataFields } from '../page/hosts/authentications_over_time/utils';
|
||||
import { ScaleType, Position } from '@elastic/charts';
|
||||
import { SetStateAction } from 'react';
|
||||
import { DocumentNode } from 'graphql';
|
||||
import {
|
||||
MatrixOverTimeHistogramData,
|
||||
MatrixOverOrdinalHistogramData,
|
||||
NetworkDnsSortField,
|
||||
PaginationInputPaginated,
|
||||
} from '../../graphql/types';
|
||||
import { UpdateDateRange } from '../charts/common';
|
||||
import { ESQuery } from '../../../common/typed_json';
|
||||
import { SetQuery } from '../../pages/hosts/navigation/types';
|
||||
|
||||
export type MatrixHistogramDataTypes = MatrixOverTimeHistogramData | MatrixOverOrdinalHistogramData;
|
||||
export type MatrixHistogramMappingTypes = AuthMatrixDataFields;
|
||||
export interface MatrixHistogramBasicProps<T> {
|
||||
data: T[];
|
||||
export type MatrixHistogramMappingTypes = Record<
|
||||
string,
|
||||
{ key: string; value: null; color?: string | undefined }
|
||||
>;
|
||||
export interface MatrixHistogramOption {
|
||||
text: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type GetSubTitle = (count: number) => string;
|
||||
export interface MatrixHistogramBasicProps {
|
||||
defaultIndex: string[];
|
||||
defaultStackByOption: MatrixHistogramOption;
|
||||
endDate: number;
|
||||
hideHistogramIfEmpty?: boolean;
|
||||
id: string;
|
||||
loading: boolean;
|
||||
mapping?: MatrixHistogramMappingTypes;
|
||||
setQuery: SetQuery;
|
||||
sourceId: string;
|
||||
startDate: number;
|
||||
totalCount: number;
|
||||
stackByOptions: MatrixHistogramOption[];
|
||||
subtitle?: string | GetSubTitle;
|
||||
title?: string;
|
||||
updateDateRange: UpdateDateRange;
|
||||
}
|
||||
|
||||
export interface MatrixHistogramProps<T> extends MatrixHistogramBasicProps<T> {
|
||||
dataKey?: string;
|
||||
export interface MatrixHistogramQueryProps {
|
||||
activePage?: number;
|
||||
dataKey: string;
|
||||
endDate: number;
|
||||
errorMessage: string;
|
||||
filterQuery?: ESQuery | string | undefined;
|
||||
limit?: number;
|
||||
query: DocumentNode;
|
||||
sort?: NetworkDnsSortField;
|
||||
stackByField: string;
|
||||
skip: boolean;
|
||||
startDate: number;
|
||||
title: string;
|
||||
isAlertsHistogram?: boolean;
|
||||
isAnomaliesHistogram?: boolean;
|
||||
isAuthenticationsHistogram?: boolean;
|
||||
isDNSHistogram?: boolean;
|
||||
isEventsType?: boolean;
|
||||
isInspected: boolean;
|
||||
isPtrIncluded?: boolean;
|
||||
pagination?: PaginationInputPaginated;
|
||||
}
|
||||
|
||||
export interface MatrixHistogramProps extends MatrixHistogramBasicProps {
|
||||
scaleType?: ScaleType;
|
||||
subtitle?: string;
|
||||
title?: string;
|
||||
yTickFormatter?: (value: number) => string;
|
||||
showLegend?: boolean;
|
||||
legendPosition?: Position;
|
||||
}
|
||||
|
||||
export interface HistogramBucket {
|
||||
key_as_string: string;
|
||||
key: number;
|
||||
doc_count: number;
|
||||
}
|
||||
export interface GroupBucket {
|
||||
key: string;
|
||||
signals: {
|
||||
buckets: HistogramBucket[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface HistogramAggregation {
|
||||
histogramAgg: {
|
||||
buckets: GroupBucket[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface SignalsResponse {
|
||||
took: number;
|
||||
timeout: boolean;
|
||||
}
|
||||
|
||||
export interface SignalSearchResponse<Hit = {}, Aggregations = {} | undefined>
|
||||
extends SignalsResponse {
|
||||
_shards: {
|
||||
total: number;
|
||||
successful: number;
|
||||
skipped: number;
|
||||
failed: number;
|
||||
};
|
||||
aggregations?: Aggregations;
|
||||
hits: {
|
||||
total: {
|
||||
value: number;
|
||||
relation: string;
|
||||
};
|
||||
hits: Hit[];
|
||||
};
|
||||
}
|
||||
|
||||
export type Return<Hit, Aggs> = [
|
||||
boolean,
|
||||
SignalSearchResponse<Hit, Aggs> | null,
|
||||
React.Dispatch<SetStateAction<string>>
|
||||
];
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ScaleType, niceTimeFormatter, Position } from '@elastic/charts';
|
||||
import { get, groupBy, map, toPairs } from 'lodash/fp';
|
||||
|
||||
|
@ -17,6 +16,7 @@ export const getBarchartConfigs = ({
|
|||
onBrushEnd,
|
||||
yTickFormatter,
|
||||
showLegend,
|
||||
legendPosition,
|
||||
}: {
|
||||
from: number;
|
||||
to: number;
|
||||
|
@ -24,6 +24,7 @@ export const getBarchartConfigs = ({
|
|||
onBrushEnd: UpdateDateRange;
|
||||
yTickFormatter?: (value: number) => string;
|
||||
showLegend?: boolean;
|
||||
legendPosition?: Position;
|
||||
}) => ({
|
||||
series: {
|
||||
xScaleType: scaleType || ScaleType.Time,
|
||||
|
@ -39,7 +40,7 @@ export const getBarchartConfigs = ({
|
|||
tickSize: 8,
|
||||
},
|
||||
settings: {
|
||||
legendPosition: Position.Bottom,
|
||||
legendPosition: legendPosition || Position.Bottom,
|
||||
onBrushEnd,
|
||||
showLegend: showLegend || true,
|
||||
theme: {
|
||||
|
@ -72,18 +73,18 @@ export const formatToChartDataItem = ([key, value]: [
|
|||
});
|
||||
|
||||
export const getCustomChartData = (
|
||||
data: MatrixHistogramDataTypes[],
|
||||
data: MatrixHistogramDataTypes[] | null,
|
||||
mapping?: MatrixHistogramMappingTypes
|
||||
): ChartSeriesData[] => {
|
||||
if (!data) return [];
|
||||
const dataGroupedByEvent = groupBy('g', data);
|
||||
const dataGroupedEntries = toPairs(dataGroupedByEvent);
|
||||
const formattedChartData = map(formatToChartDataItem, dataGroupedEntries);
|
||||
|
||||
if (mapping)
|
||||
return map((item: ChartSeriesData) => {
|
||||
const customColor = get(`${item.key}.color`, mapping);
|
||||
item.color = customColor;
|
||||
return item;
|
||||
const mapItem = get(item.key, mapping);
|
||||
return { ...item, color: mapItem.color };
|
||||
}, formattedChartData);
|
||||
else return formattedChartData;
|
||||
};
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import * as i18n from './translation';
|
||||
import { MatrixHistogram } from '../../../matrix_histogram';
|
||||
import { MatrixHistogramBasicProps } from '../../../matrix_histogram/types';
|
||||
import { MatrixOverTimeHistogramData } from '../../../../graphql/types';
|
||||
|
||||
export const AlertsOverTimeHistogram = (
|
||||
props: MatrixHistogramBasicProps<MatrixOverTimeHistogramData>
|
||||
) => {
|
||||
const dataKey = 'alertsOverTime';
|
||||
const { totalCount } = props;
|
||||
const subtitle = `${i18n.SHOWING}: ${totalCount.toLocaleString()} ${i18n.UNIT(totalCount)}`;
|
||||
const { ...matrixOverTimeProps } = props;
|
||||
|
||||
return (
|
||||
<MatrixHistogram
|
||||
title={i18n.ALERTS_COUNT_FREQUENCY_BY_MODULE}
|
||||
subtitle={subtitle}
|
||||
dataKey={dataKey}
|
||||
{...matrixOverTimeProps}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const ALERTS_COUNT_FREQUENCY_BY_MODULE = i18n.translate(
|
||||
'xpack.siem.alertsOverTime.alertsCountFrequencyByModuleTitle',
|
||||
{
|
||||
defaultMessage: 'Alerts count by module',
|
||||
}
|
||||
);
|
||||
|
||||
export const SHOWING = i18n.translate('xpack.siem.alertsOverTime.showing', {
|
||||
defaultMessage: 'Showing',
|
||||
});
|
||||
|
||||
export const UNIT = (totalCount: number) =>
|
||||
i18n.translate('xpack.siem.alertsOverTime.unit', {
|
||||
values: { totalCount },
|
||||
defaultMessage: `{totalCount, plural, =1 {alert} other {alerts}}`,
|
||||
});
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import * as i18n from './translation';
|
||||
import { MatrixHistogram } from '../../../matrix_histogram';
|
||||
import { MatrixHistogramBasicProps } from '../../../matrix_histogram/types';
|
||||
import { MatrixOverTimeHistogramData } from '../../../../graphql/types';
|
||||
import { authMatrixDataMappingFields } from './utils';
|
||||
|
||||
export const AuthenticationsOverTimeHistogram = (
|
||||
props: MatrixHistogramBasicProps<MatrixOverTimeHistogramData>
|
||||
) => {
|
||||
const dataKey = 'authenticationsOverTime';
|
||||
const { data, ...matrixOverTimeProps } = props;
|
||||
|
||||
return (
|
||||
<MatrixHistogram
|
||||
mapping={authMatrixDataMappingFields}
|
||||
dataKey={dataKey}
|
||||
data={data}
|
||||
title={i18n.AUTHENTICATIONS_COUNT}
|
||||
{...matrixOverTimeProps}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const AUTHENTICATIONS_COUNT = i18n.translate(
|
||||
'xpack.siem.authenticationsOverTime.authenticationCountTitle',
|
||||
{
|
||||
defaultMessage: 'Authentications count',
|
||||
}
|
||||
);
|
||||
|
||||
export const UNIT = (totalCount: number) =>
|
||||
i18n.translate('xpack.siem.authenticationsOverTime.unit', {
|
||||
values: { totalCount },
|
||||
defaultMessage: `{totalCount, plural, =1 {authentication} other {authentications}}`,
|
||||
});
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ChartSeriesData } from '../../../charts/common';
|
||||
import { KpiHostsChartColors } from '../kpi_hosts/types';
|
||||
|
||||
enum AuthMatrixDataGroup {
|
||||
authSuccess = 'authentication_success',
|
||||
authFailure = 'authentication_failure',
|
||||
}
|
||||
|
||||
export interface AuthMatrixDataFields {
|
||||
[AuthMatrixDataGroup.authSuccess]: ChartSeriesData;
|
||||
[AuthMatrixDataGroup.authFailure]: ChartSeriesData;
|
||||
}
|
||||
|
||||
export const authMatrixDataMappingFields: AuthMatrixDataFields = {
|
||||
[AuthMatrixDataGroup.authSuccess]: {
|
||||
key: AuthMatrixDataGroup.authSuccess,
|
||||
value: null,
|
||||
color: KpiHostsChartColors.authSuccess,
|
||||
},
|
||||
[AuthMatrixDataGroup.authFailure]: {
|
||||
key: AuthMatrixDataGroup.authFailure,
|
||||
value: null,
|
||||
color: KpiHostsChartColors.authFailure,
|
||||
},
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import * as i18n from './translation';
|
||||
import { MatrixHistogram } from '../../../matrix_histogram';
|
||||
import { MatrixHistogramBasicProps } from '../../../matrix_histogram/types';
|
||||
import { MatrixOverTimeHistogramData } from '../../../../graphql/types';
|
||||
|
||||
export const EventsOverTimeHistogram = (
|
||||
props: MatrixHistogramBasicProps<MatrixOverTimeHistogramData>
|
||||
) => {
|
||||
const dataKey = 'eventsOverTime';
|
||||
const { totalCount } = props;
|
||||
const subtitle = `${i18n.SHOWING}: ${totalCount.toLocaleString()} ${i18n.UNIT(totalCount)}`;
|
||||
const { ...matrixOverTimeProps } = props;
|
||||
|
||||
return (
|
||||
<MatrixHistogram
|
||||
title={i18n.EVENT_COUNT_FREQUENCY_BY_ACTION}
|
||||
subtitle={subtitle}
|
||||
dataKey={dataKey}
|
||||
{...matrixOverTimeProps}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const EVENT_COUNT_FREQUENCY_BY_ACTION = i18n.translate(
|
||||
'xpack.siem.eventsOverTime.eventCountFrequencyByActionTitle',
|
||||
{
|
||||
defaultMessage: 'Event count by action',
|
||||
}
|
||||
);
|
||||
|
||||
export const SHOWING = i18n.translate('xpack.siem.eventsOverTime.showing', {
|
||||
defaultMessage: 'Showing',
|
||||
});
|
||||
|
||||
export const UNIT = (totalCount: number) =>
|
||||
i18n.translate('xpack.siem.eventsOverTime.unit', {
|
||||
values: { totalCount },
|
||||
defaultMessage: `{totalCount, plural, =1 {event} other {events}}`,
|
||||
});
|
|
@ -8,18 +8,14 @@ import { omit } from 'lodash/fp';
|
|||
import React from 'react';
|
||||
|
||||
import { inputsModel } from '../../store';
|
||||
import { SetQuery } from '../../pages/hosts/navigation/types';
|
||||
|
||||
interface OwnProps {
|
||||
deleteQuery?: ({ id }: { id: string }) => void;
|
||||
id: string;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
setQuery: (params: {
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery | null;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
}) => void;
|
||||
setQuery: SetQuery;
|
||||
inspect?: inputsModel.InspectQuery;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
import * as i18n from './translation';
|
||||
import { MatrixHistogram } from '../../../matrix_histogram';
|
||||
import { MatrixOverOrdinalHistogramData } from '../../../../graphql/types';
|
||||
import { MatrixHistogramBasicProps } from '../../../matrix_histogram/types';
|
||||
import { useFormatBytes } from '../../../formatted_bytes';
|
||||
|
||||
export const NetworkDnsHistogram = (
|
||||
props: MatrixHistogramBasicProps<MatrixOverOrdinalHistogramData>
|
||||
) => {
|
||||
const dataKey = 'histogram';
|
||||
const { ...matrixOverTimeProps } = props;
|
||||
const formatBytes = useFormatBytes();
|
||||
|
||||
return (
|
||||
<MatrixHistogram
|
||||
title={i18n.NETWORK_DNS_HISTOGRAM}
|
||||
dataKey={dataKey}
|
||||
scaleType={ScaleType.Ordinal}
|
||||
yTickFormatter={formatBytes}
|
||||
showLegend={false}
|
||||
{...matrixOverTimeProps}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const AlertsOverTimeGqlQuery = gql`
|
||||
query GetAlertsOverTimeQuery(
|
||||
$sourceId: ID!
|
||||
$timerange: TimerangeInput!
|
||||
$defaultIndex: [String!]!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
AlertsHistogram(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
) {
|
||||
alertsOverTimeByModule {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
|
||||
import { inputsModel, State, inputsSelectors, hostsModel } from '../../../store';
|
||||
import { withKibana, WithKibanaProps } from '../../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../../helpers';
|
||||
import { QueryTemplate, QueryTemplateProps } from '../../query_template';
|
||||
|
||||
import { AlertsOverTimeGqlQuery } from './alerts_over_time.gql_query';
|
||||
import { MatrixOverTimeHistogramData, GetAlertsOverTimeQuery } from '../../../graphql/types';
|
||||
|
||||
const ID = 'alertsOverTimeQuery';
|
||||
|
||||
export interface AlertsArgs {
|
||||
endDate: number;
|
||||
alertsOverTime: MatrixOverTimeHistogramData[];
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
startDate: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children?: (args: AlertsArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType;
|
||||
}
|
||||
|
||||
export interface AlertsOverTimeComponentReduxProps {
|
||||
isInspected: boolean;
|
||||
}
|
||||
|
||||
type AlertsOverTimeProps = OwnProps & AlertsOverTimeComponentReduxProps & WithKibanaProps;
|
||||
|
||||
class AlertsOverTimeComponentQuery extends QueryTemplate<
|
||||
AlertsOverTimeProps,
|
||||
GetAlertsOverTimeQuery.Query,
|
||||
GetAlertsOverTimeQuery.Variables
|
||||
> {
|
||||
public render() {
|
||||
const {
|
||||
children,
|
||||
endDate,
|
||||
filterQuery,
|
||||
id = ID,
|
||||
isInspected,
|
||||
kibana,
|
||||
sourceId,
|
||||
startDate,
|
||||
} = this.props;
|
||||
return (
|
||||
<Query<GetAlertsOverTimeQuery.Query, GetAlertsOverTimeQuery.Variables>
|
||||
query={AlertsOverTimeGqlQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
variables={{
|
||||
filterQuery: createFilter(filterQuery),
|
||||
sourceId,
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
from: startDate!,
|
||||
to: endDate!,
|
||||
},
|
||||
defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),
|
||||
inspect: isInspected,
|
||||
}}
|
||||
>
|
||||
{({ data, loading, refetch }) => {
|
||||
const source = getOr({}, `source.AlertsHistogram`, data);
|
||||
const alertsOverTime = getOr([], `alertsOverTimeByModule`, source);
|
||||
const totalCount = getOr(-1, 'totalCount', source);
|
||||
return children!({
|
||||
endDate: endDate!,
|
||||
alertsOverTime,
|
||||
id,
|
||||
inspect: getOr(null, 'inspect', source),
|
||||
loading,
|
||||
refetch,
|
||||
startDate: startDate!,
|
||||
totalCount,
|
||||
});
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { type, id = ID }: OwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
isInspected,
|
||||
};
|
||||
};
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export const AlertsOverTimeQuery = compose<React.ComponentClass<OwnProps>>(
|
||||
connect(makeMapStateToProps),
|
||||
withKibana
|
||||
)(AlertsOverTimeComponentQuery);
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const AnomaliesOverTimeGqlQuery = gql`
|
||||
query GetAnomaliesOverTimeQuery(
|
||||
$sourceId: ID!
|
||||
$timerange: TimerangeInput!
|
||||
$defaultIndex: [String!]!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
AnomaliesOverTime(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
) {
|
||||
anomaliesOverTime {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { State, inputsSelectors } from '../../../store';
|
||||
import { getDefaultFetchPolicy } from '../../helpers';
|
||||
import { QueryTemplate } from '../../query_template';
|
||||
|
||||
import { AnomaliesOverTimeGqlQuery } from './anomalies_over_time.gql_query';
|
||||
import { GetAnomaliesOverTimeQuery } from '../../../graphql/types';
|
||||
import { AnomaliesOverTimeProps, OwnProps } from './types';
|
||||
|
||||
const ID = 'anomaliesOverTimeQuery';
|
||||
|
||||
class AnomaliesOverTimeComponentQuery extends QueryTemplate<
|
||||
AnomaliesOverTimeProps,
|
||||
GetAnomaliesOverTimeQuery.Query,
|
||||
GetAnomaliesOverTimeQuery.Variables
|
||||
> {
|
||||
public render() {
|
||||
const {
|
||||
children,
|
||||
endDate,
|
||||
filterQuery,
|
||||
id = ID,
|
||||
isInspected,
|
||||
sourceId,
|
||||
startDate,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Query<GetAnomaliesOverTimeQuery.Query, GetAnomaliesOverTimeQuery.Variables>
|
||||
query={AnomaliesOverTimeGqlQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
variables={{
|
||||
filterQuery,
|
||||
sourceId,
|
||||
timerange: {
|
||||
interval: 'day',
|
||||
from: startDate!,
|
||||
to: endDate!,
|
||||
},
|
||||
defaultIndex: ['.ml-anomalies-*'],
|
||||
inspect: isInspected,
|
||||
}}
|
||||
>
|
||||
{({ data, loading, refetch }) => {
|
||||
const source = getOr({}, `source.AnomaliesOverTime`, data);
|
||||
const anomaliesOverTime = getOr([], `anomaliesOverTime`, source);
|
||||
const totalCount = getOr(-1, 'totalCount', source);
|
||||
return children!({
|
||||
endDate: endDate!,
|
||||
anomaliesOverTime,
|
||||
id,
|
||||
inspect: getOr(null, 'inspect', source),
|
||||
loading,
|
||||
refetch,
|
||||
startDate: startDate!,
|
||||
totalCount,
|
||||
});
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { id = ID }: OwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
isInspected,
|
||||
};
|
||||
};
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export const AnomaliesOverTimeQuery = connect(makeMapStateToProps)(AnomaliesOverTimeComponentQuery);
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { QueryTemplateProps } from '../../query_template';
|
||||
import { inputsModel, hostsModel, networkModel } from '../../../store';
|
||||
import { MatrixOverTimeHistogramData } from '../../../graphql/types';
|
||||
|
||||
export interface AnomaliesArgs {
|
||||
endDate: number;
|
||||
anomaliesOverTime: MatrixOverTimeHistogramData[];
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
startDate: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface OwnProps extends Omit<QueryTemplateProps, 'filterQuery'> {
|
||||
filterQuery?: string;
|
||||
children?: (args: AnomaliesArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType | networkModel.NetworkType;
|
||||
}
|
||||
|
||||
export interface AnomaliesOverTimeComponentReduxProps {
|
||||
isInspected: boolean;
|
||||
}
|
||||
|
||||
export type AnomaliesOverTimeProps = OwnProps & AnomaliesOverTimeComponentReduxProps;
|
|
@ -4,35 +4,42 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import * as i18n from './translations';
|
||||
import { AnomaliesQueryTabBodyProps } from './types';
|
||||
import { manageQuery } from '../../../components/page/manage_query';
|
||||
import { AnomaliesOverTimeHistogram } from '../../../components/anomalies_over_time';
|
||||
import { AnomaliesOverTimeQuery } from '../anomalies_over_time';
|
||||
import { getAnomaliesFilterQuery } from './utils';
|
||||
import { useSiemJobs } from '../../../components/ml_popover/hooks/use_siem_jobs';
|
||||
import { useUiSetting$ } from '../../../lib/kibana';
|
||||
import { DEFAULT_ANOMALY_SCORE } from '../../../../common/constants';
|
||||
import { MatrixHistogramContainer } from '../../matrix_histogram';
|
||||
import { MatrixHistogramOption } from '../../../components/matrix_histogram/types';
|
||||
import { MatrixHistogramGqlQuery } from '../../matrix_histogram/index.gql_query';
|
||||
|
||||
const AnomaliesOverTimeManage = manageQuery(AnomaliesOverTimeHistogram);
|
||||
const ID = 'anomaliesOverTimeQuery';
|
||||
const anomaliesStackByOptions: MatrixHistogramOption[] = [
|
||||
{
|
||||
text: i18n.ANOMALIES_STACK_BY_JOB_ID,
|
||||
value: 'job_id',
|
||||
},
|
||||
];
|
||||
|
||||
export const AnomaliesQueryTabBody = ({
|
||||
deleteQuery,
|
||||
endDate,
|
||||
setQuery,
|
||||
skip,
|
||||
startDate,
|
||||
type,
|
||||
narrowDateRange,
|
||||
filterQuery,
|
||||
anomaliesFilterQuery,
|
||||
setQuery,
|
||||
hideHistogramIfEmpty,
|
||||
updateDateRange = () => {},
|
||||
AnomaliesTableComponent,
|
||||
flowTarget,
|
||||
ip,
|
||||
}: AnomaliesQueryTabBodyProps) => {
|
||||
const [siemJobsLoading, siemJobs] = useSiemJobs(true);
|
||||
const [, siemJobs] = useSiemJobs(true);
|
||||
const [anomalyScore] = useUiSetting$<number>(DEFAULT_ANOMALY_SCORE);
|
||||
|
||||
const mergedFilterQuery = getAnomaliesFilterQuery(
|
||||
|
@ -44,39 +51,37 @@ export const AnomaliesQueryTabBody = ({
|
|||
ip
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (deleteQuery) {
|
||||
deleteQuery({ id: ID });
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnomaliesOverTimeQuery
|
||||
<MatrixHistogramContainer
|
||||
isAnomaliesHistogram={true}
|
||||
dataKey="AnomaliesHistogram"
|
||||
defaultStackByOption={anomaliesStackByOptions[0]}
|
||||
deleteQuery={deleteQuery}
|
||||
endDate={endDate}
|
||||
errorMessage={i18n.ERROR_FETCHING_ANOMALIES_DATA}
|
||||
filterQuery={mergedFilterQuery}
|
||||
hideHistogramIfEmpty={true}
|
||||
id={ID}
|
||||
query={MatrixHistogramGqlQuery}
|
||||
setQuery={setQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
stackByOptions={anomaliesStackByOptions}
|
||||
startDate={startDate}
|
||||
title={i18n.ANOMALIES_TITLE}
|
||||
type={type}
|
||||
>
|
||||
{({ anomaliesOverTime, loading, id, inspect, refetch, totalCount }) => {
|
||||
if (hideHistogramIfEmpty && !anomaliesOverTime.length) {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnomaliesOverTimeManage
|
||||
data={anomaliesOverTime!}
|
||||
endDate={endDate}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
loading={siemJobsLoading || loading}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
startDate={startDate}
|
||||
totalCount={totalCount}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</AnomaliesOverTimeQuery>
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<AnomaliesTableComponent
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const ANOMALIES_STACK_BY_JOB_ID = i18n.translate(
|
||||
'xpack.siem.containers.anomalies.stackByJobId',
|
||||
{
|
||||
defaultMessage: 'job',
|
||||
}
|
||||
);
|
||||
|
||||
export const ANOMALIES_TITLE = i18n.translate('xpack.siem.containers.anomalies.title', {
|
||||
defaultMessage: 'Anomalies',
|
||||
});
|
||||
|
||||
export const ERROR_FETCHING_ANOMALIES_DATA = i18n.translate(
|
||||
'xpack.siem.containers.anomalies.errorFetchingAnomaliesData',
|
||||
{
|
||||
defaultMessage: 'Failed to query anomalies data',
|
||||
}
|
||||
);
|
|
@ -20,15 +20,16 @@ interface QueryTabBodyProps {
|
|||
}
|
||||
|
||||
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & {
|
||||
startDate: number;
|
||||
endDate: number;
|
||||
skip: boolean;
|
||||
setQuery: SetQuery;
|
||||
narrowDateRange: NarrowDateRange;
|
||||
updateDateRange?: UpdateDateRange;
|
||||
anomaliesFilterQuery?: object;
|
||||
AnomaliesTableComponent: typeof AnomaliesHostTable | typeof AnomaliesNetworkTable;
|
||||
deleteQuery?: ({ id }: { id: string }) => void;
|
||||
endDate: number;
|
||||
flowTarget?: FlowTarget;
|
||||
narrowDateRange: NarrowDateRange;
|
||||
setQuery: SetQuery;
|
||||
startDate: number;
|
||||
skip: boolean;
|
||||
updateDateRange?: UpdateDateRange;
|
||||
hideHistogramIfEmpty?: boolean;
|
||||
ip?: string;
|
||||
flowTarget?: FlowTarget;
|
||||
AnomaliesTableComponent: typeof AnomaliesHostTable | typeof AnomaliesNetworkTable;
|
||||
};
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const AuthenticationsOverTimeGqlQuery = gql`
|
||||
query GetAuthenticationsOverTimeQuery(
|
||||
$sourceId: ID!
|
||||
$timerange: TimerangeInput!
|
||||
$defaultIndex: [String!]!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
AuthenticationsOverTime(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
) {
|
||||
authenticationsOverTime {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
|
||||
import { inputsModel, State, inputsSelectors, hostsModel } from '../../../store';
|
||||
import { withKibana, WithKibanaProps } from '../../../lib/kibana';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../../helpers';
|
||||
import { QueryTemplate, QueryTemplateProps } from '../../query_template';
|
||||
|
||||
import { AuthenticationsOverTimeGqlQuery } from './authentications_over_time.gql_query';
|
||||
import {
|
||||
GetAuthenticationsOverTimeQuery,
|
||||
MatrixOverTimeHistogramData,
|
||||
} from '../../../graphql/types';
|
||||
|
||||
const ID = 'authenticationsOverTimeQuery';
|
||||
|
||||
export interface AuthenticationsArgs {
|
||||
endDate: number;
|
||||
authenticationsOverTime: MatrixOverTimeHistogramData[];
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
startDate: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children?: (args: AuthenticationsArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType;
|
||||
}
|
||||
|
||||
export interface AuthenticationsOverTimeComponentReduxProps {
|
||||
isInspected: boolean;
|
||||
}
|
||||
|
||||
type AuthenticationsOverTimeProps = OwnProps &
|
||||
AuthenticationsOverTimeComponentReduxProps &
|
||||
WithKibanaProps;
|
||||
|
||||
class AuthenticationsOverTimeComponentQuery extends QueryTemplate<
|
||||
AuthenticationsOverTimeProps,
|
||||
GetAuthenticationsOverTimeQuery.Query,
|
||||
GetAuthenticationsOverTimeQuery.Variables
|
||||
> {
|
||||
public render() {
|
||||
const {
|
||||
children,
|
||||
filterQuery,
|
||||
id = ID,
|
||||
isInspected,
|
||||
kibana,
|
||||
sourceId,
|
||||
startDate,
|
||||
endDate,
|
||||
} = this.props;
|
||||
return (
|
||||
<Query<GetAuthenticationsOverTimeQuery.Query, GetAuthenticationsOverTimeQuery.Variables>
|
||||
query={AuthenticationsOverTimeGqlQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
variables={{
|
||||
filterQuery: createFilter(filterQuery),
|
||||
sourceId,
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
from: startDate!,
|
||||
to: endDate!,
|
||||
},
|
||||
defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),
|
||||
inspect: isInspected,
|
||||
}}
|
||||
>
|
||||
{({ data, loading, refetch }) => {
|
||||
const source = getOr({}, `source.AuthenticationsOverTime`, data);
|
||||
const authenticationsOverTime = getOr([], `authenticationsOverTime`, source);
|
||||
const totalCount = getOr(-1, 'totalCount', source);
|
||||
return children!({
|
||||
endDate: endDate!,
|
||||
authenticationsOverTime,
|
||||
id,
|
||||
inspect: getOr(null, 'inspect', source),
|
||||
loading,
|
||||
refetch,
|
||||
startDate: startDate!,
|
||||
totalCount,
|
||||
});
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { type, id = ID }: OwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
isInspected,
|
||||
};
|
||||
};
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export const AuthenticationsOverTimeQuery = compose<React.ComponentClass<OwnProps>>(
|
||||
connect(makeMapStateToProps),
|
||||
withKibana
|
||||
)(AuthenticationsOverTimeComponentQuery);
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const EventsOverTimeGqlQuery = gql`
|
||||
query GetEventsOverTimeQuery(
|
||||
$sourceId: ID!
|
||||
$timerange: TimerangeInput!
|
||||
$defaultIndex: [String!]!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
EventsOverTime(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
) {
|
||||
eventsOverTime {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -1,113 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import { Query } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
|
||||
import { inputsModel, State, inputsSelectors, hostsModel } from '../../../store';
|
||||
import { createFilter, getDefaultFetchPolicy } from '../../helpers';
|
||||
import { QueryTemplate, QueryTemplateProps } from '../../query_template';
|
||||
import { withKibana, WithKibanaProps } from '../../../lib/kibana';
|
||||
|
||||
import { EventsOverTimeGqlQuery } from './events_over_time.gql_query';
|
||||
import { GetEventsOverTimeQuery, MatrixOverTimeHistogramData } from '../../../graphql/types';
|
||||
|
||||
const ID = 'eventsOverTimeQuery';
|
||||
|
||||
export interface EventsArgs {
|
||||
endDate: number;
|
||||
eventsOverTime: MatrixOverTimeHistogramData[];
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery;
|
||||
loading: boolean;
|
||||
refetch: inputsModel.Refetch;
|
||||
startDate: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
children?: (args: EventsArgs) => React.ReactNode;
|
||||
type: hostsModel.HostsType;
|
||||
}
|
||||
|
||||
export interface EventsOverTimeComponentReduxProps {
|
||||
isInspected: boolean;
|
||||
}
|
||||
|
||||
type EventsOverTimeProps = OwnProps & EventsOverTimeComponentReduxProps & WithKibanaProps;
|
||||
|
||||
class EventsOverTimeComponentQuery extends QueryTemplate<
|
||||
EventsOverTimeProps,
|
||||
GetEventsOverTimeQuery.Query,
|
||||
GetEventsOverTimeQuery.Variables
|
||||
> {
|
||||
public render() {
|
||||
const {
|
||||
children,
|
||||
endDate,
|
||||
filterQuery,
|
||||
id = ID,
|
||||
isInspected,
|
||||
kibana,
|
||||
sourceId,
|
||||
startDate,
|
||||
} = this.props;
|
||||
return (
|
||||
<Query<GetEventsOverTimeQuery.Query, GetEventsOverTimeQuery.Variables>
|
||||
query={EventsOverTimeGqlQuery}
|
||||
fetchPolicy={getDefaultFetchPolicy()}
|
||||
notifyOnNetworkStatusChange
|
||||
variables={{
|
||||
filterQuery: createFilter(filterQuery),
|
||||
sourceId,
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
from: startDate!,
|
||||
to: endDate!,
|
||||
},
|
||||
defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),
|
||||
inspect: isInspected,
|
||||
}}
|
||||
>
|
||||
{({ data, loading, refetch }) => {
|
||||
const source = getOr({}, `source.EventsOverTime`, data);
|
||||
const eventsOverTime = getOr([], `eventsOverTime`, source);
|
||||
const totalCount = getOr(-1, 'totalCount', source);
|
||||
return children!({
|
||||
endDate: endDate!,
|
||||
eventsOverTime,
|
||||
id,
|
||||
inspect: getOr(null, 'inspect', source),
|
||||
loading,
|
||||
refetch,
|
||||
startDate: startDate!,
|
||||
totalCount,
|
||||
});
|
||||
}}
|
||||
</Query>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { type, id = ID }: OwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
isInspected,
|
||||
};
|
||||
};
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export const EventsOverTimeQuery = compose<React.ComponentClass<OwnProps>>(
|
||||
connect(makeMapStateToProps),
|
||||
withKibana
|
||||
)(EventsOverTimeComponentQuery);
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const MatrixHistogramGqlQuery = gql`
|
||||
query GetMatrixHistogramQuery(
|
||||
$isAlertsHistogram: Boolean!
|
||||
$isAnomaliesHistogram: Boolean!
|
||||
$isAuthenticationsHistogram: Boolean!
|
||||
$defaultIndex: [String!]!
|
||||
$isEventsType: Boolean!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
$sourceId: ID!
|
||||
$stackByField: String
|
||||
$timerange: TimerangeInput!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
AlertsHistogram(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
stackByField: $stackByField
|
||||
) @include(if: $isAlertsHistogram) {
|
||||
matrixHistogramData {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
AnomaliesHistogram(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
stackByField: $stackByField
|
||||
) @include(if: $isAnomaliesHistogram) {
|
||||
matrixHistogramData {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
AuthenticationsHistogram(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
stackByField: $stackByField
|
||||
) @include(if: $isAuthenticationsHistogram) {
|
||||
matrixHistogramData {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
EventsHistogram(
|
||||
timerange: $timerange
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
stackByField: $stackByField
|
||||
) @include(if: $isEventsType) {
|
||||
matrixHistogramData {
|
||||
x
|
||||
y
|
||||
g
|
||||
}
|
||||
totalCount
|
||||
inspect @include(if: $inspect) {
|
||||
dsl
|
||||
response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { State, inputsSelectors, hostsModel, networkModel } from '../../store';
|
||||
import { QueryTemplateProps } from '../query_template';
|
||||
|
||||
import { Maybe } from '../../graphql/types';
|
||||
import { MatrixHistogram } from '../../components/matrix_histogram';
|
||||
import {
|
||||
MatrixHistogramOption,
|
||||
MatrixHistogramMappingTypes,
|
||||
GetSubTitle,
|
||||
} from '../../components/matrix_histogram/types';
|
||||
import { UpdateDateRange } from '../../components/charts/common';
|
||||
import { SetQuery } from '../../pages/hosts/navigation/types';
|
||||
|
||||
export interface OwnProps extends QueryTemplateProps {
|
||||
isAlertsHistogram?: boolean;
|
||||
isAnomaliesHistogram?: boolean;
|
||||
isAuthenticationsHistogram?: boolean;
|
||||
dataKey: string | string[];
|
||||
defaultStackByOption: MatrixHistogramOption;
|
||||
deleteQuery?: ({ id }: { id: string }) => void;
|
||||
isEventsType?: boolean;
|
||||
errorMessage: string;
|
||||
hideHistogramIfEmpty?: boolean;
|
||||
id: string;
|
||||
mapping?: MatrixHistogramMappingTypes;
|
||||
query: Maybe<string>;
|
||||
setQuery: SetQuery;
|
||||
sourceId: string;
|
||||
stackByOptions: MatrixHistogramOption[];
|
||||
subtitle?: string | GetSubTitle;
|
||||
title: string;
|
||||
type: hostsModel.HostsType | networkModel.NetworkType;
|
||||
updateDateRange: UpdateDateRange;
|
||||
}
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { type, id }: OwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
isInspected,
|
||||
};
|
||||
};
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
export const MatrixHistogramContainer = compose<React.ComponentClass<OwnProps>>(
|
||||
connect(makeMapStateToProps)
|
||||
)(MatrixHistogram);
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
import { getOr } from 'lodash/fp';
|
||||
import { useEffect, useState } from 'react';
|
||||
import {
|
||||
MatrixHistogramDataTypes,
|
||||
MatrixHistogramQueryProps,
|
||||
} from '../../components/matrix_histogram/types';
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import { useStateToaster } from '../../components/toasters';
|
||||
import { errorToToaster } from '../../components/ml/api/error_to_toaster';
|
||||
import { useUiSetting$ } from '../../lib/kibana';
|
||||
import { createFilter } from '../helpers';
|
||||
import { useApolloClient } from '../../utils/apollo_context';
|
||||
import { inputsModel } from '../../store';
|
||||
import { GetMatrixHistogramQuery, GetNetworkDnsQuery } from '../../graphql/types';
|
||||
|
||||
export const useQuery = <Hit, Aggs, TCache = object>({
|
||||
dataKey,
|
||||
endDate,
|
||||
errorMessage,
|
||||
filterQuery,
|
||||
isAlertsHistogram = false,
|
||||
isAnomaliesHistogram = false,
|
||||
isAuthenticationsHistogram = false,
|
||||
isEventsType = false,
|
||||
isDNSHistogram,
|
||||
isPtrIncluded,
|
||||
isInspected,
|
||||
query,
|
||||
stackByField,
|
||||
startDate,
|
||||
sort,
|
||||
pagination,
|
||||
}: MatrixHistogramQueryProps) => {
|
||||
const [defaultIndex] = useUiSetting$<string[]>(DEFAULT_INDEX_KEY);
|
||||
const [, dispatchToaster] = useStateToaster();
|
||||
const [refetch, setRefetch] = useState<inputsModel.Refetch>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [data, setData] = useState<MatrixHistogramDataTypes[] | null>(null);
|
||||
const [inspect, setInspect] = useState<inputsModel.InspectQuery | null>(null);
|
||||
const [totalCount, setTotalCount] = useState(-1);
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const isDNSQuery = (
|
||||
variable: Pick<
|
||||
MatrixHistogramQueryProps,
|
||||
'isDNSHistogram' | 'isPtrIncluded' | 'sort' | 'pagination'
|
||||
>
|
||||
): variable is GetNetworkDnsQuery.Variables => {
|
||||
return (
|
||||
!!isDNSHistogram &&
|
||||
variable.isDNSHistogram !== undefined &&
|
||||
variable.isPtrIncluded !== undefined &&
|
||||
variable.sort !== undefined &&
|
||||
variable.pagination !== undefined
|
||||
);
|
||||
};
|
||||
const basicVariables = {
|
||||
filterQuery: createFilter(filterQuery),
|
||||
sourceId: 'default',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
from: startDate!,
|
||||
to: endDate!,
|
||||
},
|
||||
defaultIndex,
|
||||
inspect: isInspected,
|
||||
stackByField,
|
||||
};
|
||||
const dnsVariables = {
|
||||
...basicVariables,
|
||||
isDNSHistogram,
|
||||
isPtrIncluded,
|
||||
sort,
|
||||
pagination,
|
||||
};
|
||||
const matrixHistogramVariables: GetMatrixHistogramQuery.Variables = {
|
||||
...basicVariables,
|
||||
isAlertsHistogram,
|
||||
isAnomaliesHistogram,
|
||||
isAuthenticationsHistogram,
|
||||
isEventsType,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let isSubscribed = true;
|
||||
const abortCtrl = new AbortController();
|
||||
const abortSignal = abortCtrl.signal;
|
||||
|
||||
async function fetchData() {
|
||||
if (!apolloClient || (pagination != null && pagination.querySize < 0)) return null;
|
||||
setLoading(true);
|
||||
return apolloClient
|
||||
.query<
|
||||
GetMatrixHistogramQuery.Query | GetNetworkDnsQuery.Query,
|
||||
GetMatrixHistogramQuery.Variables | GetNetworkDnsQuery.Variables
|
||||
>({
|
||||
query,
|
||||
fetchPolicy: 'cache-first',
|
||||
variables: isDNSQuery(dnsVariables) ? dnsVariables : matrixHistogramVariables,
|
||||
context: {
|
||||
fetchOptions: {
|
||||
abortSignal,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(
|
||||
result => {
|
||||
if (isSubscribed) {
|
||||
const isDataKeyAnArray = Array.isArray(dataKey);
|
||||
const rootDataKey = isDataKeyAnArray ? dataKey[0] : `${dataKey}`;
|
||||
const histogramDataKey = isDataKeyAnArray ? dataKey[1] : `matrixHistogramData`;
|
||||
const source = getOr({}, `data.source.${rootDataKey}`, result);
|
||||
setData(getOr([], histogramDataKey, source));
|
||||
setTotalCount(getOr(-1, 'totalCount', source));
|
||||
setInspect(getOr(null, 'inspect', source));
|
||||
setLoading(false);
|
||||
}
|
||||
},
|
||||
error => {
|
||||
if (isSubscribed) {
|
||||
setData(null);
|
||||
setTotalCount(-1);
|
||||
setInspect(null);
|
||||
errorToToaster({ title: errorMessage, error, dispatchToaster });
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
setRefetch(() => {
|
||||
fetchData();
|
||||
});
|
||||
fetchData();
|
||||
return () => {
|
||||
isSubscribed = false;
|
||||
abortCtrl.abort();
|
||||
};
|
||||
}, [
|
||||
defaultIndex,
|
||||
query,
|
||||
filterQuery,
|
||||
isInspected,
|
||||
isDNSHistogram,
|
||||
stackByField,
|
||||
sort,
|
||||
isPtrIncluded,
|
||||
pagination,
|
||||
startDate,
|
||||
endDate,
|
||||
]);
|
||||
|
||||
return { data, loading, inspect, totalCount, refetch };
|
||||
};
|
|
@ -8,14 +8,16 @@ import gql from 'graphql-tag';
|
|||
|
||||
export const networkDnsQuery = gql`
|
||||
query GetNetworkDnsQuery(
|
||||
$sourceId: ID!
|
||||
$sort: NetworkDnsSortField!
|
||||
$isPtrIncluded: Boolean!
|
||||
$timerange: TimerangeInput!
|
||||
$pagination: PaginationInputPaginated!
|
||||
$filterQuery: String
|
||||
$defaultIndex: [String!]!
|
||||
$filterQuery: String
|
||||
$inspect: Boolean!
|
||||
$isDNSHistogram: Boolean!
|
||||
$isPtrIncluded: Boolean!
|
||||
$pagination: PaginationInputPaginated!
|
||||
$sort: NetworkDnsSortField!
|
||||
$sourceId: ID!
|
||||
$stackByField: String
|
||||
$timerange: TimerangeInput!
|
||||
) {
|
||||
source(id: $sourceId) {
|
||||
id
|
||||
|
@ -26,9 +28,10 @@ export const networkDnsQuery = gql`
|
|||
pagination: $pagination
|
||||
filterQuery: $filterQuery
|
||||
defaultIndex: $defaultIndex
|
||||
stackByField: $stackByField
|
||||
) {
|
||||
totalCount
|
||||
edges {
|
||||
edges @skip(if: $isDNSHistogram) {
|
||||
node {
|
||||
_id
|
||||
dnsBytesIn
|
||||
|
@ -41,7 +44,7 @@ export const networkDnsQuery = gql`
|
|||
value
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
pageInfo @skip(if: $isDNSHistogram) {
|
||||
activePage
|
||||
fakeTotalCount
|
||||
showMorePagesIndicator
|
||||
|
@ -50,7 +53,7 @@ export const networkDnsQuery = gql`
|
|||
dsl
|
||||
response
|
||||
}
|
||||
histogram {
|
||||
histogram @include(if: $isDNSHistogram) {
|
||||
x
|
||||
y
|
||||
g
|
||||
|
|
|
@ -10,6 +10,8 @@ import { Query } from 'react-apollo';
|
|||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { DocumentNode } from 'graphql';
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
import { DEFAULT_INDEX_KEY } from '../../../common/constants';
|
||||
import {
|
||||
GetNetworkDnsQuery,
|
||||
|
@ -24,10 +26,14 @@ import { generateTablePaginationOptions } from '../../components/paginated_table
|
|||
import { createFilter, getDefaultFetchPolicy } from '../helpers';
|
||||
import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated';
|
||||
import { networkDnsQuery } from './index.gql_query';
|
||||
import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../../store/constants';
|
||||
import { DEFAULT_TABLE_ACTIVE_PAGE } from '../../store/constants';
|
||||
import { MatrixHistogram } from '../../components/matrix_histogram';
|
||||
import { MatrixHistogramOption, GetSubTitle } from '../../components/matrix_histogram/types';
|
||||
import { UpdateDateRange } from '../../components/charts/common';
|
||||
import { SetQuery } from '../../pages/hosts/navigation/types';
|
||||
|
||||
const ID = 'networkDnsQuery';
|
||||
const HISTOGRAM_ID = 'networkDnsHistogramQuery';
|
||||
export const HISTOGRAM_ID = 'networkDnsHistogramQuery';
|
||||
export interface NetworkDnsArgs {
|
||||
id: string;
|
||||
inspect: inputsModel.InspectQuery;
|
||||
|
@ -37,6 +43,7 @@ export interface NetworkDnsArgs {
|
|||
networkDns: NetworkDnsEdges[];
|
||||
pageInfo: PageInfoPaginated;
|
||||
refetch: inputsModel.Refetch;
|
||||
stackByField?: string;
|
||||
totalCount: number;
|
||||
histogram: MatrixOverOrdinalHistogramData[];
|
||||
}
|
||||
|
@ -46,6 +53,24 @@ export interface OwnProps extends QueryTemplatePaginatedProps {
|
|||
type: networkModel.NetworkType;
|
||||
}
|
||||
|
||||
interface DnsHistogramOwnProps extends QueryTemplatePaginatedProps {
|
||||
dataKey: string | string[];
|
||||
defaultStackByOption: MatrixHistogramOption;
|
||||
errorMessage: string;
|
||||
isDNSHistogram?: boolean;
|
||||
limit: number;
|
||||
query: DocumentNode;
|
||||
scaleType: ScaleType;
|
||||
setQuery: SetQuery;
|
||||
showLegend?: boolean;
|
||||
stackByOptions: MatrixHistogramOption[];
|
||||
subtitle?: string | GetSubTitle;
|
||||
title: string;
|
||||
type: networkModel.NetworkType;
|
||||
updateDateRange: UpdateDateRange;
|
||||
yTickFormatter?: (value: number) => string;
|
||||
}
|
||||
|
||||
export interface NetworkDnsComponentReduxProps {
|
||||
activePage: number;
|
||||
sort: NetworkDnsSortField;
|
||||
|
@ -80,6 +105,7 @@ export class NetworkDnsComponentQuery extends QueryTemplatePaginated<
|
|||
const variables: GetNetworkDnsQuery.Variables = {
|
||||
defaultIndex: kibana.services.uiSettings.get<string[]>(DEFAULT_INDEX_KEY),
|
||||
filterQuery: createFilter(filterQuery),
|
||||
isDNSHistogram: false,
|
||||
inspect: isInspected,
|
||||
isPtrIncluded,
|
||||
pagination: generateTablePaginationOptions(activePage, limit),
|
||||
|
@ -160,12 +186,12 @@ const makeMapStateToProps = () => {
|
|||
const makeMapHistogramStateToProps = () => {
|
||||
const getNetworkDnsSelector = networkSelectors.dnsSelector();
|
||||
const getQuery = inputsSelectors.globalQueryByIdSelector();
|
||||
const mapStateToProps = (state: State, { id = HISTOGRAM_ID }: OwnProps) => {
|
||||
const mapStateToProps = (state: State, { id = HISTOGRAM_ID, limit }: DnsHistogramOwnProps) => {
|
||||
const { isInspected } = getQuery(state, id);
|
||||
return {
|
||||
...getNetworkDnsSelector(state),
|
||||
activePage: DEFAULT_TABLE_ACTIVE_PAGE,
|
||||
limit: DEFAULT_TABLE_LIMIT,
|
||||
limit,
|
||||
isInspected,
|
||||
id,
|
||||
};
|
||||
|
@ -179,7 +205,7 @@ export const NetworkDnsQuery = compose<React.ComponentClass<OwnProps>>(
|
|||
withKibana
|
||||
)(NetworkDnsComponentQuery);
|
||||
|
||||
export const NetworkDnsHistogramQuery = compose<React.ComponentClass<OwnProps>>(
|
||||
export const NetworkDnsHistogramQuery = compose<React.ComponentClass<DnsHistogramOwnProps>>(
|
||||
connect(makeMapHistogramStateToProps),
|
||||
withKibana
|
||||
)(NetworkDnsComponentQuery);
|
||||
)(MatrixHistogram);
|
||||
|
|
|
@ -703,6 +703,12 @@
|
|||
"ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "stackByField",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
|
@ -714,7 +720,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "AnomaliesOverTime",
|
||||
"name": "AnomaliesHistogram",
|
||||
"description": "",
|
||||
"args": [
|
||||
{
|
||||
|
@ -750,6 +756,12 @@
|
|||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "stackByField",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
|
@ -822,7 +834,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "AuthenticationsOverTime",
|
||||
"name": "AuthenticationsHistogram",
|
||||
"description": "",
|
||||
"args": [
|
||||
{
|
||||
|
@ -858,6 +870,12 @@
|
|||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "stackByField",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
|
@ -1058,7 +1076,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "EventsOverTime",
|
||||
"name": "EventsHistogram",
|
||||
"description": "",
|
||||
"args": [
|
||||
{
|
||||
|
@ -1094,6 +1112,12 @@
|
|||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "stackByField",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
|
@ -1834,6 +1858,12 @@
|
|||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "stackByField",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "timerange",
|
||||
"description": "",
|
||||
|
@ -2599,7 +2629,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "alertsOverTimeByModule",
|
||||
"name": "matrixHistogramData",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
|
@ -2752,7 +2782,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "anomaliesOverTime",
|
||||
"name": "matrixHistogramData",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
|
@ -3516,7 +3546,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "authenticationsOverTime",
|
||||
"name": "matrixHistogramData",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
|
@ -6235,7 +6265,7 @@
|
|||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "eventsOverTime",
|
||||
"name": "matrixHistogramData",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
|
|
|
@ -459,11 +459,11 @@ export interface Source {
|
|||
|
||||
AlertsHistogram: AlertsOverTimeData;
|
||||
|
||||
AnomaliesOverTime: AnomaliesOverTimeData;
|
||||
AnomaliesHistogram: AnomaliesOverTimeData;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications: AuthenticationsData;
|
||||
|
||||
AuthenticationsOverTime: AuthenticationsOverTimeData;
|
||||
AuthenticationsHistogram: AuthenticationsOverTimeData;
|
||||
|
||||
Timeline: TimelineData;
|
||||
|
||||
|
@ -471,7 +471,7 @@ export interface Source {
|
|||
|
||||
LastEventTime: LastEventTimeData;
|
||||
|
||||
EventsOverTime: EventsOverTimeData;
|
||||
EventsHistogram: EventsOverTimeData;
|
||||
/** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */
|
||||
Hosts: HostsData;
|
||||
|
||||
|
@ -563,7 +563,7 @@ export interface IndexField {
|
|||
export interface AlertsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
alertsOverTimeByModule: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ export interface MatrixOverTimeHistogramData {
|
|||
export interface AnomaliesOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
anomaliesOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -727,7 +727,7 @@ export interface PageInfoPaginated {
|
|||
export interface AuthenticationsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
authenticationsOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -1311,7 +1311,7 @@ export interface LastEventTimeData {
|
|||
export interface EventsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
eventsOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -2153,13 +2153,17 @@ export interface AlertsHistogramSourceArgs {
|
|||
defaultIndex: string[];
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface AnomaliesOverTimeSourceArgs {
|
||||
export interface AnomaliesHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface AuthenticationsSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
@ -2170,12 +2174,14 @@ export interface AuthenticationsSourceArgs {
|
|||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface AuthenticationsOverTimeSourceArgs {
|
||||
export interface AuthenticationsHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface TimelineSourceArgs {
|
||||
pagination: PaginationInput;
|
||||
|
@ -2206,12 +2212,14 @@ export interface LastEventTimeSourceArgs {
|
|||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface EventsOverTimeSourceArgs {
|
||||
export interface EventsHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface HostsSourceArgs {
|
||||
id?: Maybe<string>;
|
||||
|
@ -2340,6 +2348,8 @@ export interface NetworkDnsSourceArgs {
|
|||
|
||||
sort: NetworkDnsSortField;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
@ -2455,162 +2465,6 @@ export interface DeleteTimelineMutationArgs {
|
|||
// Documents
|
||||
// ====================================================
|
||||
|
||||
export namespace GetAlertsOverTimeQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
timerange: TimerangeInput;
|
||||
defaultIndex: string[];
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
|
||||
source: Source;
|
||||
};
|
||||
|
||||
export type Source = {
|
||||
__typename?: 'Source';
|
||||
|
||||
id: string;
|
||||
|
||||
AlertsHistogram: AlertsHistogram;
|
||||
};
|
||||
|
||||
export type AlertsHistogram = {
|
||||
__typename?: 'AlertsOverTimeData';
|
||||
|
||||
alertsOverTimeByModule: AlertsOverTimeByModule[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<Inspect>;
|
||||
};
|
||||
|
||||
export type AlertsOverTimeByModule = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export namespace GetAnomaliesOverTimeQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
timerange: TimerangeInput;
|
||||
defaultIndex: string[];
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
|
||||
source: Source;
|
||||
};
|
||||
|
||||
export type Source = {
|
||||
__typename?: 'Source';
|
||||
|
||||
id: string;
|
||||
|
||||
AnomaliesOverTime: AnomaliesOverTime;
|
||||
};
|
||||
|
||||
export type AnomaliesOverTime = {
|
||||
__typename?: 'AnomaliesOverTimeData';
|
||||
|
||||
anomaliesOverTime: _AnomaliesOverTime[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<Inspect>;
|
||||
};
|
||||
|
||||
export type _AnomaliesOverTime = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export namespace GetAuthenticationsOverTimeQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
timerange: TimerangeInput;
|
||||
defaultIndex: string[];
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
|
||||
source: Source;
|
||||
};
|
||||
|
||||
export type Source = {
|
||||
__typename?: 'Source';
|
||||
|
||||
id: string;
|
||||
|
||||
AuthenticationsOverTime: AuthenticationsOverTime;
|
||||
};
|
||||
|
||||
export type AuthenticationsOverTime = {
|
||||
__typename?: 'AuthenticationsOverTimeData';
|
||||
|
||||
authenticationsOverTime: _AuthenticationsOverTime[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<Inspect>;
|
||||
};
|
||||
|
||||
export type _AuthenticationsOverTime = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export namespace GetAuthenticationsQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
|
@ -2750,58 +2604,6 @@ export namespace GetAuthenticationsQuery {
|
|||
};
|
||||
}
|
||||
|
||||
export namespace GetEventsOverTimeQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
timerange: TimerangeInput;
|
||||
defaultIndex: string[];
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
|
||||
source: Source;
|
||||
};
|
||||
|
||||
export type Source = {
|
||||
__typename?: 'Source';
|
||||
|
||||
id: string;
|
||||
|
||||
EventsOverTime: EventsOverTime;
|
||||
};
|
||||
|
||||
export type EventsOverTime = {
|
||||
__typename?: 'EventsOverTimeData';
|
||||
|
||||
eventsOverTime: _EventsOverTime[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<Inspect>;
|
||||
};
|
||||
|
||||
export type _EventsOverTime = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export namespace GetLastEventTimeQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
|
@ -3423,16 +3225,165 @@ export namespace GetKpiNetworkQuery {
|
|||
};
|
||||
}
|
||||
|
||||
export namespace GetMatrixHistogramQuery {
|
||||
export type Variables = {
|
||||
isAlertsHistogram: boolean;
|
||||
isAnomaliesHistogram: boolean;
|
||||
isAuthenticationsHistogram: boolean;
|
||||
defaultIndex: string[];
|
||||
isEventsType: boolean;
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
sourceId: string;
|
||||
stackByField?: Maybe<string>;
|
||||
timerange: TimerangeInput;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
__typename?: 'Query';
|
||||
|
||||
source: Source;
|
||||
};
|
||||
|
||||
export type Source = {
|
||||
__typename?: 'Source';
|
||||
|
||||
id: string;
|
||||
|
||||
AlertsHistogram: AlertsHistogram;
|
||||
|
||||
AnomaliesHistogram: AnomaliesHistogram;
|
||||
|
||||
AuthenticationsHistogram: AuthenticationsHistogram;
|
||||
|
||||
EventsHistogram: EventsHistogram;
|
||||
};
|
||||
|
||||
export type AlertsHistogram = {
|
||||
__typename?: 'AlertsOverTimeData';
|
||||
|
||||
matrixHistogramData: MatrixHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<Inspect>;
|
||||
};
|
||||
|
||||
export type MatrixHistogramData = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
|
||||
export type AnomaliesHistogram = {
|
||||
__typename?: 'AnomaliesOverTimeData';
|
||||
|
||||
matrixHistogramData: _MatrixHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<_Inspect>;
|
||||
};
|
||||
|
||||
export type _MatrixHistogramData = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type _Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
|
||||
export type AuthenticationsHistogram = {
|
||||
__typename?: 'AuthenticationsOverTimeData';
|
||||
|
||||
matrixHistogramData: __MatrixHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<__Inspect>;
|
||||
};
|
||||
|
||||
export type __MatrixHistogramData = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type __Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
|
||||
export type EventsHistogram = {
|
||||
__typename?: 'EventsOverTimeData';
|
||||
|
||||
matrixHistogramData: ___MatrixHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
|
||||
inspect: Maybe<___Inspect>;
|
||||
};
|
||||
|
||||
export type ___MatrixHistogramData = {
|
||||
__typename?: 'MatrixOverTimeHistogramData';
|
||||
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
};
|
||||
|
||||
export type ___Inspect = {
|
||||
__typename?: 'Inspect';
|
||||
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export namespace GetNetworkDnsQuery {
|
||||
export type Variables = {
|
||||
sourceId: string;
|
||||
sort: NetworkDnsSortField;
|
||||
isPtrIncluded: boolean;
|
||||
timerange: TimerangeInput;
|
||||
pagination: PaginationInputPaginated;
|
||||
filterQuery?: Maybe<string>;
|
||||
defaultIndex: string[];
|
||||
filterQuery?: Maybe<string>;
|
||||
inspect: boolean;
|
||||
isDNSHistogram: boolean;
|
||||
isPtrIncluded: boolean;
|
||||
pagination: PaginationInputPaginated;
|
||||
sort: NetworkDnsSortField;
|
||||
sourceId: string;
|
||||
stackByField?: Maybe<string>;
|
||||
timerange: TimerangeInput;
|
||||
};
|
||||
|
||||
export type Query = {
|
||||
|
|
|
@ -5,18 +5,48 @@
|
|||
*/
|
||||
|
||||
import { getOr } from 'lodash/fp';
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { AuthenticationTable } from '../../../components/page/hosts/authentications_table';
|
||||
import { manageQuery } from '../../../components/page/manage_query';
|
||||
import { AuthenticationsOverTimeHistogram } from '../../../components/page/hosts/authentications_over_time';
|
||||
import { AuthenticationsOverTimeQuery } from '../../../containers/authentications/authentications_over_time';
|
||||
import { AuthenticationsQuery } from '../../../containers/authentications';
|
||||
import { HostsComponentsQueryProps } from './types';
|
||||
import { hostsModel } from '../../../store/hosts';
|
||||
import {
|
||||
MatrixHistogramOption,
|
||||
MatrixHistogramMappingTypes,
|
||||
} from '../../../components/matrix_histogram/types';
|
||||
import { MatrixHistogramContainer } from '../../../containers/matrix_histogram';
|
||||
import { KpiHostsChartColors } from '../../../components/page/hosts/kpi_hosts/types';
|
||||
import { MatrixHistogramGqlQuery } from '../../../containers/matrix_histogram/index.gql_query';
|
||||
import * as i18n from '../translations';
|
||||
|
||||
const AuthenticationTableManage = manageQuery(AuthenticationTable);
|
||||
const AuthenticationsOverTimeManage = manageQuery(AuthenticationsOverTimeHistogram);
|
||||
const ID = 'authenticationsOverTimeQuery';
|
||||
const authStackByOptions: MatrixHistogramOption[] = [
|
||||
{
|
||||
text: i18n.NAVIGATION_AUTHENTICATIONS_STACK_BY_EVENT_TYPE,
|
||||
value: 'event.type',
|
||||
},
|
||||
];
|
||||
|
||||
enum AuthMatrixDataGroup {
|
||||
authSuccess = 'authentication_success',
|
||||
authFailure = 'authentication_failure',
|
||||
}
|
||||
|
||||
export const authMatrixDataMappingFields: MatrixHistogramMappingTypes = {
|
||||
[AuthMatrixDataGroup.authSuccess]: {
|
||||
key: AuthMatrixDataGroup.authSuccess,
|
||||
value: null,
|
||||
color: KpiHostsChartColors.authSuccess,
|
||||
},
|
||||
[AuthMatrixDataGroup.authFailure]: {
|
||||
key: AuthMatrixDataGroup.authFailure,
|
||||
value: null,
|
||||
color: KpiHostsChartColors.authFailure,
|
||||
},
|
||||
};
|
||||
|
||||
export const AuthenticationsQueryTabBody = ({
|
||||
deleteQuery,
|
||||
|
@ -27,68 +57,75 @@ export const AuthenticationsQueryTabBody = ({
|
|||
startDate,
|
||||
type,
|
||||
updateDateRange = () => {},
|
||||
}: HostsComponentsQueryProps) => (
|
||||
<>
|
||||
<AuthenticationsOverTimeQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
type={hostsModel.HostsType.page}
|
||||
>
|
||||
{({ authenticationsOverTime, loading, id, inspect, refetch, totalCount }) => (
|
||||
<AuthenticationsOverTimeManage
|
||||
data={authenticationsOverTime!}
|
||||
endDate={endDate}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
loading={loading}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
startDate={startDate}
|
||||
totalCount={totalCount}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
)}
|
||||
</AuthenticationsOverTimeQuery>
|
||||
<EuiSpacer size="l" />
|
||||
<AuthenticationsQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({
|
||||
authentications,
|
||||
totalCount,
|
||||
loading,
|
||||
pageInfo,
|
||||
loadPage,
|
||||
id,
|
||||
inspect,
|
||||
isInspected,
|
||||
refetch,
|
||||
}) => (
|
||||
<AuthenticationTableManage
|
||||
data={authentications}
|
||||
deleteQuery={deleteQuery}
|
||||
fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
isInspect={isInspected}
|
||||
loading={loading}
|
||||
loadPage={loadPage}
|
||||
refetch={refetch}
|
||||
showMorePagesIndicator={getOr(false, 'showMorePagesIndicator', pageInfo)}
|
||||
setQuery={setQuery}
|
||||
totalCount={totalCount}
|
||||
type={type}
|
||||
/>
|
||||
)}
|
||||
</AuthenticationsQuery>
|
||||
</>
|
||||
);
|
||||
}: HostsComponentsQueryProps) => {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (deleteQuery) {
|
||||
deleteQuery({ id: ID });
|
||||
}
|
||||
};
|
||||
}, [deleteQuery]);
|
||||
return (
|
||||
<>
|
||||
<MatrixHistogramContainer
|
||||
isAuthenticationsHistogram={true}
|
||||
dataKey="AuthenticationsHistogram"
|
||||
defaultStackByOption={authStackByOptions[0]}
|
||||
deleteQuery={deleteQuery}
|
||||
endDate={endDate}
|
||||
errorMessage={i18n.ERROR_FETCHING_AUTHENTICATIONS_DATA}
|
||||
filterQuery={filterQuery}
|
||||
id={ID}
|
||||
mapping={authMatrixDataMappingFields}
|
||||
query={MatrixHistogramGqlQuery}
|
||||
setQuery={setQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
stackByOptions={authStackByOptions}
|
||||
title={i18n.NAVIGATION_AUTHENTICATIONS_TITLE}
|
||||
type={hostsModel.HostsType.page}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
<EuiSpacer size="l" />
|
||||
<AuthenticationsQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({
|
||||
authentications,
|
||||
totalCount,
|
||||
loading,
|
||||
pageInfo,
|
||||
loadPage,
|
||||
id,
|
||||
inspect,
|
||||
isInspected,
|
||||
refetch,
|
||||
}) => (
|
||||
<AuthenticationTableManage
|
||||
data={authentications}
|
||||
deleteQuery={deleteQuery}
|
||||
fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
isInspect={isInspected}
|
||||
loading={loading}
|
||||
loadPage={loadPage}
|
||||
refetch={refetch}
|
||||
showMorePagesIndicator={getOr(false, 'showMorePagesIndicator', pageInfo)}
|
||||
setQuery={setQuery}
|
||||
totalCount={totalCount}
|
||||
type={type}
|
||||
/>
|
||||
)}
|
||||
</AuthenticationsQuery>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AuthenticationsQueryTabBody.displayName = 'AuthenticationsQueryTabBody';
|
||||
|
|
|
@ -4,50 +4,64 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { StatefulEventsViewer } from '../../../components/events_viewer';
|
||||
import { HostsComponentsQueryProps } from './types';
|
||||
import { manageQuery } from '../../../components/page/manage_query';
|
||||
import { EventsOverTimeHistogram } from '../../../components/page/hosts/events_over_time';
|
||||
import { EventsOverTimeQuery } from '../../../containers/events/events_over_time';
|
||||
import { hostsModel } from '../../../store/hosts';
|
||||
import { eventsDefaultModel } from '../../../components/events_viewer/default_model';
|
||||
import { MatrixHistogramOption } from '../../../components/matrix_histogram/types';
|
||||
import { MatrixHistogramContainer } from '../../../containers/matrix_histogram';
|
||||
import { MatrixHistogramGqlQuery } from '../../../containers/matrix_histogram/index.gql_query';
|
||||
import * as i18n from '../translations';
|
||||
|
||||
const HOSTS_PAGE_TIMELINE_ID = 'hosts-page';
|
||||
const EventsOverTimeManage = manageQuery(EventsOverTimeHistogram);
|
||||
const EVENTS_HISTOGRAM_ID = 'eventsOverTimeQuery';
|
||||
|
||||
const eventsStackByOptions: MatrixHistogramOption[] = [
|
||||
{
|
||||
text: i18n.NAVIGATION_EVENTS_STACK_BY_EVENT_ACTION,
|
||||
value: 'event.action',
|
||||
},
|
||||
];
|
||||
|
||||
export const EventsQueryTabBody = ({
|
||||
deleteQuery,
|
||||
endDate,
|
||||
filterQuery,
|
||||
setQuery,
|
||||
skip,
|
||||
startDate,
|
||||
updateDateRange = () => {},
|
||||
}: HostsComponentsQueryProps) => {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (deleteQuery) {
|
||||
deleteQuery({ id: EVENTS_HISTOGRAM_ID });
|
||||
}
|
||||
};
|
||||
}, [deleteQuery]);
|
||||
return (
|
||||
<>
|
||||
<EventsOverTimeQuery
|
||||
<MatrixHistogramContainer
|
||||
dataKey="EventsHistogram"
|
||||
defaultStackByOption={eventsStackByOptions[0]}
|
||||
deleteQuery={deleteQuery}
|
||||
endDate={endDate}
|
||||
isEventsType={true}
|
||||
errorMessage={i18n.ERROR_FETCHING_EVENTS_DATA}
|
||||
filterQuery={filterQuery}
|
||||
query={MatrixHistogramGqlQuery}
|
||||
setQuery={setQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
stackByOptions={eventsStackByOptions}
|
||||
startDate={startDate}
|
||||
type={hostsModel.HostsType.page}
|
||||
>
|
||||
{({ eventsOverTime, loading, id, inspect, refetch, totalCount }) => (
|
||||
<EventsOverTimeManage
|
||||
data={eventsOverTime!}
|
||||
endDate={endDate}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
loading={loading}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
startDate={startDate}
|
||||
totalCount={totalCount}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
)}
|
||||
</EventsOverTimeQuery>
|
||||
title={i18n.NAVIGATION_EVENTS_TITLE}
|
||||
updateDateRange={updateDateRange}
|
||||
id={EVENTS_HISTOGRAM_ID}
|
||||
/>
|
||||
<EuiSpacer size="l" />
|
||||
<StatefulEventsViewer
|
||||
defaultModel={eventsDefaultModel}
|
||||
|
|
|
@ -28,6 +28,13 @@ export const NAVIGATION_AUTHENTICATIONS_TITLE = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const NAVIGATION_AUTHENTICATIONS_STACK_BY_EVENT_TYPE = i18n.translate(
|
||||
'xpack.siem.hosts.navigation.authentications.stackByEventType',
|
||||
{
|
||||
defaultMessage: 'event type',
|
||||
}
|
||||
);
|
||||
|
||||
export const NAVIGATION_UNCOMMON_PROCESSES_TITLE = i18n.translate(
|
||||
'xpack.siem.hosts.navigation.uncommonProcessesTitle',
|
||||
{
|
||||
|
@ -46,6 +53,13 @@ export const NAVIGATION_EVENTS_TITLE = i18n.translate('xpack.siem.hosts.navigati
|
|||
defaultMessage: 'Events',
|
||||
});
|
||||
|
||||
export const NAVIGATION_EVENTS_STACK_BY_EVENT_ACTION = i18n.translate(
|
||||
'xpack.siem.hosts.navigation.eventsStackByEventAction',
|
||||
{
|
||||
defaultMessage: 'action',
|
||||
}
|
||||
);
|
||||
|
||||
export const NAVIGATION_ALERTS_TITLE = i18n.translate('xpack.siem.hosts.navigation.alertsTitle', {
|
||||
defaultMessage: 'Alerts',
|
||||
});
|
||||
|
@ -62,3 +76,17 @@ export const EMPTY_ACTION_PRIMARY = i18n.translate('xpack.siem.hosts.emptyAction
|
|||
export const EMPTY_ACTION_SECONDARY = i18n.translate('xpack.siem.hosts.emptyActionSecondary', {
|
||||
defaultMessage: 'Go to documentation',
|
||||
});
|
||||
|
||||
export const ERROR_FETCHING_AUTHENTICATIONS_DATA = i18n.translate(
|
||||
'xpack.siem.hosts.navigaton.matrixHistogram.errorFetchingAuthenticationsData',
|
||||
{
|
||||
defaultMessage: 'Failed to query authentications data',
|
||||
}
|
||||
);
|
||||
|
||||
export const ERROR_FETCHING_EVENTS_DATA = i18n.translate(
|
||||
'xpack.siem.hosts.navigaton.matrixHistogram.errorFetchingEventsData',
|
||||
{
|
||||
defaultMessage: 'Failed to query events data',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -4,21 +4,37 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { getOr } from 'lodash/fp';
|
||||
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
import { NetworkDnsTable } from '../../../components/page/network/network_dns_table';
|
||||
import { NetworkDnsQuery, NetworkDnsHistogramQuery } from '../../../containers/network_dns';
|
||||
import {
|
||||
NetworkDnsQuery,
|
||||
NetworkDnsHistogramQuery,
|
||||
HISTOGRAM_ID,
|
||||
} from '../../../containers/network_dns';
|
||||
import { manageQuery } from '../../../components/page/manage_query';
|
||||
|
||||
import { NetworkComponentQueryProps } from './types';
|
||||
import { NetworkDnsHistogram } from '../../../components/page/network/dns_histogram';
|
||||
import { networkModel } from '../../../store';
|
||||
import { MatrixHistogramOption } from '../../../components/matrix_histogram/types';
|
||||
import { networkDnsQuery } from '../../../containers/network_dns/index.gql_query';
|
||||
import * as i18n from '../translations';
|
||||
import { useFormatBytes } from '../../../components/formatted_bytes';
|
||||
|
||||
const NetworkDnsTableManage = manageQuery(NetworkDnsTable);
|
||||
const NetworkDnsHistogramManage = manageQuery(NetworkDnsHistogram);
|
||||
|
||||
const dnsStackByOptions: MatrixHistogramOption[] = [
|
||||
{
|
||||
text: i18n.NAVIGATION_DNS_STACK_BY_DOMAIN,
|
||||
value: 'dns.question.registered_domain',
|
||||
},
|
||||
];
|
||||
|
||||
export const DnsQueryTabBody = ({
|
||||
deleteQuery,
|
||||
endDate,
|
||||
filterQuery,
|
||||
skip,
|
||||
|
@ -26,32 +42,17 @@ export const DnsQueryTabBody = ({
|
|||
setQuery,
|
||||
type,
|
||||
updateDateRange = () => {},
|
||||
}: NetworkComponentQueryProps) => (
|
||||
<>
|
||||
<NetworkDnsHistogramQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({ totalCount, loading, id, inspect, refetch, histogram }) => (
|
||||
<NetworkDnsHistogramManage
|
||||
id={id}
|
||||
loading={loading}
|
||||
data={histogram}
|
||||
endDate={endDate}
|
||||
startDate={startDate}
|
||||
inspect={inspect}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
totalCount={totalCount}
|
||||
updateDateRange={updateDateRange}
|
||||
/>
|
||||
)}
|
||||
</NetworkDnsHistogramQuery>
|
||||
<EuiSpacer />
|
||||
}: NetworkComponentQueryProps) => {
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (deleteQuery) {
|
||||
deleteQuery({ id: HISTOGRAM_ID });
|
||||
}
|
||||
};
|
||||
}, [deleteQuery]);
|
||||
const formatBytes = useFormatBytes();
|
||||
|
||||
return (
|
||||
<NetworkDnsQuery
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
|
@ -70,25 +71,47 @@ export const DnsQueryTabBody = ({
|
|||
inspect,
|
||||
isInspected,
|
||||
refetch,
|
||||
histogram,
|
||||
}) => (
|
||||
<NetworkDnsTableManage
|
||||
data={networkDns}
|
||||
fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
isInspect={isInspected}
|
||||
loading={loading}
|
||||
loadPage={loadPage}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
showMorePagesIndicator={getOr(false, 'showMorePagesIndicator', pageInfo)}
|
||||
totalCount={totalCount}
|
||||
type={type}
|
||||
/>
|
||||
<>
|
||||
<NetworkDnsHistogramQuery
|
||||
dataKey={['NetworkDns', 'histogram']}
|
||||
defaultStackByOption={dnsStackByOptions[0]}
|
||||
endDate={endDate}
|
||||
errorMessage={i18n.ERROR_FETCHING_DNS_DATA}
|
||||
filterQuery={filterQuery}
|
||||
isDNSHistogram={true}
|
||||
limit={totalCount}
|
||||
query={networkDnsQuery}
|
||||
scaleType={ScaleType.Ordinal}
|
||||
setQuery={setQuery}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
stackByOptions={dnsStackByOptions}
|
||||
title={i18n.NAVIGATION_DNS_TITLE}
|
||||
type={networkModel.NetworkType.page}
|
||||
updateDateRange={updateDateRange}
|
||||
yTickFormatter={formatBytes}
|
||||
showLegend={false}
|
||||
/>
|
||||
<EuiSpacer />
|
||||
<NetworkDnsTableManage
|
||||
data={networkDns}
|
||||
fakeTotalCount={getOr(50, 'fakeTotalCount', pageInfo)}
|
||||
id={id}
|
||||
inspect={inspect}
|
||||
isInspect={isInspected}
|
||||
loading={loading}
|
||||
loadPage={loadPage}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
showMorePagesIndicator={getOr(false, 'showMorePagesIndicator', pageInfo)}
|
||||
totalCount={totalCount}
|
||||
type={type}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</NetworkDnsQuery>
|
||||
</>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
DnsQueryTabBody.displayName = 'DNSQueryTabBody';
|
||||
|
|
|
@ -133,14 +133,14 @@ const NetworkComponent = React.memo<NetworkComponentProps>(
|
|||
<EuiSpacer />
|
||||
|
||||
<NetworkRoutes
|
||||
to={to}
|
||||
filterQuery={filterQuery}
|
||||
isInitializing={isInitializing}
|
||||
from={from}
|
||||
type={networkModel.NetworkType.page}
|
||||
isInitializing={isInitializing}
|
||||
indexPattern={indexPattern}
|
||||
setQuery={setQuery}
|
||||
setAbsoluteRangeDatePicker={setAbsoluteRangeDatePicker}
|
||||
type={networkModel.NetworkType.page}
|
||||
to={to}
|
||||
networkPagePath={networkPagePath}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -35,6 +35,20 @@ export const NAVIGATION_DNS_TITLE = i18n.translate('xpack.siem.network.navigatio
|
|||
defaultMessage: 'DNS',
|
||||
});
|
||||
|
||||
export const NAVIGATION_DNS_STACK_BY_DOMAIN = i18n.translate(
|
||||
'xpack.siem.hosts.navigation.dns.stackByDomain',
|
||||
{
|
||||
defaultMessage: 'domain',
|
||||
}
|
||||
);
|
||||
|
||||
export const ERROR_FETCHING_DNS_DATA = i18n.translate(
|
||||
'xpack.siem.hosts.navigation.dns.histogram.errorFetchingDnsData',
|
||||
{
|
||||
defaultMessage: 'Failed to query DNS data',
|
||||
}
|
||||
);
|
||||
|
||||
export const NAVIGATION_TLS_TITLE = i18n.translate('xpack.siem.network.navigation.tlsTitle', {
|
||||
defaultMessage: 'TLS',
|
||||
});
|
||||
|
|
|
@ -31,6 +31,7 @@ export const createAlertsResolvers = (
|
|||
const options = {
|
||||
...createOptions(source, args, info),
|
||||
defaultIndex: args.defaultIndex,
|
||||
stackByField: args.stackByField,
|
||||
};
|
||||
return libs.alerts.getAlertsHistogramData(req, options);
|
||||
},
|
||||
|
|
|
@ -9,7 +9,7 @@ import gql from 'graphql-tag';
|
|||
export const alertsSchema = gql`
|
||||
type AlertsOverTimeData {
|
||||
inspect: Inspect
|
||||
alertsOverTimeByModule: [MatrixOverTimeHistogramData!]!
|
||||
matrixHistogramData: [MatrixOverTimeHistogramData!]!
|
||||
totalCount: Float!
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ export const alertsSchema = gql`
|
|||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
timerange: TimerangeInput!
|
||||
stackByField: String
|
||||
): AlertsOverTimeData!
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -15,7 +15,7 @@ export interface AnomaliesResolversDeps {
|
|||
}
|
||||
|
||||
type QueryAnomaliesOverTimeResolver = ChildResolverOf<
|
||||
AppResolverOf<SourceResolvers.AnomaliesOverTimeResolver>,
|
||||
AppResolverOf<SourceResolvers.AnomaliesHistogramResolver>,
|
||||
QuerySourceResolver
|
||||
>;
|
||||
|
||||
|
@ -23,14 +23,15 @@ export const createAnomaliesResolvers = (
|
|||
libs: AnomaliesResolversDeps
|
||||
): {
|
||||
Source: {
|
||||
AnomaliesOverTime: QueryAnomaliesOverTimeResolver;
|
||||
AnomaliesHistogram: QueryAnomaliesOverTimeResolver;
|
||||
};
|
||||
} => ({
|
||||
Source: {
|
||||
async AnomaliesOverTime(source, args, { req }, info) {
|
||||
async AnomaliesHistogram(source, args, { req }, info) {
|
||||
const options = {
|
||||
...createOptions(source, args, info),
|
||||
defaultIndex: args.defaultIndex,
|
||||
stackByField: args.stackByField,
|
||||
};
|
||||
return libs.anomalies.getAnomaliesOverTime(req, options);
|
||||
},
|
||||
|
|
|
@ -9,15 +9,16 @@ import gql from 'graphql-tag';
|
|||
export const anomaliesSchema = gql`
|
||||
type AnomaliesOverTimeData {
|
||||
inspect: Inspect
|
||||
anomaliesOverTime: [MatrixOverTimeHistogramData!]!
|
||||
matrixHistogramData: [MatrixOverTimeHistogramData!]!
|
||||
totalCount: Float!
|
||||
}
|
||||
|
||||
extend type Source {
|
||||
AnomaliesOverTime(
|
||||
AnomaliesHistogram(
|
||||
timerange: TimerangeInput!
|
||||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
stackByField: String
|
||||
): AnomaliesOverTimeData!
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -16,7 +16,7 @@ type QueryAuthenticationsResolver = ChildResolverOf<
|
|||
>;
|
||||
|
||||
type QueryAuthenticationsOverTimeResolver = ChildResolverOf<
|
||||
AppResolverOf<SourceResolvers.AuthenticationsOverTimeResolver>,
|
||||
AppResolverOf<SourceResolvers.AuthenticationsHistogramResolver>,
|
||||
QuerySourceResolver
|
||||
>;
|
||||
|
||||
|
@ -29,7 +29,7 @@ export const createAuthenticationsResolvers = (
|
|||
): {
|
||||
Source: {
|
||||
Authentications: QueryAuthenticationsResolver;
|
||||
AuthenticationsOverTime: QueryAuthenticationsOverTimeResolver;
|
||||
AuthenticationsHistogram: QueryAuthenticationsOverTimeResolver;
|
||||
};
|
||||
} => ({
|
||||
Source: {
|
||||
|
@ -37,10 +37,11 @@ export const createAuthenticationsResolvers = (
|
|||
const options = createOptionsPaginated(source, args, info);
|
||||
return libs.authentications.getAuthentications(req, options);
|
||||
},
|
||||
async AuthenticationsOverTime(source, args, { req }, info) {
|
||||
async AuthenticationsHistogram(source, args, { req }, info) {
|
||||
const options = {
|
||||
...createOptions(source, args, info),
|
||||
defaultIndex: args.defaultIndex,
|
||||
stackByField: args.stackByField,
|
||||
};
|
||||
return libs.authentications.getAuthenticationsOverTime(req, options);
|
||||
},
|
||||
|
|
|
@ -36,7 +36,7 @@ export const authenticationsSchema = gql`
|
|||
|
||||
type AuthenticationsOverTimeData {
|
||||
inspect: Inspect
|
||||
authenticationsOverTime: [MatrixOverTimeHistogramData!]!
|
||||
matrixHistogramData: [MatrixOverTimeHistogramData!]!
|
||||
totalCount: Float!
|
||||
}
|
||||
|
||||
|
@ -48,10 +48,11 @@ export const authenticationsSchema = gql`
|
|||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
): AuthenticationsData!
|
||||
AuthenticationsOverTime(
|
||||
AuthenticationsHistogram(
|
||||
timerange: TimerangeInput!
|
||||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
stackByField: String
|
||||
): AuthenticationsOverTimeData!
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -33,7 +33,7 @@ export interface EventsResolversDeps {
|
|||
}
|
||||
|
||||
type QueryEventsOverTimeResolver = ChildResolverOf<
|
||||
AppResolverOf<SourceResolvers.EventsOverTimeResolver>,
|
||||
AppResolverOf<SourceResolvers.EventsHistogramResolver>,
|
||||
QuerySourceResolver
|
||||
>;
|
||||
|
||||
|
@ -44,7 +44,7 @@ export const createEventsResolvers = (
|
|||
Timeline: QueryTimelineResolver;
|
||||
TimelineDetails: QueryTimelineDetailsResolver;
|
||||
LastEventTime: QueryLastEventTimeResolver;
|
||||
EventsOverTime: QueryEventsOverTimeResolver;
|
||||
EventsHistogram: QueryEventsOverTimeResolver;
|
||||
};
|
||||
} => ({
|
||||
Source: {
|
||||
|
@ -71,10 +71,11 @@ export const createEventsResolvers = (
|
|||
};
|
||||
return libs.events.getLastEventTimeData(req, options);
|
||||
},
|
||||
async EventsOverTime(source, args, { req }, info) {
|
||||
async EventsHistogram(source, args, { req }, info) {
|
||||
const options = {
|
||||
...createOptions(source, args, info),
|
||||
defaultIndex: args.defaultIndex,
|
||||
stackByField: args.stackByField,
|
||||
};
|
||||
return libs.events.getEventsOverTime(req, options);
|
||||
},
|
||||
|
|
|
@ -76,7 +76,7 @@ export const eventsSchema = gql`
|
|||
|
||||
type EventsOverTimeData {
|
||||
inspect: Inspect
|
||||
eventsOverTime: [MatrixOverTimeHistogramData!]!
|
||||
matrixHistogramData: [MatrixOverTimeHistogramData!]!
|
||||
totalCount: Float!
|
||||
}
|
||||
|
||||
|
@ -100,10 +100,11 @@ export const eventsSchema = gql`
|
|||
details: LastTimeDetails!
|
||||
defaultIndex: [String!]!
|
||||
): LastEventTimeData!
|
||||
EventsOverTime(
|
||||
EventsHistogram(
|
||||
timerange: TimerangeInput!
|
||||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
stackByField: String
|
||||
): EventsOverTimeData!
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -76,6 +76,7 @@ export const createNetworkResolvers = (
|
|||
...createOptionsPaginated(source, args, info),
|
||||
networkDnsSortField: args.sort,
|
||||
isPtrIncluded: args.isPtrIncluded,
|
||||
stackByField: args.stackByField,
|
||||
};
|
||||
return libs.network.getNetworkDns(req, options);
|
||||
},
|
||||
|
|
|
@ -223,6 +223,7 @@ export const networkSchema = gql`
|
|||
isPtrIncluded: Boolean!
|
||||
pagination: PaginationInputPaginated!
|
||||
sort: NetworkDnsSortField!
|
||||
stackByField: String
|
||||
timerange: TimerangeInput!
|
||||
defaultIndex: [String!]!
|
||||
): NetworkDnsData!
|
||||
|
|
|
@ -461,11 +461,11 @@ export interface Source {
|
|||
|
||||
AlertsHistogram: AlertsOverTimeData;
|
||||
|
||||
AnomaliesOverTime: AnomaliesOverTimeData;
|
||||
AnomaliesHistogram: AnomaliesOverTimeData;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications: AuthenticationsData;
|
||||
|
||||
AuthenticationsOverTime: AuthenticationsOverTimeData;
|
||||
AuthenticationsHistogram: AuthenticationsOverTimeData;
|
||||
|
||||
Timeline: TimelineData;
|
||||
|
||||
|
@ -473,7 +473,7 @@ export interface Source {
|
|||
|
||||
LastEventTime: LastEventTimeData;
|
||||
|
||||
EventsOverTime: EventsOverTimeData;
|
||||
EventsHistogram: EventsOverTimeData;
|
||||
/** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */
|
||||
Hosts: HostsData;
|
||||
|
||||
|
@ -565,7 +565,7 @@ export interface IndexField {
|
|||
export interface AlertsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
alertsOverTimeByModule: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ export interface MatrixOverTimeHistogramData {
|
|||
export interface AnomaliesOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
anomaliesOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -729,7 +729,7 @@ export interface PageInfoPaginated {
|
|||
export interface AuthenticationsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
authenticationsOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -1313,7 +1313,7 @@ export interface LastEventTimeData {
|
|||
export interface EventsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
eventsOverTime: MatrixOverTimeHistogramData[];
|
||||
matrixHistogramData: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
@ -2155,13 +2155,17 @@ export interface AlertsHistogramSourceArgs {
|
|||
defaultIndex: string[];
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface AnomaliesOverTimeSourceArgs {
|
||||
export interface AnomaliesHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface AuthenticationsSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
@ -2172,12 +2176,14 @@ export interface AuthenticationsSourceArgs {
|
|||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface AuthenticationsOverTimeSourceArgs {
|
||||
export interface AuthenticationsHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface TimelineSourceArgs {
|
||||
pagination: PaginationInput;
|
||||
|
@ -2208,12 +2214,14 @@ export interface LastEventTimeSourceArgs {
|
|||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface EventsOverTimeSourceArgs {
|
||||
export interface EventsHistogramSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
export interface HostsSourceArgs {
|
||||
id?: Maybe<string>;
|
||||
|
@ -2342,6 +2350,8 @@ export interface NetworkDnsSourceArgs {
|
|||
|
||||
sort: NetworkDnsSortField;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
@ -2800,11 +2810,11 @@ export namespace SourceResolvers {
|
|||
|
||||
AlertsHistogram?: AlertsHistogramResolver<AlertsOverTimeData, TypeParent, TContext>;
|
||||
|
||||
AnomaliesOverTime?: AnomaliesOverTimeResolver<AnomaliesOverTimeData, TypeParent, TContext>;
|
||||
AnomaliesHistogram?: AnomaliesHistogramResolver<AnomaliesOverTimeData, TypeParent, TContext>;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications?: AuthenticationsResolver<AuthenticationsData, TypeParent, TContext>;
|
||||
|
||||
AuthenticationsOverTime?: AuthenticationsOverTimeResolver<
|
||||
AuthenticationsHistogram?: AuthenticationsHistogramResolver<
|
||||
AuthenticationsOverTimeData,
|
||||
TypeParent,
|
||||
TContext
|
||||
|
@ -2816,7 +2826,7 @@ export namespace SourceResolvers {
|
|||
|
||||
LastEventTime?: LastEventTimeResolver<LastEventTimeData, TypeParent, TContext>;
|
||||
|
||||
EventsOverTime?: EventsOverTimeResolver<EventsOverTimeData, TypeParent, TContext>;
|
||||
EventsHistogram?: EventsHistogramResolver<EventsOverTimeData, TypeParent, TContext>;
|
||||
/** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */
|
||||
Hosts?: HostsResolver<HostsData, TypeParent, TContext>;
|
||||
|
||||
|
@ -2883,19 +2893,23 @@ export namespace SourceResolvers {
|
|||
defaultIndex: string[];
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export type AnomaliesOverTimeResolver<
|
||||
export type AnomaliesHistogramResolver<
|
||||
R = AnomaliesOverTimeData,
|
||||
Parent = Source,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext, AnomaliesOverTimeArgs>;
|
||||
export interface AnomaliesOverTimeArgs {
|
||||
> = Resolver<R, Parent, TContext, AnomaliesHistogramArgs>;
|
||||
export interface AnomaliesHistogramArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export type AuthenticationsResolver<
|
||||
|
@ -2913,17 +2927,19 @@ export namespace SourceResolvers {
|
|||
defaultIndex: string[];
|
||||
}
|
||||
|
||||
export type AuthenticationsOverTimeResolver<
|
||||
export type AuthenticationsHistogramResolver<
|
||||
R = AuthenticationsOverTimeData,
|
||||
Parent = Source,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext, AuthenticationsOverTimeArgs>;
|
||||
export interface AuthenticationsOverTimeArgs {
|
||||
> = Resolver<R, Parent, TContext, AuthenticationsHistogramArgs>;
|
||||
export interface AuthenticationsHistogramArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export type TimelineResolver<
|
||||
|
@ -2973,17 +2989,19 @@ export namespace SourceResolvers {
|
|||
defaultIndex: string[];
|
||||
}
|
||||
|
||||
export type EventsOverTimeResolver<
|
||||
export type EventsHistogramResolver<
|
||||
R = EventsOverTimeData,
|
||||
Parent = Source,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext, EventsOverTimeArgs>;
|
||||
export interface EventsOverTimeArgs {
|
||||
> = Resolver<R, Parent, TContext, EventsHistogramArgs>;
|
||||
export interface EventsHistogramArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export type HostsResolver<R = HostsData, Parent = Source, TContext = SiemContext> = Resolver<
|
||||
|
@ -3180,6 +3198,8 @@ export namespace SourceResolvers {
|
|||
|
||||
sort: NetworkDnsSortField;
|
||||
|
||||
stackByField?: Maybe<string>;
|
||||
|
||||
timerange: TimerangeInput;
|
||||
|
||||
defaultIndex: string[];
|
||||
|
@ -3443,7 +3463,7 @@ export namespace AlertsOverTimeDataResolvers {
|
|||
export interface Resolvers<TContext = SiemContext, TypeParent = AlertsOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
||||
alertsOverTimeByModule?: AlertsOverTimeByModuleResolver<
|
||||
matrixHistogramData?: MatrixHistogramDataResolver<
|
||||
MatrixOverTimeHistogramData[],
|
||||
TypeParent,
|
||||
TContext
|
||||
|
@ -3457,7 +3477,7 @@ export namespace AlertsOverTimeDataResolvers {
|
|||
Parent = AlertsOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type AlertsOverTimeByModuleResolver<
|
||||
export type MatrixHistogramDataResolver<
|
||||
R = MatrixOverTimeHistogramData[],
|
||||
Parent = AlertsOverTimeData,
|
||||
TContext = SiemContext
|
||||
|
@ -3518,7 +3538,7 @@ export namespace AnomaliesOverTimeDataResolvers {
|
|||
export interface Resolvers<TContext = SiemContext, TypeParent = AnomaliesOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
||||
anomaliesOverTime?: AnomaliesOverTimeResolver<
|
||||
matrixHistogramData?: MatrixHistogramDataResolver<
|
||||
MatrixOverTimeHistogramData[],
|
||||
TypeParent,
|
||||
TContext
|
||||
|
@ -3532,7 +3552,7 @@ export namespace AnomaliesOverTimeDataResolvers {
|
|||
Parent = AnomaliesOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type AnomaliesOverTimeResolver<
|
||||
export type MatrixHistogramDataResolver<
|
||||
R = MatrixOverTimeHistogramData[],
|
||||
Parent = AnomaliesOverTimeData,
|
||||
TContext = SiemContext
|
||||
|
@ -3993,7 +4013,7 @@ export namespace AuthenticationsOverTimeDataResolvers {
|
|||
export interface Resolvers<TContext = SiemContext, TypeParent = AuthenticationsOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
||||
authenticationsOverTime?: AuthenticationsOverTimeResolver<
|
||||
matrixHistogramData?: MatrixHistogramDataResolver<
|
||||
MatrixOverTimeHistogramData[],
|
||||
TypeParent,
|
||||
TContext
|
||||
|
@ -4007,7 +4027,7 @@ export namespace AuthenticationsOverTimeDataResolvers {
|
|||
Parent = AuthenticationsOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type AuthenticationsOverTimeResolver<
|
||||
export type MatrixHistogramDataResolver<
|
||||
R = MatrixOverTimeHistogramData[],
|
||||
Parent = AuthenticationsOverTimeData,
|
||||
TContext = SiemContext
|
||||
|
@ -5947,7 +5967,11 @@ export namespace EventsOverTimeDataResolvers {
|
|||
export interface Resolvers<TContext = SiemContext, TypeParent = EventsOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
||||
eventsOverTime?: EventsOverTimeResolver<MatrixOverTimeHistogramData[], TypeParent, TContext>;
|
||||
matrixHistogramData?: MatrixHistogramDataResolver<
|
||||
MatrixOverTimeHistogramData[],
|
||||
TypeParent,
|
||||
TContext
|
||||
>;
|
||||
|
||||
totalCount?: TotalCountResolver<number, TypeParent, TContext>;
|
||||
}
|
||||
|
@ -5957,7 +5981,7 @@ export namespace EventsOverTimeDataResolvers {
|
|||
Parent = EventsOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type EventsOverTimeResolver<
|
||||
export type MatrixHistogramDataResolver<
|
||||
R = MatrixOverTimeHistogramData[],
|
||||
Parent = EventsOverTimeData,
|
||||
TContext = SiemContext
|
||||
|
|
|
@ -10,7 +10,7 @@ import { AlertsOverTimeData, MatrixOverTimeHistogramData } from '../../graphql/t
|
|||
|
||||
import { inspectStringifyObject } from '../../utils/build_query';
|
||||
|
||||
import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkAdapter, FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
import { buildAlertsHistogramQuery } from './query.dsl';
|
||||
|
||||
import { AlertsAdapter, AlertsGroupData, AlertsBucket } from './types';
|
||||
|
@ -22,7 +22,7 @@ export class ElasticsearchAlertsAdapter implements AlertsAdapter {
|
|||
|
||||
public async getAlertsHistogramData(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AlertsOverTimeData> {
|
||||
const dsl = buildAlertsHistogramQuery(options);
|
||||
const response = await this.framework.callWithRequest<EventHit, TermAggregation>(
|
||||
|
@ -31,14 +31,14 @@ export class ElasticsearchAlertsAdapter implements AlertsAdapter {
|
|||
dsl
|
||||
);
|
||||
const totalCount = getOr(0, 'hits.total.value', response);
|
||||
const alertsOverTimeByModule = getOr([], 'aggregations.alertsByModuleGroup.buckets', response);
|
||||
const matrixHistogramData = getOr([], 'aggregations.alertsByModuleGroup.buckets', response);
|
||||
const inspect = {
|
||||
dsl: [inspectStringifyObject(dsl)],
|
||||
response: [inspectStringifyObject(response)],
|
||||
};
|
||||
return {
|
||||
inspect,
|
||||
alertsOverTimeByModule: getAlertsOverTimeByModule(alertsOverTimeByModule),
|
||||
matrixHistogramData: getAlertsOverTimeByModule(matrixHistogramData),
|
||||
totalCount,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkAdapter, FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { ElasticsearchAlertsAdapter } from './elasticsearch_adapter';
|
||||
|
@ -41,11 +41,11 @@ describe('alerts elasticsearch_adapter', () => {
|
|||
const EsNetworkTimelineAlerts = new ElasticsearchAlertsAdapter(mockFramework);
|
||||
const data = await EsNetworkTimelineAlerts.getAlertsHistogramData(
|
||||
(mockRequest as unknown) as FrameworkRequest,
|
||||
(mockOptions as unknown) as RequestBasicOptions
|
||||
(mockOptions as unknown) as MatrixHistogramRequestOptions
|
||||
);
|
||||
|
||||
expect(data).to.eql({
|
||||
alertsOverTimeByModule: mockAlertsHistogramDataFormattedResponse,
|
||||
matrixHistogramData: mockAlertsHistogramDataFormattedResponse,
|
||||
inspect: {
|
||||
dsl: ['"mockAlertsHistogramQueryDsl"'],
|
||||
response: [JSON.stringify(mockAlertsHistogramDataResponse, null, 2)],
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
export * from './elasticsearch_adapter';
|
||||
import { AlertsAdapter } from './types';
|
||||
import { AlertsOverTimeData } from '../../graphql/types';
|
||||
|
@ -14,7 +14,7 @@ export class Alerts {
|
|||
|
||||
public async getAlertsHistogramData(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AlertsOverTimeData> {
|
||||
return this.adapter.getAlertsHistogramData(req, options);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query';
|
||||
import { buildTimelineQuery } from '../events/query.dsl';
|
||||
import { RequestOptions, RequestBasicOptions } from '../framework';
|
||||
import { RequestOptions, MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
export const buildAlertsQuery = (options: RequestOptions) => {
|
||||
const eventsQuery = buildTimelineQuery(options);
|
||||
|
@ -35,7 +35,8 @@ export const buildAlertsHistogramQuery = ({
|
|||
sourceConfiguration: {
|
||||
fields: { timestamp },
|
||||
},
|
||||
}: RequestBasicOptions) => {
|
||||
stackByField,
|
||||
}: MatrixHistogramRequestOptions) => {
|
||||
const filter = [
|
||||
...createQueryFilterClauses(filterQuery),
|
||||
{
|
||||
|
@ -84,7 +85,7 @@ export const buildAlertsHistogramQuery = ({
|
|||
return {
|
||||
alertsByModuleGroup: {
|
||||
terms: {
|
||||
field: 'event.module',
|
||||
field: stackByField,
|
||||
missing: 'All others',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { AlertsOverTimeData } from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
export interface AlertsBucket {
|
||||
key: number;
|
||||
|
@ -22,6 +22,6 @@ export interface AlertsGroupData {
|
|||
export interface AlertsAdapter {
|
||||
getAlertsHistogramData(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AlertsOverTimeData>;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import { getOr } from 'lodash/fp';
|
|||
|
||||
import { AnomaliesOverTimeData } from '../../graphql/types';
|
||||
import { inspectStringifyObject } from '../../utils/build_query';
|
||||
import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkAdapter, FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
import { TermAggregation } from '../types';
|
||||
|
||||
import { AnomalyHit, AnomaliesAdapter, AnomaliesActionGroupData } from './types';
|
||||
|
@ -20,7 +20,7 @@ export class ElasticsearchAnomaliesAdapter implements AnomaliesAdapter {
|
|||
|
||||
public async getAnomaliesOverTime(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AnomaliesOverTimeData> {
|
||||
const dsl = buildAnomaliesOverTimeQuery(options);
|
||||
|
||||
|
@ -39,7 +39,7 @@ export class ElasticsearchAnomaliesAdapter implements AnomaliesAdapter {
|
|||
};
|
||||
return {
|
||||
inspect,
|
||||
anomaliesOverTime: getAnomaliesOverTimeByJobId(anomaliesOverTimeBucket),
|
||||
matrixHistogramData: getAnomaliesOverTimeByJobId(anomaliesOverTimeBucket),
|
||||
totalCount,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
export * from './elasticsearch_adapter';
|
||||
import { AnomaliesAdapter } from './types';
|
||||
import { AnomaliesOverTimeData } from '../../../public/graphql/types';
|
||||
|
@ -14,7 +14,7 @@ export class Anomalies {
|
|||
|
||||
public async getAnomaliesOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AnomaliesOverTimeData> {
|
||||
return this.adapter.getAnomaliesOverTime(req, options);
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
*/
|
||||
|
||||
import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query';
|
||||
import { RequestBasicOptions } from '../framework';
|
||||
import { MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
export const buildAnomaliesOverTimeQuery = ({
|
||||
filterQuery,
|
||||
timerange: { from, to },
|
||||
defaultIndex,
|
||||
}: RequestBasicOptions) => {
|
||||
stackByField = 'job_id',
|
||||
}: MatrixHistogramRequestOptions) => {
|
||||
const filter = [
|
||||
...createQueryFilterClauses(filterQuery),
|
||||
{
|
||||
|
@ -42,7 +43,7 @@ export const buildAnomaliesOverTimeQuery = ({
|
|||
return {
|
||||
anomalyActionGroup: {
|
||||
terms: {
|
||||
field: 'job_id',
|
||||
field: stackByField,
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
*/
|
||||
|
||||
import { AnomaliesOverTimeData } from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
import { SearchHit } from '../types';
|
||||
|
||||
export interface AnomaliesAdapter {
|
||||
getAnomaliesOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AnomaliesOverTimeData>;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
FrameworkAdapter,
|
||||
FrameworkRequest,
|
||||
RequestOptionsPaginated,
|
||||
RequestBasicOptions,
|
||||
MatrixHistogramRequestOptions,
|
||||
} from '../framework';
|
||||
import { TermAggregation } from '../types';
|
||||
import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants';
|
||||
|
@ -112,7 +112,7 @@ export class ElasticsearchAuthenticationAdapter implements AuthenticationsAdapte
|
|||
|
||||
public async getAuthenticationsOverTime(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AuthenticationsOverTimeData> {
|
||||
const dsl = buildAuthenticationsOverTimeQuery(options);
|
||||
const response = await this.framework.callWithRequest<AuthenticationHit, TermAggregation>(
|
||||
|
@ -132,7 +132,7 @@ export class ElasticsearchAuthenticationAdapter implements AuthenticationsAdapte
|
|||
};
|
||||
return {
|
||||
inspect,
|
||||
authenticationsOverTime: getAuthenticationsOverTimeByAuthenticationResult(
|
||||
matrixHistogramData: getAuthenticationsOverTimeByAuthenticationResult(
|
||||
authenticationsOverTimeBucket
|
||||
),
|
||||
totalCount,
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
*/
|
||||
|
||||
import { AuthenticationsData } from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestOptionsPaginated, RequestBasicOptions } from '../framework';
|
||||
import {
|
||||
FrameworkRequest,
|
||||
RequestOptionsPaginated,
|
||||
MatrixHistogramRequestOptions,
|
||||
} from '../framework';
|
||||
|
||||
import { AuthenticationsAdapter } from './types';
|
||||
import { AuthenticationsOverTimeData } from '../../../public/graphql/types';
|
||||
|
@ -22,7 +26,7 @@ export class Authentications {
|
|||
|
||||
public async getAuthenticationsOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AuthenticationsOverTimeData> {
|
||||
return this.adapter.getAuthenticationsOverTime(req, options);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query';
|
||||
import { RequestBasicOptions } from '../framework';
|
||||
import { MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
export const buildAuthenticationsOverTimeQuery = ({
|
||||
filterQuery,
|
||||
|
@ -13,7 +13,8 @@ export const buildAuthenticationsOverTimeQuery = ({
|
|||
sourceConfiguration: {
|
||||
fields: { timestamp },
|
||||
},
|
||||
}: RequestBasicOptions) => {
|
||||
stackByField = 'event.type',
|
||||
}: MatrixHistogramRequestOptions) => {
|
||||
const filter = [
|
||||
...createQueryFilterClauses(filterQuery),
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ export const buildAuthenticationsOverTimeQuery = ({
|
|||
return {
|
||||
eventActionGroup: {
|
||||
terms: {
|
||||
field: 'event.type',
|
||||
field: stackByField,
|
||||
include: ['authentication_success', 'authentication_failure'],
|
||||
order: {
|
||||
_count: 'desc',
|
||||
|
|
|
@ -9,7 +9,11 @@ import {
|
|||
AuthenticationsOverTimeData,
|
||||
LastSourceHost,
|
||||
} from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestOptionsPaginated, RequestBasicOptions } from '../framework';
|
||||
import {
|
||||
FrameworkRequest,
|
||||
RequestOptionsPaginated,
|
||||
MatrixHistogramRequestOptions,
|
||||
} from '../framework';
|
||||
import { Hit, SearchHit, TotalHit } from '../types';
|
||||
|
||||
export interface AuthenticationsAdapter {
|
||||
|
@ -19,7 +23,7 @@ export interface AuthenticationsAdapter {
|
|||
): Promise<AuthenticationsData>;
|
||||
getAuthenticationsOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<AuthenticationsOverTimeData>;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import { baseCategoryFields } from '../../utils/beat_schema/8.0.0';
|
|||
import { reduceFields } from '../../utils/build_query/reduce_fields';
|
||||
import { mergeFieldsWithHit, inspectStringifyObject } from '../../utils/build_query';
|
||||
import { eventFieldsMap } from '../ecs_fields';
|
||||
import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { FrameworkAdapter, FrameworkRequest, MatrixHistogramRequestOptions } from '../framework';
|
||||
import { TermAggregation } from '../types';
|
||||
|
||||
import { buildDetailsQuery, buildTimelineQuery } from './query.dsl';
|
||||
|
@ -131,7 +131,7 @@ export class ElasticsearchEventsAdapter implements EventsAdapter {
|
|||
|
||||
public async getEventsOverTime(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
options: MatrixHistogramRequestOptions
|
||||
): Promise<EventsOverTimeData> {
|
||||
const dsl = buildEventsOverTimeQuery(options);
|
||||
const response = await this.framework.callWithRequest<EventHit, TermAggregation>(
|
||||
|
@ -147,7 +147,7 @@ export class ElasticsearchEventsAdapter implements EventsAdapter {
|
|||
};
|
||||
return {
|
||||
inspect,
|
||||
eventsOverTime: getEventsOverTimeByActionName(eventsOverTimeBucket),
|
||||
matrixHistogramData: getEventsOverTimeByActionName(eventsOverTimeBucket),
|
||||
totalCount,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query';
|
||||
import { RequestBasicOptions } from '../framework';
|
||||
import { MatrixHistogramRequestOptions } from '../framework';
|
||||
|
||||
export const buildEventsOverTimeQuery = ({
|
||||
filterQuery,
|
||||
|
@ -13,7 +13,8 @@ export const buildEventsOverTimeQuery = ({
|
|||
sourceConfiguration: {
|
||||
fields: { timestamp },
|
||||
},
|
||||
}: RequestBasicOptions) => {
|
||||
stackByField = 'event.action',
|
||||
}: MatrixHistogramRequestOptions) => {
|
||||
const filter = [
|
||||
...createQueryFilterClauses(filterQuery),
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ export const buildEventsOverTimeQuery = ({
|
|||
return {
|
||||
eventActionGroup: {
|
||||
terms: {
|
||||
field: 'event.action',
|
||||
field: stackByField,
|
||||
missing: 'All others',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
SortField,
|
||||
SourceConfiguration,
|
||||
TimerangeInput,
|
||||
Maybe,
|
||||
} from '../../graphql/types';
|
||||
import { RequestFacade } from '../../types';
|
||||
|
||||
|
@ -130,6 +131,10 @@ export interface RequestBasicOptions {
|
|||
defaultIndex: string[];
|
||||
}
|
||||
|
||||
export interface MatrixHistogramRequestOptions extends RequestBasicOptions {
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface RequestOptions extends RequestBasicOptions {
|
||||
pagination: PaginationInput;
|
||||
fields: readonly string[];
|
||||
|
|
|
@ -41,6 +41,7 @@ export interface NetworkHttpRequestOptions extends RequestOptionsPaginated {
|
|||
export interface NetworkDnsRequestOptions extends RequestOptionsPaginated {
|
||||
isPtrIncluded: boolean;
|
||||
networkDnsSortField: NetworkDnsSortField;
|
||||
stackByField?: Maybe<string>;
|
||||
}
|
||||
|
||||
export class Network {
|
||||
|
|
|
@ -64,6 +64,7 @@ export const buildDnsQuery = ({
|
|||
sourceConfiguration: {
|
||||
fields: { timestamp },
|
||||
},
|
||||
stackByField = 'dns.question.registered_domain',
|
||||
timerange: { from, to },
|
||||
}: NetworkDnsRequestOptions) => {
|
||||
const filter = [
|
||||
|
@ -87,7 +88,7 @@ export const buildDnsQuery = ({
|
|||
...getCountAgg(),
|
||||
dns_name_query_count: {
|
||||
terms: {
|
||||
field: 'dns.question.registered_domain',
|
||||
field: stackByField,
|
||||
size: querySize,
|
||||
order: {
|
||||
...getQueryOrder(networkDnsSortField),
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestOptionsPaginated } from '../framework';
|
||||
import { TotalValue } from '../types';
|
||||
import { NetworkDnsRequestOptions } from '.';
|
||||
|
||||
export interface NetworkAdapter {
|
||||
getNetworkTopCountries(
|
||||
|
@ -22,7 +23,7 @@ export interface NetworkAdapter {
|
|||
req: FrameworkRequest,
|
||||
options: RequestOptionsPaginated
|
||||
): Promise<NetworkTopNFlowData>;
|
||||
getNetworkDns(req: FrameworkRequest, options: RequestOptionsPaginated): Promise<NetworkDnsData>;
|
||||
getNetworkDns(req: FrameworkRequest, options: NetworkDnsRequestOptions): Promise<NetworkDnsData>;
|
||||
getNetworkHttp(req: FrameworkRequest, options: RequestOptionsPaginated): Promise<NetworkHttpData>;
|
||||
}
|
||||
|
||||
|
|
|
@ -11000,8 +11000,6 @@
|
|||
"xpack.siem.auditd.violatedSeLinuxPolicyDescription": "selinuxポリシーに違反しました",
|
||||
"xpack.siem.auditd.wasAuthorizedToUseDescription": "が以下の使用を承認されました:",
|
||||
"xpack.siem.auditd.withResultDescription": "結果付き",
|
||||
"xpack.siem.authenticationsOverTime.authenticationCountTitle": "認証カウント",
|
||||
"xpack.siem.authenticationsOverTime.unit": "{totalCount, plural, =1 {authentication} other {authentications}}",
|
||||
"xpack.siem.authenticationsTable.authenticationFailures": "認証",
|
||||
"xpack.siem.authenticationsTable.failures": "失敗",
|
||||
"xpack.siem.authenticationsTable.lastFailedDestination": "前回失敗したデスティネーション",
|
||||
|
@ -11135,9 +11133,6 @@
|
|||
"xpack.siem.eventDetails.table": "表",
|
||||
"xpack.siem.eventDetails.toggleColumnTooltip": "列を切り替えます",
|
||||
"xpack.siem.eventDetails.value": "値",
|
||||
"xpack.siem.eventsOverTime.eventCountFrequencyByActionTitle": "アクション別のイベントカウント",
|
||||
"xpack.siem.eventsOverTime.showing": "表示中",
|
||||
"xpack.siem.eventsOverTime.unit": "{totalCount, plural, =1 {event} other {events}}",
|
||||
"xpack.siem.eventsViewer.eventsLabel": "イベント",
|
||||
"xpack.siem.eventsViewer.showingLabel": "表示中",
|
||||
"xpack.siem.eventsViewer.unit": "{totalCount, plural, =1 {event} other {events}}",
|
||||
|
@ -13306,4 +13301,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "フィールドを選択してください。",
|
||||
"xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10999,8 +10999,6 @@
|
|||
"xpack.siem.auditd.violatedSeLinuxPolicyDescription": "已违反 selinux 策略",
|
||||
"xpack.siem.auditd.wasAuthorizedToUseDescription": "有权使用",
|
||||
"xpack.siem.auditd.withResultDescription": ",结果为",
|
||||
"xpack.siem.authenticationsOverTime.authenticationCountTitle": "身份验证计数",
|
||||
"xpack.siem.authenticationsOverTime.unit": "{totalCount, plural, =1 {个身份验证} other {个身份验证}}",
|
||||
"xpack.siem.authenticationsTable.authenticationFailures": "身份验证",
|
||||
"xpack.siem.authenticationsTable.failures": "失败",
|
||||
"xpack.siem.authenticationsTable.lastFailedDestination": "上一失败目标",
|
||||
|
@ -11134,9 +11132,6 @@
|
|||
"xpack.siem.eventDetails.table": "表",
|
||||
"xpack.siem.eventDetails.toggleColumnTooltip": "切换列",
|
||||
"xpack.siem.eventDetails.value": "值",
|
||||
"xpack.siem.eventsOverTime.eventCountFrequencyByActionTitle": "事件计数 - 按操作",
|
||||
"xpack.siem.eventsOverTime.showing": "显示",
|
||||
"xpack.siem.eventsOverTime.unit": "{totalCount, plural, =1 {个事件} other {个事件}}",
|
||||
"xpack.siem.eventsViewer.eventsLabel": "事件",
|
||||
"xpack.siem.eventsViewer.showingLabel": "显示",
|
||||
"xpack.siem.eventsViewer.unit": "{totalCount, plural, =1 {个事件} other {个事件}}",
|
||||
|
@ -13305,4 +13300,4 @@
|
|||
"xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "此字段必填。",
|
||||
"xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { EventsOverTimeGqlQuery } from '../../../../legacy/plugins/siem/public/containers/events/events_over_time/events_over_time.gql_query';
|
||||
import { GetEventsOverTimeQuery } from '../../../../legacy/plugins/siem/public/graphql/types';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const client = getService('siemGraphQLClient');
|
||||
const FROM = new Date('2000-01-01T00:00:00.000Z').valueOf();
|
||||
const TO = new Date('3000-01-01T00:00:00.000Z').valueOf();
|
||||
describe('Events over time', () => {
|
||||
describe('With filebeat', () => {
|
||||
before(() => esArchiver.load('filebeat/default'));
|
||||
after(() => esArchiver.unload('filebeat/default'));
|
||||
|
||||
it('Make sure that we get events over time data', () => {
|
||||
return client
|
||||
.query<GetEventsOverTimeQuery.Query>({
|
||||
query: EventsOverTimeGqlQuery,
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
inspect: false,
|
||||
},
|
||||
})
|
||||
.then(resp => {
|
||||
const expectedData = [
|
||||
{
|
||||
x: new Date('2018-12-20T00:00:00.000Z').valueOf(),
|
||||
y: 4884,
|
||||
g: 'All others',
|
||||
__typename: 'MatrixOverTimeHistogramData',
|
||||
},
|
||||
{
|
||||
x: new Date('2018-12-20T00:00:00.000Z').valueOf(),
|
||||
y: 1273,
|
||||
g: 'netflow_flow',
|
||||
__typename: 'MatrixOverTimeHistogramData',
|
||||
},
|
||||
];
|
||||
const eventsOverTime = resp.data.source.EventsOverTime;
|
||||
expect(eventsOverTime.eventsOverTime).to.eql(expectedData);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('With packetbeat', () => {
|
||||
before(() => esArchiver.load('packetbeat/default'));
|
||||
after(() => esArchiver.unload('packetbeat/default'));
|
||||
|
||||
it('Make sure that we get events over time data', () => {
|
||||
return client
|
||||
.query<GetEventsOverTimeQuery.Query>({
|
||||
query: EventsOverTimeGqlQuery,
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
inspect: false,
|
||||
},
|
||||
})
|
||||
.then(resp => {
|
||||
const expectedData = [
|
||||
{
|
||||
x: new Date('2018-12-20T00:00:00.000Z').valueOf(),
|
||||
y: 4884,
|
||||
g: 'All others',
|
||||
__typename: 'MatrixOverTimeHistogramData',
|
||||
},
|
||||
{
|
||||
x: new Date('2018-12-20T00:00:00.000Z').valueOf(),
|
||||
y: 1273,
|
||||
g: 'netflow_flow',
|
||||
__typename: 'MatrixOverTimeHistogramData',
|
||||
},
|
||||
];
|
||||
const eventsOverTime = resp.data.source.EventsOverTime;
|
||||
expect(eventsOverTime.eventsOverTime).to.eql(expectedData);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
export default function({ loadTestFile }) {
|
||||
describe('Siem GraphQL Endpoints', () => {
|
||||
loadTestFile(require.resolve('./authentications'));
|
||||
loadTestFile(require.resolve('./events_over_time'));
|
||||
loadTestFile(require.resolve('./hosts'));
|
||||
loadTestFile(require.resolve('./kpi_network'));
|
||||
loadTestFile(require.resolve('./kpi_hosts'));
|
||||
|
|
|
@ -29,22 +29,24 @@ export default function({ getService }: FtrProviderContext) {
|
|||
.query<GetNetworkDnsQuery.Query>({
|
||||
query: networkDnsQuery,
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
isDNSHistogram: false,
|
||||
inspect: false,
|
||||
isPtrIncluded: false,
|
||||
sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.asc },
|
||||
pagination: {
|
||||
activePage: 0,
|
||||
cursorStart: 0,
|
||||
fakePossibleCount: 30,
|
||||
querySize: 10,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
inspect: false,
|
||||
sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.asc },
|
||||
sourceId: 'default',
|
||||
stackByField: 'dns.question.registered_domain',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(resp => {
|
||||
|
@ -63,22 +65,24 @@ export default function({ getService }: FtrProviderContext) {
|
|||
.query<GetNetworkDnsQuery.Query>({
|
||||
query: networkDnsQuery,
|
||||
variables: {
|
||||
sourceId: 'default',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
isDNSHistogram: false,
|
||||
inspect: false,
|
||||
isPtrIncluded: false,
|
||||
sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.desc },
|
||||
pagination: {
|
||||
activePage: 0,
|
||||
cursorStart: 0,
|
||||
fakePossibleCount: 30,
|
||||
querySize: 10,
|
||||
},
|
||||
defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
|
||||
inspect: false,
|
||||
sourceId: 'default',
|
||||
sort: { field: NetworkDnsFields.uniqueDomains, direction: Direction.desc },
|
||||
stackByField: 'dns.question.registered_domain',
|
||||
timerange: {
|
||||
interval: '12h',
|
||||
to: TO,
|
||||
from: FROM,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(resp => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue