mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
parent
60696a08b1
commit
71a7f8a7ea
42 changed files with 1235 additions and 352 deletions
|
@ -83,7 +83,8 @@
|
|||
"**/typescript": "3.7.2",
|
||||
"**/graphql-toolkit/lodash": "^4.17.13",
|
||||
"**/isomorphic-git/**/base64-js": "^1.2.1",
|
||||
"**/image-diff/gm/debug": "^2.6.9"
|
||||
"**/image-diff/gm/debug": "^2.6.9",
|
||||
"**/deepmerge": "^4.2.2"
|
||||
},
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
@ -153,6 +154,7 @@
|
|||
"custom-event-polyfill": "^0.3.0",
|
||||
"d3": "3.5.17",
|
||||
"d3-cloud": "1.2.5",
|
||||
"deepmerge": "^4.2.2",
|
||||
"del": "^5.1.0",
|
||||
"elasticsearch": "^16.5.0",
|
||||
"elasticsearch-browser": "^16.5.0",
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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}}`,
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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);
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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;
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 { EuiSpacer } from '@elastic/eui';
|
||||
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 { useKibanaUiSetting } from '../../../lib/settings/use_kibana_ui_setting';
|
||||
import { DEFAULT_ANOMALY_SCORE } from '../../../../common/constants';
|
||||
|
||||
const AnomaliesOverTimeManage = manageQuery(AnomaliesOverTimeHistogram);
|
||||
|
||||
export const AnomaliesQueryTabBody = ({
|
||||
endDate,
|
||||
skip,
|
||||
startDate,
|
||||
type,
|
||||
narrowDateRange,
|
||||
filterQuery,
|
||||
anomaliesFilterQuery,
|
||||
setQuery,
|
||||
hideHistogramIfEmpty,
|
||||
updateDateRange = () => {},
|
||||
AnomaliesTableComponent,
|
||||
flowTarget,
|
||||
ip,
|
||||
}: AnomaliesQueryTabBodyProps) => {
|
||||
const [siemJobsLoading, siemJobs] = useSiemJobs(true);
|
||||
const [anomalyScore] = useKibanaUiSetting(DEFAULT_ANOMALY_SCORE);
|
||||
|
||||
const mergedFilterQuery = getAnomaliesFilterQuery(
|
||||
filterQuery,
|
||||
anomaliesFilterQuery,
|
||||
siemJobs,
|
||||
anomalyScore,
|
||||
flowTarget,
|
||||
ip
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AnomaliesOverTimeQuery
|
||||
endDate={endDate}
|
||||
filterQuery={mergedFilterQuery}
|
||||
sourceId="default"
|
||||
startDate={startDate}
|
||||
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>
|
||||
<AnomaliesTableComponent
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
skip={skip}
|
||||
type={type as never}
|
||||
narrowDateRange={narrowDateRange}
|
||||
flowTarget={flowTarget}
|
||||
ip={ip}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
AnomaliesQueryTabBody.displayName = 'AnomaliesQueryTabBody';
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 { ESTermQuery } from '../../../../common/typed_json';
|
||||
import { NarrowDateRange } from '../../../components/ml/types';
|
||||
import { UpdateDateRange } from '../../../components/charts/common';
|
||||
import { SetQuery } from '../../../pages/hosts/navigation/types';
|
||||
import { FlowTarget } from '../../../graphql/types';
|
||||
import { HostsType } from '../../../store/hosts/model';
|
||||
import { NetworkType } from '../../../store/network/model';
|
||||
import { AnomaliesHostTable } from '../../../components/ml/tables/anomalies_host_table';
|
||||
import { AnomaliesNetworkTable } from '../../../components/ml/tables/anomalies_network_table';
|
||||
|
||||
interface QueryTabBodyProps {
|
||||
type: HostsType | NetworkType;
|
||||
filterQuery?: string | ESTermQuery;
|
||||
}
|
||||
|
||||
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & {
|
||||
startDate: number;
|
||||
endDate: number;
|
||||
skip: boolean;
|
||||
setQuery: SetQuery;
|
||||
narrowDateRange: NarrowDateRange;
|
||||
updateDateRange?: UpdateDateRange;
|
||||
anomaliesFilterQuery?: object;
|
||||
hideHistogramIfEmpty?: boolean;
|
||||
ip?: string;
|
||||
flowTarget?: FlowTarget;
|
||||
AnomaliesTableComponent: typeof AnomaliesHostTable | typeof AnomaliesNetworkTable;
|
||||
};
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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 deepmerge from 'deepmerge';
|
||||
import { createFilter } from '../../helpers';
|
||||
import { ESTermQuery } from '../../../../common/typed_json';
|
||||
import { SiemJob } from '../../../components/ml_popover/types';
|
||||
import { FlowTarget } from '../../../graphql/types';
|
||||
|
||||
export const getAnomaliesFilterQuery = (
|
||||
filterQuery: string | ESTermQuery | undefined,
|
||||
anomaliesFilterQuery: object = {},
|
||||
siemJobs: SiemJob[] = [],
|
||||
anomalyScore: number,
|
||||
flowTarget?: FlowTarget,
|
||||
ip?: string
|
||||
): string => {
|
||||
const siemJobIds = siemJobs
|
||||
.filter(job => job.isInstalled)
|
||||
.map(job => job.id)
|
||||
.map(jobId => ({
|
||||
match_phrase: {
|
||||
job_id: jobId,
|
||||
},
|
||||
}));
|
||||
|
||||
const filterQueryString = createFilter(filterQuery);
|
||||
const filterQueryObject = filterQueryString ? JSON.parse(filterQueryString) : {};
|
||||
const mergedFilterQuery = deepmerge.all([
|
||||
filterQueryObject,
|
||||
anomaliesFilterQuery,
|
||||
{
|
||||
bool: {
|
||||
filter: [
|
||||
{
|
||||
bool: {
|
||||
should: siemJobIds,
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
match_phrase: {
|
||||
result_type: 'record',
|
||||
},
|
||||
},
|
||||
flowTarget &&
|
||||
ip && {
|
||||
match_phrase: {
|
||||
[`${flowTarget}.ip`]: ip,
|
||||
},
|
||||
},
|
||||
{
|
||||
range: {
|
||||
record_score: {
|
||||
gte: anomalyScore,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
return JSON.stringify(mergedFilterQuery);
|
||||
};
|
|
@ -666,6 +666,53 @@
|
|||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "AnomaliesOverTime",
|
||||
"description": "",
|
||||
"args": [
|
||||
{
|
||||
"name": "timerange",
|
||||
"description": "",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "ofType": null }
|
||||
},
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "filterQuery",
|
||||
"description": "",
|
||||
"type": { "kind": "SCALAR", "name": "String", "ofType": null },
|
||||
"defaultValue": null
|
||||
},
|
||||
{
|
||||
"name": "defaultIndex",
|
||||
"description": "",
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultValue": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "OBJECT", "name": "AnomaliesOverTimeData", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "Authentications",
|
||||
"description": "Gets Authentication success and failures based on a timerange",
|
||||
|
@ -2491,6 +2538,159 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AnomaliesOverTimeData",
|
||||
"description": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "inspect",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": { "kind": "OBJECT", "name": "Inspect", "ofType": null },
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "anomaliesOverTime",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "MatrixOverTimeHistogramData",
|
||||
"ofType": null
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "totalCount",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Inspect",
|
||||
"description": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "dsl",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "response",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "MatrixOverTimeHistogramData",
|
||||
"description": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "x",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "y",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "g",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "PaginationInputPaginated",
|
||||
|
@ -3200,57 +3400,6 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "Inspect",
|
||||
"description": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "dsl",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "response",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "LIST",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
}
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "AuthenticationsOverTimeData",
|
||||
|
@ -3306,53 +3455,6 @@
|
|||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "OBJECT",
|
||||
"name": "MatrixOverTimeHistogramData",
|
||||
"description": "",
|
||||
"fields": [
|
||||
{
|
||||
"name": "x",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "y",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "Float", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "g",
|
||||
"description": "",
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": { "kind": "SCALAR", "name": "String", "ofType": null }
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"inputFields": null,
|
||||
"interfaces": [],
|
||||
"enumValues": null,
|
||||
"possibleTypes": null
|
||||
},
|
||||
{
|
||||
"kind": "INPUT_OBJECT",
|
||||
"name": "PaginationInput",
|
||||
|
|
|
@ -456,6 +456,8 @@ export interface Source {
|
|||
configuration: SourceConfiguration;
|
||||
/** The status of the source */
|
||||
status: SourceStatus;
|
||||
|
||||
AnomaliesOverTime: AnomaliesOverTimeData;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications: AuthenticationsData;
|
||||
|
||||
|
@ -556,6 +558,28 @@ export interface IndexField {
|
|||
format?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface AnomaliesOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
anomaliesOverTime: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface Inspect {
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
}
|
||||
|
||||
export interface MatrixOverTimeHistogramData {
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
}
|
||||
|
||||
export interface AuthenticationsData {
|
||||
edges: AuthenticationsEdges[];
|
||||
|
||||
|
@ -690,12 +714,6 @@ export interface PageInfoPaginated {
|
|||
showMorePagesIndicator: boolean;
|
||||
}
|
||||
|
||||
export interface Inspect {
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
}
|
||||
|
||||
export interface AuthenticationsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
|
@ -704,14 +722,6 @@ export interface AuthenticationsOverTimeData {
|
|||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface MatrixOverTimeHistogramData {
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
}
|
||||
|
||||
export interface TimelineData {
|
||||
edges: TimelineEdges[];
|
||||
|
||||
|
@ -2127,6 +2137,13 @@ export interface GetAllTimelineQueryArgs {
|
|||
|
||||
onlyUserFavorite?: Maybe<boolean>;
|
||||
}
|
||||
export interface AnomaliesOverTimeSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface AuthenticationsSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
|
@ -2421,6 +2438,58 @@ export interface DeleteTimelineMutationArgs {
|
|||
// Documents
|
||||
// ====================================================
|
||||
|
||||
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;
|
||||
|
|
|
@ -10,6 +10,8 @@ import { Route, Switch } from 'react-router-dom';
|
|||
import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime';
|
||||
import { Anomaly } from '../../../components/ml/types';
|
||||
import { HostsTableType } from '../../../store/hosts/model';
|
||||
import { AnomaliesQueryTabBody } from '../../../containers/anomalies/anomalies_query_tab_body';
|
||||
import { AnomaliesHostTable } from '../../../components/ml/tables/anomalies_host_table';
|
||||
|
||||
import { HostDetailsTabsProps } from './types';
|
||||
import { type } from './utils';
|
||||
|
@ -18,7 +20,6 @@ import {
|
|||
HostsQueryTabBody,
|
||||
AuthenticationsQueryTabBody,
|
||||
UncommonProcessQueryTabBody,
|
||||
AnomaliesQueryTabBody,
|
||||
EventsQueryTabBody,
|
||||
} from '../navigation';
|
||||
|
||||
|
@ -84,7 +85,9 @@ const HostDetailsTabs = React.memo<HostDetailsTabsProps>(
|
|||
/>
|
||||
<Route
|
||||
path={`${hostDetailsPagePath}/:tabName(${HostsTableType.anomalies})`}
|
||||
render={() => <AnomaliesQueryTabBody {...tabProps} />}
|
||||
render={() => (
|
||||
<AnomaliesQueryTabBody {...tabProps} AnomaliesTableComponent={AnomaliesHostTable} />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path={`${hostDetailsPagePath}/:tabName(${HostsTableType.events})`}
|
||||
|
|
|
@ -11,12 +11,13 @@ import { HostsTabsProps } from './types';
|
|||
import { scoreIntervalToDateTime } from '../../components/ml/score/score_interval_to_datetime';
|
||||
import { Anomaly } from '../../components/ml/types';
|
||||
import { HostsTableType } from '../../store/hosts/model';
|
||||
import { AnomaliesQueryTabBody } from '../../containers/anomalies/anomalies_query_tab_body';
|
||||
import { AnomaliesHostTable } from '../../components/ml/tables/anomalies_host_table';
|
||||
|
||||
import {
|
||||
HostsQueryTabBody,
|
||||
AuthenticationsQueryTabBody,
|
||||
UncommonProcessQueryTabBody,
|
||||
AnomaliesQueryTabBody,
|
||||
EventsQueryTabBody,
|
||||
} from './navigation';
|
||||
|
||||
|
@ -71,7 +72,9 @@ const HostsTabs = memo<HostsTabsProps>(
|
|||
/>
|
||||
<Route
|
||||
path={`${hostsPagePath}/:tabName(${HostsTableType.anomalies})`}
|
||||
render={() => <AnomaliesQueryTabBody {...tabProps} />}
|
||||
render={() => (
|
||||
<AnomaliesQueryTabBody {...tabProps} AnomaliesTableComponent={AnomaliesHostTable} />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path={`${hostsPagePath}/:tabName(${HostsTableType.events})`}
|
||||
|
|
|
@ -1,29 +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 { AnomaliesQueryTabBodyProps } from './types';
|
||||
import { AnomaliesHostTable } from '../../../components/ml/tables/anomalies_host_table';
|
||||
|
||||
export const AnomaliesQueryTabBody = ({
|
||||
endDate,
|
||||
skip,
|
||||
startDate,
|
||||
type,
|
||||
narrowDateRange,
|
||||
hostName,
|
||||
}: AnomaliesQueryTabBodyProps) => (
|
||||
<AnomaliesHostTable
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
skip={skip}
|
||||
type={type}
|
||||
hostName={hostName}
|
||||
narrowDateRange={narrowDateRange}
|
||||
/>
|
||||
);
|
||||
|
||||
AnomaliesQueryTabBody.displayName = 'AnomaliesQueryTabBody';
|
|
@ -4,7 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export * from './anomalies_query_tab_body';
|
||||
export * from './authentications_query_tab_body';
|
||||
export * from './events_query_tab_body';
|
||||
export * from './hosts_query_tab_body';
|
||||
|
|
|
@ -25,6 +25,18 @@ type KeyHostsNavTab = KeyHostsNavTabWithoutMlPermission | KeyHostsNavTabWithMlPe
|
|||
|
||||
export type HostsNavTab = Record<KeyHostsNavTab, NavTab>;
|
||||
|
||||
export type SetQuery = ({
|
||||
id,
|
||||
inspect,
|
||||
loading,
|
||||
refetch,
|
||||
}: {
|
||||
id: string;
|
||||
inspect: InspectQuery | null;
|
||||
loading: boolean;
|
||||
refetch: Refetch;
|
||||
}) => void;
|
||||
|
||||
interface QueryTabBodyProps {
|
||||
type: hostsModel.HostsType;
|
||||
startDate: number;
|
||||
|
@ -32,30 +44,13 @@ interface QueryTabBodyProps {
|
|||
filterQuery?: string | ESTermQuery;
|
||||
}
|
||||
|
||||
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & {
|
||||
skip: boolean;
|
||||
narrowDateRange: NarrowDateRange;
|
||||
hostName?: string;
|
||||
};
|
||||
|
||||
export type HostsComponentsQueryProps = QueryTabBodyProps & {
|
||||
deleteQuery?: ({ id }: { id: string }) => void;
|
||||
indexPattern: StaticIndexPattern;
|
||||
skip: boolean;
|
||||
setQuery: ({
|
||||
id,
|
||||
inspect,
|
||||
loading,
|
||||
refetch,
|
||||
}: {
|
||||
id: string;
|
||||
inspect: InspectQuery | null;
|
||||
loading: boolean;
|
||||
refetch: Refetch;
|
||||
}) => void;
|
||||
setQuery: SetQuery;
|
||||
updateDateRange?: UpdateDateRange;
|
||||
narrowDateRange?: NarrowDateRange;
|
||||
};
|
||||
|
||||
export type CommonChildren = (args: HostsComponentsQueryProps) => JSX.Element;
|
||||
export type AnomaliesChildren = (args: AnomaliesQueryTabBodyProps) => JSX.Element;
|
||||
|
|
|
@ -39,6 +39,7 @@ import { NetworkTopNFlowQueryTable } from './network_top_n_flow_query_table';
|
|||
import { TlsQueryTable } from './tls_query_table';
|
||||
import { IPDetailsComponentProps } from './types';
|
||||
import { UsersQueryTable } from './users_query_table';
|
||||
import { AnomaliesQueryTabBody } from '../../../containers/anomalies/anomalies_query_tab_body';
|
||||
import { esQuery } from '../../../../../../../../src/plugins/data/public';
|
||||
|
||||
export { getBreadcrumbs } from './utils';
|
||||
|
@ -58,6 +59,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
setQuery,
|
||||
to,
|
||||
}) => {
|
||||
const type = networkModel.NetworkType.details;
|
||||
const narrowDateRange = useCallback(
|
||||
(score, interval) => {
|
||||
const fromTo = scoreIntervalToDateTime(score, interval);
|
||||
|
@ -108,7 +110,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
skip={isInitializing}
|
||||
sourceId="default"
|
||||
filterQuery={filterQuery}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
ip={ip}
|
||||
>
|
||||
{({ id, inspect, ipOverviewData, loading, refetch }) => (
|
||||
|
@ -127,7 +129,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
anomaliesData={anomaliesData}
|
||||
loading={loading}
|
||||
isLoadingAnomaliesData={isLoadingAnomaliesData}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
flowTarget={flowTarget}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
|
@ -158,7 +160,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
indexPattern={indexPattern}
|
||||
/>
|
||||
|
@ -172,7 +174,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
indexPattern={indexPattern}
|
||||
/>
|
||||
|
@ -190,7 +192,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
indexPattern={indexPattern}
|
||||
/>
|
||||
|
@ -204,7 +206,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
indexPattern={indexPattern}
|
||||
/>
|
||||
|
@ -220,7 +222,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
/>
|
||||
|
||||
|
@ -232,7 +234,7 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
ip={ip}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
setQuery={setQuery}
|
||||
/>
|
||||
|
||||
|
@ -246,19 +248,23 @@ export const IPDetailsComponent = React.memo<IPDetailsComponentProps>(
|
|||
setQuery={setQuery}
|
||||
skip={isInitializing}
|
||||
startDate={from}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
/>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<AnomaliesNetworkTable
|
||||
<AnomaliesQueryTabBody
|
||||
filterQuery={filterQuery}
|
||||
setQuery={setQuery}
|
||||
startDate={from}
|
||||
endDate={to}
|
||||
skip={isInitializing}
|
||||
ip={ip}
|
||||
type={networkModel.NetworkType.details}
|
||||
type={type}
|
||||
flowTarget={flowTarget}
|
||||
narrowDateRange={narrowDateRange}
|
||||
hideHistogramIfEmpty={true}
|
||||
AnomaliesTableComponent={AnomaliesNetworkTable}
|
||||
/>
|
||||
</WrapperPage>
|
||||
</StickyContainer>
|
||||
|
|
|
@ -1,27 +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 { AnomaliesQueryTabBodyProps } from './types';
|
||||
import { AnomaliesNetworkTable } from '../../../components/ml/tables/anomalies_network_table';
|
||||
|
||||
export const AnomaliesQueryTabBody = ({
|
||||
to,
|
||||
isInitializing,
|
||||
from,
|
||||
type,
|
||||
narrowDateRange,
|
||||
}: AnomaliesQueryTabBodyProps) => (
|
||||
<AnomaliesNetworkTable
|
||||
startDate={from}
|
||||
endDate={to}
|
||||
skip={isInitializing}
|
||||
type={type}
|
||||
narrowDateRange={narrowDateRange}
|
||||
/>
|
||||
);
|
||||
|
||||
AnomaliesQueryTabBody.displayName = 'AnomaliesQueryTabBody';
|
|
@ -17,21 +17,21 @@ import { IPsQueryTabBodyProps as CountriesQueryTabBodyProps } from './types';
|
|||
const NetworkTopCountriesTableManage = manageQuery(NetworkTopCountriesTable);
|
||||
|
||||
export const CountriesQueryTabBody = ({
|
||||
to,
|
||||
endDate,
|
||||
filterQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
skip,
|
||||
startDate,
|
||||
setQuery,
|
||||
indexPattern,
|
||||
flowTarget,
|
||||
}: CountriesQueryTabBodyProps) => (
|
||||
<NetworkTopCountriesQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
flowTarget={flowTarget}
|
||||
filterQuery={filterQuery}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={networkModel.NetworkType.page}
|
||||
>
|
||||
{({
|
||||
|
|
|
@ -12,28 +12,28 @@ import { NetworkDnsTable } from '../../../components/page/network/network_dns_ta
|
|||
import { NetworkDnsQuery, NetworkDnsHistogramQuery } from '../../../containers/network_dns';
|
||||
import { manageQuery } from '../../../components/page/manage_query';
|
||||
|
||||
import { DnsQueryTabBodyProps } from './types';
|
||||
import { NetworkComponentQueryProps } from './types';
|
||||
import { NetworkDnsHistogram } from '../../../components/page/network/dns_histogram';
|
||||
|
||||
const NetworkDnsTableManage = manageQuery(NetworkDnsTable);
|
||||
const NetworkDnsHistogramManage = manageQuery(NetworkDnsHistogram);
|
||||
|
||||
export const DnsQueryTabBody = ({
|
||||
to,
|
||||
endDate,
|
||||
filterQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
skip,
|
||||
startDate,
|
||||
setQuery,
|
||||
type,
|
||||
updateDateRange = () => {},
|
||||
}: DnsQueryTabBodyProps) => (
|
||||
}: NetworkComponentQueryProps) => (
|
||||
<>
|
||||
<NetworkDnsHistogramQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({ totalCount, loading, id, inspect, refetch, histogram }) => (
|
||||
|
@ -41,8 +41,8 @@ export const DnsQueryTabBody = ({
|
|||
id={id}
|
||||
loading={loading}
|
||||
data={histogram}
|
||||
endDate={to}
|
||||
startDate={from}
|
||||
endDate={endDate}
|
||||
startDate={startDate}
|
||||
inspect={inspect}
|
||||
refetch={refetch}
|
||||
setQuery={setQuery}
|
||||
|
@ -53,11 +53,11 @@ export const DnsQueryTabBody = ({
|
|||
</NetworkDnsHistogramQuery>
|
||||
<EuiSpacer />
|
||||
<NetworkDnsQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({
|
||||
|
|
|
@ -17,18 +17,18 @@ import { HttpQueryTabBodyProps } from './types';
|
|||
const NetworkHttpTableManage = manageQuery(NetworkHttpTable);
|
||||
|
||||
export const HttpQueryTabBody = ({
|
||||
to,
|
||||
endDate,
|
||||
filterQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
skip,
|
||||
startDate,
|
||||
setQuery,
|
||||
}: HttpQueryTabBodyProps) => (
|
||||
<NetworkHttpQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={networkModel.NetworkType.page}
|
||||
>
|
||||
{({
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export * from './anomalies_query_tab_body';
|
||||
export * from './network_routes';
|
||||
export * from './network_routes_loading';
|
||||
export * from './nav_tabs';
|
||||
|
|
|
@ -17,21 +17,21 @@ import { IPsQueryTabBodyProps } from './types';
|
|||
const NetworkTopNFlowTableManage = manageQuery(NetworkTopNFlowTable);
|
||||
|
||||
export const IPsQueryTabBody = ({
|
||||
to,
|
||||
endDate,
|
||||
filterQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
skip,
|
||||
startDate,
|
||||
setQuery,
|
||||
indexPattern,
|
||||
flowTarget,
|
||||
}: IPsQueryTabBodyProps) => (
|
||||
<NetworkTopNFlowQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
flowTarget={flowTarget}
|
||||
filterQuery={filterQuery}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={networkModel.NetworkType.page}
|
||||
>
|
||||
{({
|
||||
|
|
|
@ -14,7 +14,8 @@ import { scoreIntervalToDateTime } from '../../../components/ml/score/score_inte
|
|||
import { IPsQueryTabBody } from './ips_query_tab_body';
|
||||
import { CountriesQueryTabBody } from './countries_query_tab_body';
|
||||
import { HttpQueryTabBody } from './http_query_tab_body';
|
||||
import { AnomaliesQueryTabBody } from './anomalies_query_tab_body';
|
||||
import { AnomaliesQueryTabBody } from '../../../containers/anomalies/anomalies_query_tab_body';
|
||||
import { AnomaliesNetworkTable } from '../../../components/ml/tables/anomalies_network_table';
|
||||
import { DnsQueryTabBody } from './dns_query_tab_body';
|
||||
import { ConditionalFlexGroup } from './conditional_flex_group';
|
||||
import { NetworkRoutesProps, NetworkRouteType } from './types';
|
||||
|
@ -50,24 +51,44 @@ export const NetworkRoutes = ({
|
|||
[from, to]
|
||||
);
|
||||
|
||||
const tabProps = {
|
||||
networkPagePath,
|
||||
const networkAnomaliesFilterQuery = {
|
||||
bool: {
|
||||
should: [
|
||||
{
|
||||
exists: {
|
||||
field: 'source.ip',
|
||||
},
|
||||
},
|
||||
{
|
||||
exists: {
|
||||
field: 'destination.ip',
|
||||
},
|
||||
},
|
||||
],
|
||||
minimum_should_match: 1,
|
||||
},
|
||||
};
|
||||
|
||||
const commonProps = {
|
||||
startDate: from,
|
||||
endDate: to,
|
||||
skip: isInitializing,
|
||||
type,
|
||||
to,
|
||||
filterQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
indexPattern,
|
||||
narrowDateRange,
|
||||
setQuery,
|
||||
filterQuery,
|
||||
};
|
||||
|
||||
const tabProps = {
|
||||
...commonProps,
|
||||
indexPattern,
|
||||
updateDateRange,
|
||||
};
|
||||
|
||||
const anomaliesProps = {
|
||||
from,
|
||||
to,
|
||||
isInitializing,
|
||||
type,
|
||||
narrowDateRange,
|
||||
...commonProps,
|
||||
anomaliesFilterQuery: networkAnomaliesFilterQuery,
|
||||
AnomaliesTableComponent: AnomaliesNetworkTable,
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -115,7 +136,12 @@ export const NetworkRoutes = ({
|
|||
/>
|
||||
<Route
|
||||
path={`${networkPagePath}/:tabName(${NetworkRouteType.anomalies})`}
|
||||
render={() => <AnomaliesQueryTabBody {...anomaliesProps} />}
|
||||
render={() => (
|
||||
<AnomaliesQueryTabBody
|
||||
{...anomaliesProps}
|
||||
AnomaliesTableComponent={AnomaliesNetworkTable}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</Switch>
|
||||
);
|
||||
|
|
|
@ -13,23 +13,23 @@ import { TlsQueryTabBodyProps } from './types';
|
|||
const TlsTableManage = manageQuery(TlsTable);
|
||||
|
||||
export const TlsQueryTabBody = ({
|
||||
to,
|
||||
endDate,
|
||||
filterQuery,
|
||||
flowTarget,
|
||||
ip = '',
|
||||
setQuery,
|
||||
isInitializing,
|
||||
from,
|
||||
skip,
|
||||
startDate,
|
||||
type,
|
||||
}: TlsQueryTabBodyProps) => (
|
||||
<TlsQuery
|
||||
endDate={to}
|
||||
endDate={endDate}
|
||||
filterQuery={filterQuery}
|
||||
flowTarget={flowTarget}
|
||||
ip={ip}
|
||||
skip={isInitializing}
|
||||
skip={skip}
|
||||
sourceId="default"
|
||||
startDate={from}
|
||||
startDate={startDate}
|
||||
type={type}
|
||||
>
|
||||
{({ id, inspect, isInspected, tls, totalCount, pageInfo, loading, loadPage, refetch }) => (
|
||||
|
|
|
@ -10,41 +10,37 @@ import { NavTab } from '../../../components/navigation/types';
|
|||
import { FlowTargetSourceDest } from '../../../graphql/types';
|
||||
import { networkModel } from '../../../store';
|
||||
import { ESTermQuery } from '../../../../common/typed_json';
|
||||
import { NarrowDateRange } from '../../../components/ml/types';
|
||||
import { GlobalTimeArgs } from '../../../containers/global_time';
|
||||
|
||||
import { SetAbsoluteRangeDatePicker } from '../types';
|
||||
import { UpdateDateRange } from '../../../components/charts/common';
|
||||
import { NarrowDateRange } from '../../../components/ml/types';
|
||||
|
||||
interface QueryTabBodyProps {
|
||||
interface QueryTabBodyProps extends Pick<GlobalTimeArgs, 'setQuery' | 'deleteQuery'> {
|
||||
skip: boolean;
|
||||
type: networkModel.NetworkType;
|
||||
startDate: number;
|
||||
endDate: number;
|
||||
filterQuery?: string | ESTermQuery;
|
||||
updateDateRange?: UpdateDateRange;
|
||||
narrowDateRange?: NarrowDateRange;
|
||||
}
|
||||
|
||||
export type DnsQueryTabBodyProps = QueryTabBodyProps & GlobalTimeArgs;
|
||||
export type NetworkComponentQueryProps = QueryTabBodyProps;
|
||||
|
||||
export type IPsQueryTabBodyProps = QueryTabBodyProps &
|
||||
GlobalTimeArgs & {
|
||||
indexPattern: StaticIndexPattern;
|
||||
flowTarget: FlowTargetSourceDest;
|
||||
};
|
||||
export type IPsQueryTabBodyProps = QueryTabBodyProps & {
|
||||
indexPattern: StaticIndexPattern;
|
||||
flowTarget: FlowTargetSourceDest;
|
||||
};
|
||||
|
||||
export type TlsQueryTabBodyProps = QueryTabBodyProps &
|
||||
GlobalTimeArgs & {
|
||||
flowTarget: FlowTargetSourceDest;
|
||||
ip?: string;
|
||||
};
|
||||
export type TlsQueryTabBodyProps = QueryTabBodyProps & {
|
||||
flowTarget: FlowTargetSourceDest;
|
||||
ip?: string;
|
||||
};
|
||||
|
||||
export type HttpQueryTabBodyProps = QueryTabBodyProps &
|
||||
GlobalTimeArgs & {
|
||||
ip?: string;
|
||||
};
|
||||
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps &
|
||||
Pick<GlobalTimeArgs, 'to' | 'from' | 'isInitializing'> & {
|
||||
narrowDateRange: NarrowDateRange;
|
||||
};
|
||||
export type HttpQueryTabBodyProps = QueryTabBodyProps & {
|
||||
ip?: string;
|
||||
};
|
||||
|
||||
export type NetworkRoutesProps = GlobalTimeArgs & {
|
||||
networkPagePath: string;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { createAnomaliesResolvers } from './resolvers';
|
||||
export { anomaliesSchema } from './schema.gql';
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 { Anomalies } from '../../lib/anomalies';
|
||||
import { AppResolverOf, ChildResolverOf } from '../../lib/framework';
|
||||
import { createOptions } from '../../utils/build_query/create_options';
|
||||
import { QuerySourceResolver } from '../sources/resolvers';
|
||||
import { SourceResolvers } from '../types';
|
||||
|
||||
export interface AnomaliesResolversDeps {
|
||||
anomalies: Anomalies;
|
||||
}
|
||||
|
||||
type QueryAnomaliesOverTimeResolver = ChildResolverOf<
|
||||
AppResolverOf<SourceResolvers.AnomaliesOverTimeResolver>,
|
||||
QuerySourceResolver
|
||||
>;
|
||||
|
||||
export const createAnomaliesResolvers = (
|
||||
libs: AnomaliesResolversDeps
|
||||
): {
|
||||
Source: {
|
||||
AnomaliesOverTime: QueryAnomaliesOverTimeResolver;
|
||||
};
|
||||
} => ({
|
||||
Source: {
|
||||
async AnomaliesOverTime(source, args, { req }, info) {
|
||||
const options = {
|
||||
...createOptions(source, args, info),
|
||||
defaultIndex: args.defaultIndex,
|
||||
};
|
||||
return libs.anomalies.getAnomaliesOverTime(req, options);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 anomaliesSchema = gql`
|
||||
type AnomaliesOverTimeData {
|
||||
inspect: Inspect
|
||||
anomaliesOverTime: [MatrixOverTimeHistogramData!]!
|
||||
totalCount: Float!
|
||||
}
|
||||
|
||||
extend type Source {
|
||||
AnomaliesOverTime(
|
||||
timerange: TimerangeInput!
|
||||
filterQuery: String
|
||||
defaultIndex: [String!]!
|
||||
): AnomaliesOverTimeData!
|
||||
}
|
||||
`;
|
|
@ -7,6 +7,7 @@
|
|||
import { rootSchema } from '../../common/graphql/root';
|
||||
import { sharedSchema } from '../../common/graphql/shared';
|
||||
|
||||
import { anomaliesSchema } from './anomalies';
|
||||
import { authenticationsSchema } from './authentications';
|
||||
import { ecsSchema } from './ecs';
|
||||
import { eventsSchema } from './events';
|
||||
|
@ -29,6 +30,7 @@ import { tlsSchema } from './tls';
|
|||
import { uncommonProcessesSchema } from './uncommon_processes';
|
||||
import { whoAmISchema } from './who_am_i';
|
||||
export const schemas = [
|
||||
anomaliesSchema,
|
||||
authenticationsSchema,
|
||||
ecsSchema,
|
||||
eventsSchema,
|
||||
|
|
|
@ -458,6 +458,8 @@ export interface Source {
|
|||
configuration: SourceConfiguration;
|
||||
/** The status of the source */
|
||||
status: SourceStatus;
|
||||
|
||||
AnomaliesOverTime: AnomaliesOverTimeData;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications: AuthenticationsData;
|
||||
|
||||
|
@ -558,6 +560,28 @@ export interface IndexField {
|
|||
format?: Maybe<string>;
|
||||
}
|
||||
|
||||
export interface AnomaliesOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
anomaliesOverTime: MatrixOverTimeHistogramData[];
|
||||
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface Inspect {
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
}
|
||||
|
||||
export interface MatrixOverTimeHistogramData {
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
}
|
||||
|
||||
export interface AuthenticationsData {
|
||||
edges: AuthenticationsEdges[];
|
||||
|
||||
|
@ -692,12 +716,6 @@ export interface PageInfoPaginated {
|
|||
showMorePagesIndicator: boolean;
|
||||
}
|
||||
|
||||
export interface Inspect {
|
||||
dsl: string[];
|
||||
|
||||
response: string[];
|
||||
}
|
||||
|
||||
export interface AuthenticationsOverTimeData {
|
||||
inspect?: Maybe<Inspect>;
|
||||
|
||||
|
@ -706,14 +724,6 @@ export interface AuthenticationsOverTimeData {
|
|||
totalCount: number;
|
||||
}
|
||||
|
||||
export interface MatrixOverTimeHistogramData {
|
||||
x: number;
|
||||
|
||||
y: number;
|
||||
|
||||
g: string;
|
||||
}
|
||||
|
||||
export interface TimelineData {
|
||||
edges: TimelineEdges[];
|
||||
|
||||
|
@ -2129,6 +2139,13 @@ export interface GetAllTimelineQueryArgs {
|
|||
|
||||
onlyUserFavorite?: Maybe<boolean>;
|
||||
}
|
||||
export interface AnomaliesOverTimeSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
export interface AuthenticationsSourceArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
|
@ -2763,6 +2780,8 @@ export namespace SourceResolvers {
|
|||
configuration?: ConfigurationResolver<SourceConfiguration, TypeParent, TContext>;
|
||||
/** The status of the source */
|
||||
status?: StatusResolver<SourceStatus, TypeParent, TContext>;
|
||||
|
||||
AnomaliesOverTime?: AnomaliesOverTimeResolver<AnomaliesOverTimeData, TypeParent, TContext>;
|
||||
/** Gets Authentication success and failures based on a timerange */
|
||||
Authentications?: AuthenticationsResolver<AuthenticationsData, TypeParent, TContext>;
|
||||
|
||||
|
@ -2834,6 +2853,19 @@ export namespace SourceResolvers {
|
|||
Parent,
|
||||
TContext
|
||||
>;
|
||||
export type AnomaliesOverTimeResolver<
|
||||
R = AnomaliesOverTimeData,
|
||||
Parent = Source,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext, AnomaliesOverTimeArgs>;
|
||||
export interface AnomaliesOverTimeArgs {
|
||||
timerange: TimerangeInput;
|
||||
|
||||
filterQuery?: Maybe<string>;
|
||||
|
||||
defaultIndex: string[];
|
||||
}
|
||||
|
||||
export type AuthenticationsResolver<
|
||||
R = AuthenticationsData,
|
||||
Parent = Source,
|
||||
|
@ -3375,6 +3407,81 @@ export namespace IndexFieldResolvers {
|
|||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace AnomaliesOverTimeDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = AnomaliesOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
||||
anomaliesOverTime?: AnomaliesOverTimeResolver<
|
||||
MatrixOverTimeHistogramData[],
|
||||
TypeParent,
|
||||
TContext
|
||||
>;
|
||||
|
||||
totalCount?: TotalCountResolver<number, TypeParent, TContext>;
|
||||
}
|
||||
|
||||
export type InspectResolver<
|
||||
R = Maybe<Inspect>,
|
||||
Parent = AnomaliesOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type AnomaliesOverTimeResolver<
|
||||
R = MatrixOverTimeHistogramData[],
|
||||
Parent = AnomaliesOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type TotalCountResolver<
|
||||
R = number,
|
||||
Parent = AnomaliesOverTimeData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace InspectResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = Inspect> {
|
||||
dsl?: DslResolver<string[], TypeParent, TContext>;
|
||||
|
||||
response?: ResponseResolver<string[], TypeParent, TContext>;
|
||||
}
|
||||
|
||||
export type DslResolver<R = string[], Parent = Inspect, TContext = SiemContext> = Resolver<
|
||||
R,
|
||||
Parent,
|
||||
TContext
|
||||
>;
|
||||
export type ResponseResolver<R = string[], Parent = Inspect, TContext = SiemContext> = Resolver<
|
||||
R,
|
||||
Parent,
|
||||
TContext
|
||||
>;
|
||||
}
|
||||
|
||||
export namespace MatrixOverTimeHistogramDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = MatrixOverTimeHistogramData> {
|
||||
x?: XResolver<number, TypeParent, TContext>;
|
||||
|
||||
y?: YResolver<number, TypeParent, TContext>;
|
||||
|
||||
g?: GResolver<string, TypeParent, TContext>;
|
||||
}
|
||||
|
||||
export type XResolver<
|
||||
R = number,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type YResolver<
|
||||
R = number,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type GResolver<
|
||||
R = string,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace AuthenticationsDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = AuthenticationsData> {
|
||||
edges?: EdgesResolver<AuthenticationsEdges[], TypeParent, TContext>;
|
||||
|
@ -3820,25 +3927,6 @@ export namespace PageInfoPaginatedResolvers {
|
|||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace InspectResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = Inspect> {
|
||||
dsl?: DslResolver<string[], TypeParent, TContext>;
|
||||
|
||||
response?: ResponseResolver<string[], TypeParent, TContext>;
|
||||
}
|
||||
|
||||
export type DslResolver<R = string[], Parent = Inspect, TContext = SiemContext> = Resolver<
|
||||
R,
|
||||
Parent,
|
||||
TContext
|
||||
>;
|
||||
export type ResponseResolver<R = string[], Parent = Inspect, TContext = SiemContext> = Resolver<
|
||||
R,
|
||||
Parent,
|
||||
TContext
|
||||
>;
|
||||
}
|
||||
|
||||
export namespace AuthenticationsOverTimeDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = AuthenticationsOverTimeData> {
|
||||
inspect?: InspectResolver<Maybe<Inspect>, TypeParent, TContext>;
|
||||
|
@ -3869,32 +3957,6 @@ export namespace AuthenticationsOverTimeDataResolvers {
|
|||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace MatrixOverTimeHistogramDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = MatrixOverTimeHistogramData> {
|
||||
x?: XResolver<number, TypeParent, TContext>;
|
||||
|
||||
y?: YResolver<number, TypeParent, TContext>;
|
||||
|
||||
g?: GResolver<string, TypeParent, TContext>;
|
||||
}
|
||||
|
||||
export type XResolver<
|
||||
R = number,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type YResolver<
|
||||
R = number,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
export type GResolver<
|
||||
R = string,
|
||||
Parent = MatrixOverTimeHistogramData,
|
||||
TContext = SiemContext
|
||||
> = Resolver<R, Parent, TContext>;
|
||||
}
|
||||
|
||||
export namespace TimelineDataResolvers {
|
||||
export interface Resolvers<TContext = SiemContext, TypeParent = TimelineData> {
|
||||
edges?: EdgesResolver<TimelineEdges[], TypeParent, TContext>;
|
||||
|
@ -8645,6 +8707,9 @@ export type IResolvers<TContext = SiemContext> = {
|
|||
SourceFields?: SourceFieldsResolvers.Resolvers<TContext>;
|
||||
SourceStatus?: SourceStatusResolvers.Resolvers<TContext>;
|
||||
IndexField?: IndexFieldResolvers.Resolvers<TContext>;
|
||||
AnomaliesOverTimeData?: AnomaliesOverTimeDataResolvers.Resolvers<TContext>;
|
||||
Inspect?: InspectResolvers.Resolvers<TContext>;
|
||||
MatrixOverTimeHistogramData?: MatrixOverTimeHistogramDataResolvers.Resolvers<TContext>;
|
||||
AuthenticationsData?: AuthenticationsDataResolvers.Resolvers<TContext>;
|
||||
AuthenticationsEdges?: AuthenticationsEdgesResolvers.Resolvers<TContext>;
|
||||
AuthenticationItem?: AuthenticationItemResolvers.Resolvers<TContext>;
|
||||
|
@ -8657,9 +8722,7 @@ export type IResolvers<TContext = SiemContext> = {
|
|||
OsEcsFields?: OsEcsFieldsResolvers.Resolvers<TContext>;
|
||||
CursorType?: CursorTypeResolvers.Resolvers<TContext>;
|
||||
PageInfoPaginated?: PageInfoPaginatedResolvers.Resolvers<TContext>;
|
||||
Inspect?: InspectResolvers.Resolvers<TContext>;
|
||||
AuthenticationsOverTimeData?: AuthenticationsOverTimeDataResolvers.Resolvers<TContext>;
|
||||
MatrixOverTimeHistogramData?: MatrixOverTimeHistogramDataResolvers.Resolvers<TContext>;
|
||||
TimelineData?: TimelineDataResolvers.Resolvers<TContext>;
|
||||
TimelineEdges?: TimelineEdgesResolvers.Resolvers<TContext>;
|
||||
TimelineItem?: TimelineItemResolvers.Resolvers<TContext>;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { IResolvers, makeExecutableSchema } from 'graphql-tools';
|
||||
|
||||
import { schemas } from './graphql';
|
||||
import { createAnomaliesResolvers } from './graphql/anomalies';
|
||||
import { createAuthenticationsResolvers } from './graphql/authentications';
|
||||
import { createScalarToStringArrayValueResolvers } from './graphql/ecs';
|
||||
import { createEsValueResolvers, createEventsResolvers } from './graphql/events';
|
||||
|
@ -32,6 +33,7 @@ import { createTlsResolvers } from './graphql/tls';
|
|||
export const initServer = (libs: AppBackendLibs) => {
|
||||
const schema = makeExecutableSchema({
|
||||
resolvers: [
|
||||
createAnomaliesResolvers(libs) as IResolvers,
|
||||
createAuthenticationsResolvers(libs) as IResolvers,
|
||||
createEsValueResolvers() as IResolvers,
|
||||
createEventsResolvers(libs) as IResolvers,
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 { AnomaliesOverTimeData } from '../../graphql/types';
|
||||
import { inspectStringifyObject } from '../../utils/build_query';
|
||||
import { FrameworkAdapter, FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { TermAggregation } from '../types';
|
||||
|
||||
import { AnomalyHit, AnomaliesAdapter, AnomaliesActionGroupData } from './types';
|
||||
import { buildAnomaliesOverTimeQuery } from './query.anomalies_over_time.dsl';
|
||||
import { MatrixOverTimeHistogramData } from '../../../public/graphql/types';
|
||||
|
||||
export class ElasticsearchAnomaliesAdapter implements AnomaliesAdapter {
|
||||
constructor(private readonly framework: FrameworkAdapter) {}
|
||||
|
||||
public async getAnomaliesOverTime(
|
||||
request: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
): Promise<AnomaliesOverTimeData> {
|
||||
const dsl = buildAnomaliesOverTimeQuery(options);
|
||||
|
||||
const response = await this.framework.callWithRequest<AnomalyHit, TermAggregation>(
|
||||
request,
|
||||
'search',
|
||||
dsl
|
||||
);
|
||||
|
||||
const totalCount = getOr(0, 'hits.total.value', response);
|
||||
const anomaliesOverTimeBucket = getOr([], 'aggregations.anomalyActionGroup.buckets', response);
|
||||
|
||||
const inspect = {
|
||||
dsl: [inspectStringifyObject(dsl)],
|
||||
response: [inspectStringifyObject(response)],
|
||||
};
|
||||
return {
|
||||
inspect,
|
||||
anomaliesOverTime: getAnomaliesOverTimeByJobId(anomaliesOverTimeBucket),
|
||||
totalCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const getAnomaliesOverTimeByJobId = (
|
||||
data: AnomaliesActionGroupData[]
|
||||
): MatrixOverTimeHistogramData[] => {
|
||||
let result: MatrixOverTimeHistogramData[] = [];
|
||||
data.forEach(({ key: group, anomalies }) => {
|
||||
const anomaliesData = getOr([], 'buckets', anomalies).map(
|
||||
({ key, doc_count }: { key: number; doc_count: number }) => ({
|
||||
x: key,
|
||||
y: doc_count,
|
||||
g: group,
|
||||
})
|
||||
);
|
||||
result = [...result, ...anomaliesData];
|
||||
});
|
||||
|
||||
return result;
|
||||
};
|
21
x-pack/legacy/plugins/siem/server/lib/anomalies/index.ts
Normal file
21
x-pack/legacy/plugins/siem/server/lib/anomalies/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
export * from './elasticsearch_adapter';
|
||||
import { AnomaliesAdapter } from './types';
|
||||
import { AnomaliesOverTimeData } from '../../../public/graphql/types';
|
||||
|
||||
export class Anomalies {
|
||||
constructor(private readonly adapter: AnomaliesAdapter) {}
|
||||
|
||||
public async getAnomaliesOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
): Promise<AnomaliesOverTimeData> {
|
||||
return this.adapter.getAnomaliesOverTime(req, options);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 { createQueryFilterClauses, calculateTimeseriesInterval } from '../../utils/build_query';
|
||||
import { RequestBasicOptions } from '../framework';
|
||||
|
||||
export const buildAnomaliesOverTimeQuery = ({
|
||||
filterQuery,
|
||||
timerange: { from, to },
|
||||
defaultIndex,
|
||||
}: RequestBasicOptions) => {
|
||||
const filter = [
|
||||
...createQueryFilterClauses(filterQuery),
|
||||
{
|
||||
range: {
|
||||
timestamp: {
|
||||
gte: from,
|
||||
lte: to,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const getHistogramAggregation = () => {
|
||||
const interval = calculateTimeseriesInterval(from, to);
|
||||
const histogramTimestampField = 'timestamp';
|
||||
const dateHistogram = {
|
||||
date_histogram: {
|
||||
field: histogramTimestampField,
|
||||
fixed_interval: `${interval}s`,
|
||||
},
|
||||
};
|
||||
const autoDateHistogram = {
|
||||
auto_date_histogram: {
|
||||
field: histogramTimestampField,
|
||||
buckets: 36,
|
||||
},
|
||||
};
|
||||
return {
|
||||
anomalyActionGroup: {
|
||||
terms: {
|
||||
field: 'job_id',
|
||||
order: {
|
||||
_count: 'desc',
|
||||
},
|
||||
size: 10,
|
||||
},
|
||||
aggs: {
|
||||
anomalies: interval ? dateHistogram : autoDateHistogram,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const dslQuery = {
|
||||
index: defaultIndex,
|
||||
allowNoIndices: true,
|
||||
ignoreUnavailable: true,
|
||||
body: {
|
||||
aggs: getHistogramAggregation(),
|
||||
query: {
|
||||
bool: {
|
||||
filter,
|
||||
},
|
||||
},
|
||||
size: 0,
|
||||
track_total_hits: true,
|
||||
},
|
||||
};
|
||||
|
||||
return dslQuery;
|
||||
};
|
42
x-pack/legacy/plugins/siem/server/lib/anomalies/types.ts
Normal file
42
x-pack/legacy/plugins/siem/server/lib/anomalies/types.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 { AnomaliesOverTimeData } from '../../graphql/types';
|
||||
import { FrameworkRequest, RequestBasicOptions } from '../framework';
|
||||
import { SearchHit } from '../types';
|
||||
|
||||
export interface AnomaliesAdapter {
|
||||
getAnomaliesOverTime(
|
||||
req: FrameworkRequest,
|
||||
options: RequestBasicOptions
|
||||
): Promise<AnomaliesOverTimeData>;
|
||||
}
|
||||
|
||||
export interface AnomalySource {
|
||||
[field: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
}
|
||||
|
||||
export interface AnomalyHit extends SearchHit {
|
||||
sort: string[];
|
||||
_source: AnomalySource;
|
||||
aggregations: {
|
||||
[agg: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
};
|
||||
}
|
||||
|
||||
interface AnomaliesOverTimeHistogramData {
|
||||
key_as_string: string;
|
||||
key: number;
|
||||
doc_count: number;
|
||||
}
|
||||
|
||||
export interface AnomaliesActionGroupData {
|
||||
key: number;
|
||||
anomalies: {
|
||||
bucket: AnomaliesOverTimeHistogramData[];
|
||||
};
|
||||
doc_count: number;
|
||||
}
|
|
@ -27,8 +27,7 @@ export const buildAuthenticationsOverTimeQuery = ({
|
|||
];
|
||||
|
||||
const getHistogramAggregation = () => {
|
||||
const minIntervalSeconds = 10;
|
||||
const interval = calculateTimeseriesInterval(from, to, minIntervalSeconds);
|
||||
const interval = calculateTimeseriesInterval(from, to);
|
||||
const histogramTimestampField = '@timestamp';
|
||||
const dateHistogram = {
|
||||
date_histogram: {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
import { EnvironmentMode } from 'src/core/server';
|
||||
import { ServerFacade } from '../../types';
|
||||
import { Anomalies } from '../anomalies';
|
||||
import { ElasticsearchAnomaliesAdapter } from '../anomalies/elasticsearch_adapter';
|
||||
import { Authentications } from '../authentications';
|
||||
import { ElasticsearchAuthenticationAdapter } from '../authentications/elasticsearch_adapter';
|
||||
import { KibanaConfigurationAdapter } from '../configuration/kibana_configuration_adapter';
|
||||
|
@ -43,6 +45,7 @@ export function compose(server: ServerFacade, mode: EnvironmentMode): AppBackend
|
|||
const pinnedEvent = new PinnedEvent({ savedObjects: framework.getSavedObjectsService() });
|
||||
|
||||
const domainLibs: AppDomainLibs = {
|
||||
anomalies: new Anomalies(new ElasticsearchAnomaliesAdapter(framework)),
|
||||
authentications: new Authentications(new ElasticsearchAuthenticationAdapter(framework)),
|
||||
events: new Events(new ElasticsearchEventsAdapter(framework)),
|
||||
fields: new IndexFields(new ElasticsearchIndexFieldAdapter(framework)),
|
||||
|
|
|
@ -27,8 +27,7 @@ export const buildEventsOverTimeQuery = ({
|
|||
];
|
||||
|
||||
const getHistogramAggregation = () => {
|
||||
const minIntervalSeconds = 10;
|
||||
const interval = calculateTimeseriesInterval(from, to, minIntervalSeconds);
|
||||
const interval = calculateTimeseriesInterval(from, to);
|
||||
const histogramTimestampField = '@timestamp';
|
||||
const dateHistogram = {
|
||||
date_histogram: {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Anomalies } from './anomalies';
|
||||
import { Authentications } from './authentications';
|
||||
import { ConfigurationAdapter } from './configuration';
|
||||
import { Events } from './events';
|
||||
|
@ -27,6 +28,7 @@ import { SignalAlertParamsRest } from './detection_engine/alerts/types';
|
|||
export * from './hosts';
|
||||
|
||||
export interface AppDomainLibs {
|
||||
anomalies: Anomalies;
|
||||
authentications: Authentications;
|
||||
events: Events;
|
||||
fields: IndexFields;
|
||||
|
|
|
@ -91,8 +91,7 @@ export const calculateAuto = {
|
|||
|
||||
export const calculateTimeseriesInterval = (
|
||||
lowerBoundInMsSinceEpoch: number,
|
||||
upperBoundInMsSinceEpoch: number,
|
||||
minIntervalSeconds: number
|
||||
upperBoundInMsSinceEpoch: number
|
||||
) => {
|
||||
const duration = moment.duration(upperBoundInMsSinceEpoch - lowerBoundInMsSinceEpoch, 'ms');
|
||||
|
||||
|
|
13
yarn.lock
13
yarn.lock
|
@ -9676,15 +9676,10 @@ deep-object-diff@^1.1.0:
|
|||
resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a"
|
||||
integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw==
|
||||
|
||||
deepmerge@3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.0.tgz#58ef463a57c08d376547f8869fdc5bcee957f44e"
|
||||
integrity sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow==
|
||||
|
||||
deepmerge@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.0.0.tgz#3e3110ca29205f120d7cb064960a39c3d2087c09"
|
||||
integrity sha512-YZ1rOP5+kHor4hMAH+HRQnBQHg+wvS1un1hAOuIcxcBy0hzcUf6Jg2a1w65kpoOUnurOfZbERwjI1TfZxNjcww==
|
||||
deepmerge@3.2.0, deepmerge@^4.0.0, deepmerge@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
|
||||
|
||||
default-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue