Skip to content

Commit ac6628d

Browse files
Merge branch 'master' into dev/typscriptify-expression-service-functional-tests
2 parents a50f285 + 59affba commit ac6628d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1235
-352
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@
8585
"**/typescript": "3.7.2",
8686
"**/graphql-toolkit/lodash": "^4.17.13",
8787
"**/isomorphic-git/**/base64-js": "^1.2.1",
88-
"**/image-diff/gm/debug": "^2.6.9"
88+
"**/image-diff/gm/debug": "^2.6.9",
89+
"**/deepmerge": "^4.2.2"
8990
},
9091
"workspaces": {
9192
"packages": [
@@ -155,6 +156,7 @@
155156
"custom-event-polyfill": "^0.3.0",
156157
"d3": "3.5.17",
157158
"d3-cloud": "1.2.5",
159+
"deepmerge": "^4.2.2",
158160
"del": "^5.1.0",
159161
"elasticsearch": "^16.5.0",
160162
"elasticsearch-browser": "^16.5.0",

x-pack/legacy/plugins/siem/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"scripts": {
88
"build-graphql-types": "node scripts/generate_types_from_graphql.js",
99
"cypress:open": "../../../node_modules/.bin/cypress open",
10-
"cypress:run": "../../../node_modules/.bin/cypress run --spec ./cypress/integration/**/*.spec.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./reporter_config.json; ../../../node_modules/.bin/mochawesome-merge --reportDir ../../../../target/kibana-siem/cypress/results > ../../../../target/kibana-siem/cypress/results/output.json; ../../../../node_modules/.bin/marge ../../../../target/kibana-siem/cypress/results/output.json --reportDir ../../../../target/kibana-siem/cypress/results; mkdir -p ../../../../target/junit && cp ../../../../target/kibana-siem/cypress/results/*.xml ../../../../target/junit/"
10+
"cypress:run": "../../../node_modules/.bin/cypress run --spec ./cypress/integration/**/*.spec.ts --reporter ../../../node_modules/cypress-multi-reporters --reporter-options configFile=./reporter_config.json; status=$?; ../../../node_modules/.bin/mochawesome-merge --reportDir ../../../../target/kibana-siem/cypress/results > ../../../../target/kibana-siem/cypress/results/output.json; ../../../../node_modules/.bin/marge ../../../../target/kibana-siem/cypress/results/output.json --reportDir ../../../../target/kibana-siem/cypress/results; mkdir -p ../../../../target/junit && cp ../../../../target/kibana-siem/cypress/results/*.xml ../../../../target/junit/ && exit $status;"
1111
},
1212
"devDependencies": {
1313
"@types/lodash": "^4.14.110",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React from 'react';
8+
9+
import { MatrixHistogramBasicProps } from '../matrix_histogram/types';
10+
import { MatrixOverTimeHistogramData } from '../../graphql/types';
11+
import { MatrixHistogram } from '../matrix_histogram';
12+
import * as i18n from './translation';
13+
14+
export const AnomaliesOverTimeHistogram = (
15+
props: MatrixHistogramBasicProps<MatrixOverTimeHistogramData>
16+
) => {
17+
const dataKey = 'anomaliesOverTime';
18+
const { totalCount } = props;
19+
const subtitle = `${i18n.SHOWING}: ${totalCount.toLocaleString()} ${i18n.UNIT(totalCount)}`;
20+
const { ...matrixOverTimeProps } = props;
21+
22+
return (
23+
<MatrixHistogram
24+
title={i18n.ANOMALIES_COUNT_FREQUENCY_BY_ACTION}
25+
subtitle={subtitle}
26+
dataKey={dataKey}
27+
{...matrixOverTimeProps}
28+
/>
29+
);
30+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { i18n } from '@kbn/i18n';
8+
9+
export const ANOMALIES_COUNT_FREQUENCY_BY_ACTION = i18n.translate(
10+
'xpack.siem.anomaliesOverTime.anomaliesCountFrequencyByJobTile',
11+
{
12+
defaultMessage: 'Anomalies count by job',
13+
}
14+
);
15+
16+
export const SHOWING = i18n.translate('xpack.siem.anomaliesOverTime.showing', {
17+
defaultMessage: 'Showing',
18+
});
19+
20+
export const UNIT = (totalCount: number) =>
21+
i18n.translate('xpack.siem.anomaliesOverTime.unit', {
22+
values: { totalCount },
23+
defaultMessage: `{totalCount, plural, =1 {anomaly} other {anomalies}}`,
24+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import gql from 'graphql-tag';
8+
9+
export const AnomaliesOverTimeGqlQuery = gql`
10+
query GetAnomaliesOverTimeQuery(
11+
$sourceId: ID!
12+
$timerange: TimerangeInput!
13+
$defaultIndex: [String!]!
14+
$filterQuery: String
15+
$inspect: Boolean!
16+
) {
17+
source(id: $sourceId) {
18+
id
19+
AnomaliesOverTime(
20+
timerange: $timerange
21+
filterQuery: $filterQuery
22+
defaultIndex: $defaultIndex
23+
) {
24+
anomaliesOverTime {
25+
x
26+
y
27+
g
28+
}
29+
totalCount
30+
inspect @include(if: $inspect) {
31+
dsl
32+
response
33+
}
34+
}
35+
}
36+
}
37+
`;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { getOr } from 'lodash/fp';
8+
import React from 'react';
9+
import { Query } from 'react-apollo';
10+
import { connect } from 'react-redux';
11+
12+
import { State, inputsSelectors } from '../../../store';
13+
import { getDefaultFetchPolicy } from '../../helpers';
14+
import { QueryTemplate } from '../../query_template';
15+
16+
import { AnomaliesOverTimeGqlQuery } from './anomalies_over_time.gql_query';
17+
import { GetAnomaliesOverTimeQuery } from '../../../graphql/types';
18+
import { AnomaliesOverTimeProps, OwnProps } from './types';
19+
20+
const ID = 'anomaliesOverTimeQuery';
21+
22+
class AnomaliesOverTimeComponentQuery extends QueryTemplate<
23+
AnomaliesOverTimeProps,
24+
GetAnomaliesOverTimeQuery.Query,
25+
GetAnomaliesOverTimeQuery.Variables
26+
> {
27+
public render() {
28+
const {
29+
children,
30+
endDate,
31+
filterQuery,
32+
id = ID,
33+
isInspected,
34+
sourceId,
35+
startDate,
36+
} = this.props;
37+
38+
return (
39+
<Query<GetAnomaliesOverTimeQuery.Query, GetAnomaliesOverTimeQuery.Variables>
40+
query={AnomaliesOverTimeGqlQuery}
41+
fetchPolicy={getDefaultFetchPolicy()}
42+
notifyOnNetworkStatusChange
43+
variables={{
44+
filterQuery,
45+
sourceId,
46+
timerange: {
47+
interval: 'day',
48+
from: startDate!,
49+
to: endDate!,
50+
},
51+
defaultIndex: ['.ml-anomalies-*'],
52+
inspect: isInspected,
53+
}}
54+
>
55+
{({ data, loading, refetch }) => {
56+
const source = getOr({}, `source.AnomaliesOverTime`, data);
57+
const anomaliesOverTime = getOr([], `anomaliesOverTime`, source);
58+
const totalCount = getOr(-1, 'totalCount', source);
59+
return children!({
60+
endDate: endDate!,
61+
anomaliesOverTime,
62+
id,
63+
inspect: getOr(null, 'inspect', source),
64+
loading,
65+
refetch,
66+
startDate: startDate!,
67+
totalCount,
68+
});
69+
}}
70+
</Query>
71+
);
72+
}
73+
}
74+
75+
const makeMapStateToProps = () => {
76+
const getQuery = inputsSelectors.globalQueryByIdSelector();
77+
const mapStateToProps = (state: State, { id = ID }: OwnProps) => {
78+
const { isInspected } = getQuery(state, id);
79+
return {
80+
isInspected,
81+
};
82+
};
83+
return mapStateToProps;
84+
};
85+
86+
export const AnomaliesOverTimeQuery = connect(makeMapStateToProps)(AnomaliesOverTimeComponentQuery);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { QueryTemplateProps } from '../../query_template';
8+
import { inputsModel, hostsModel, networkModel } from '../../../store';
9+
import { MatrixOverTimeHistogramData } from '../../../graphql/types';
10+
11+
export interface AnomaliesArgs {
12+
endDate: number;
13+
anomaliesOverTime: MatrixOverTimeHistogramData[];
14+
id: string;
15+
inspect: inputsModel.InspectQuery;
16+
loading: boolean;
17+
refetch: inputsModel.Refetch;
18+
startDate: number;
19+
totalCount: number;
20+
}
21+
22+
export interface OwnProps extends Omit<QueryTemplateProps, 'filterQuery'> {
23+
filterQuery?: string;
24+
children?: (args: AnomaliesArgs) => React.ReactNode;
25+
type: hostsModel.HostsType | networkModel.NetworkType;
26+
}
27+
28+
export interface AnomaliesOverTimeComponentReduxProps {
29+
isInspected: boolean;
30+
}
31+
32+
export type AnomaliesOverTimeProps = OwnProps & AnomaliesOverTimeComponentReduxProps;
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React from 'react';
8+
import { EuiSpacer } from '@elastic/eui';
9+
import { AnomaliesQueryTabBodyProps } from './types';
10+
import { manageQuery } from '../../../components/page/manage_query';
11+
import { AnomaliesOverTimeHistogram } from '../../../components/anomalies_over_time';
12+
import { AnomaliesOverTimeQuery } from '../anomalies_over_time';
13+
import { getAnomaliesFilterQuery } from './utils';
14+
import { useSiemJobs } from '../../../components/ml_popover/hooks/use_siem_jobs';
15+
import { useKibanaUiSetting } from '../../../lib/settings/use_kibana_ui_setting';
16+
import { DEFAULT_ANOMALY_SCORE } from '../../../../common/constants';
17+
18+
const AnomaliesOverTimeManage = manageQuery(AnomaliesOverTimeHistogram);
19+
20+
export const AnomaliesQueryTabBody = ({
21+
endDate,
22+
skip,
23+
startDate,
24+
type,
25+
narrowDateRange,
26+
filterQuery,
27+
anomaliesFilterQuery,
28+
setQuery,
29+
hideHistogramIfEmpty,
30+
updateDateRange = () => {},
31+
AnomaliesTableComponent,
32+
flowTarget,
33+
ip,
34+
}: AnomaliesQueryTabBodyProps) => {
35+
const [siemJobsLoading, siemJobs] = useSiemJobs(true);
36+
const [anomalyScore] = useKibanaUiSetting(DEFAULT_ANOMALY_SCORE);
37+
38+
const mergedFilterQuery = getAnomaliesFilterQuery(
39+
filterQuery,
40+
anomaliesFilterQuery,
41+
siemJobs,
42+
anomalyScore,
43+
flowTarget,
44+
ip
45+
);
46+
47+
return (
48+
<>
49+
<AnomaliesOverTimeQuery
50+
endDate={endDate}
51+
filterQuery={mergedFilterQuery}
52+
sourceId="default"
53+
startDate={startDate}
54+
type={type}
55+
>
56+
{({ anomaliesOverTime, loading, id, inspect, refetch, totalCount }) => {
57+
if (hideHistogramIfEmpty && !anomaliesOverTime.length) {
58+
return <div />;
59+
}
60+
61+
return (
62+
<>
63+
<AnomaliesOverTimeManage
64+
data={anomaliesOverTime!}
65+
endDate={endDate}
66+
id={id}
67+
inspect={inspect}
68+
loading={siemJobsLoading || loading}
69+
refetch={refetch}
70+
setQuery={setQuery}
71+
startDate={startDate}
72+
totalCount={totalCount}
73+
updateDateRange={updateDateRange}
74+
/>
75+
<EuiSpacer />
76+
</>
77+
);
78+
}}
79+
</AnomaliesOverTimeQuery>
80+
<AnomaliesTableComponent
81+
startDate={startDate}
82+
endDate={endDate}
83+
skip={skip}
84+
type={type as never}
85+
narrowDateRange={narrowDateRange}
86+
flowTarget={flowTarget}
87+
ip={ip}
88+
/>
89+
</>
90+
);
91+
};
92+
93+
AnomaliesQueryTabBody.displayName = 'AnomaliesQueryTabBody';
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { ESTermQuery } from '../../../../common/typed_json';
8+
import { NarrowDateRange } from '../../../components/ml/types';
9+
import { UpdateDateRange } from '../../../components/charts/common';
10+
import { SetQuery } from '../../../pages/hosts/navigation/types';
11+
import { FlowTarget } from '../../../graphql/types';
12+
import { HostsType } from '../../../store/hosts/model';
13+
import { NetworkType } from '../../../store/network/model';
14+
import { AnomaliesHostTable } from '../../../components/ml/tables/anomalies_host_table';
15+
import { AnomaliesNetworkTable } from '../../../components/ml/tables/anomalies_network_table';
16+
17+
interface QueryTabBodyProps {
18+
type: HostsType | NetworkType;
19+
filterQuery?: string | ESTermQuery;
20+
}
21+
22+
export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & {
23+
startDate: number;
24+
endDate: number;
25+
skip: boolean;
26+
setQuery: SetQuery;
27+
narrowDateRange: NarrowDateRange;
28+
updateDateRange?: UpdateDateRange;
29+
anomaliesFilterQuery?: object;
30+
hideHistogramIfEmpty?: boolean;
31+
ip?: string;
32+
flowTarget?: FlowTarget;
33+
AnomaliesTableComponent: typeof AnomaliesHostTable | typeof AnomaliesNetworkTable;
34+
};

0 commit comments

Comments
 (0)