diff --git a/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts b/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts index dc94826c637cc..d043c1587d3c3 100644 --- a/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/common/graphql/shared/schema.gql.ts @@ -53,7 +53,7 @@ export const sharedSchema = gql` source } - enum FlowTargetNew { + enum FlowTargetSourceDest { destination source } diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 7c9dfb87400a2..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,162 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Domains Table Component Rendering it renders the default Domains table 1`] = ` - -`; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/columns.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/columns.tsx deleted file mode 100644 index cf5da3fbebba6..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/columns.tsx +++ /dev/null @@ -1,200 +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 { EuiIcon, EuiToolTip } from '@elastic/eui'; -import numeral from '@elastic/numeral'; -import { getOr, isEmpty } from 'lodash/fp'; -import moment from 'moment'; -import React from 'react'; -import { StaticIndexPattern } from 'ui/index_patterns'; - -import { - DomainsEdges, - DomainsItem, - DomainsNetworkField, - FlowDirection, - FlowTarget, -} from '../../../../graphql/types'; -import { assertUnreachable } from '../../../../lib/helpers'; -import { escapeQueryValue } from '../../../../lib/keury'; -import { networkModel } from '../../../../store'; -import { DragEffects, DraggableWrapper } from '../../../drag_and_drop/draggable_wrapper'; -import { escapeDataProviderId } from '../../../drag_and_drop/helpers'; -import { defaultToEmptyTag, getEmptyTagValue } from '../../../empty_value'; -import { PreferenceFormattedDate } from '../../../formatted_date'; -import { Columns } from '../../../paginated_table'; -import { LocalizedDateTooltip } from '../../../localized_date_tooltip'; -import { IS_OPERATOR } from '../../../timeline/data_providers/data_provider'; -import { PreferenceFormattedBytes } from '../../../formatted_bytes'; -import { Provider } from '../../../timeline/data_providers/provider'; -import { AddToKql } from '../../add_to_kql'; - -import * as i18n from './translations'; - -export type DomainsColumns = [ - Columns, - Columns, - Columns, - Columns, - Columns, - Columns -]; - -export const getDomainsColumns = ( - indexPattern: StaticIndexPattern, - ip: string, - flowDirection: FlowDirection, - flowTarget: FlowTarget, - type: networkModel.NetworkType, - tableId: string -): DomainsColumns => [ - { - field: `node.${flowTarget}.domainName`, - name: i18n.DOMAIN_NAME, - truncateText: false, - hideForMobile: false, - sortable: true, - render: domainName => { - const domainNameAttr = `${flowTarget}.domain`; - if (domainName != null) { - const id = escapeDataProviderId( - `${tableId}-table-${flowTarget}-${flowDirection}-domain-${domainName}` - ); - return ( - - snapshot.isDragging ? ( - - - - ) : ( - <>{domainName} - ) - } - /> - ); - } else { - return getEmptyTagValue(); - } - }, - }, - { - field: 'node.network.direction', - name: i18n.DIRECTION, - truncateText: false, - hideForMobile: false, - render: directions => - isEmpty(directions) - ? getEmptyTagValue() - : directions && - directions.map((direction, index) => ( - - <> - {defaultToEmptyTag(direction)} - {index < directions.length - 1 ? '\u00A0' : null} - - - )), - }, - { - field: 'node.network.bytes', - name: i18n.BYTES, - truncateText: false, - hideForMobile: false, - sortable: true, - render: bytes => { - if (bytes != null) { - return ; - } else { - return getEmptyTagValue(); - } - }, - }, - { - field: 'node.network.packets', - name: i18n.PACKETS, - truncateText: false, - hideForMobile: false, - sortable: true, - render: packets => { - if (packets != null) { - return numeral(packets).format('0,000'); - } else { - return getEmptyTagValue(); - } - }, - }, - { - field: `node.${flowTarget}.uniqueIpCount`, - name: getFlowTargetTitle(flowTarget), - truncateText: false, - hideForMobile: false, - sortable: true, - render: uniqueIpCount => { - if (uniqueIpCount != null) { - return numeral(uniqueIpCount).format('0,000'); - } else { - return getEmptyTagValue(); - } - }, - }, - { - name: ( - - <> - {i18n.LAST_SEEN}{' '} - - - - ), - truncateText: false, - hideForMobile: false, - render: ({ node }) => { - const lastSeenAttr = `${flowTarget}.lastSeen`; - const lastSeen = getOr(null, lastSeenAttr, node); - if (lastSeen != null) { - return ( - - - - ); - } - return getEmptyTagValue(); - }, - }, -]; - -const getFlowTargetTitle = (flowTarget: FlowTarget): string => { - switch (flowTarget) { - case FlowTarget.client: - return i18n.UNIQUE_CLIENTS; - case FlowTarget.server: - return i18n.UNIQUE_SERVERS; - case FlowTarget.source: - return i18n.UNIQUE_DESTINATIONS; - case FlowTarget.destination: - return i18n.UNIQUE_SOURCES; - } - assertUnreachable(flowTarget); -}; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.test.tsx deleted file mode 100644 index 45b5998f4d45c..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.test.tsx +++ /dev/null @@ -1,130 +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 { mount, shallow } from 'enzyme'; -import toJson from 'enzyme-to-json'; -import { getOr } from 'lodash/fp'; -import * as React from 'react'; -import { MockedProvider } from 'react-apollo/test-utils'; -import { Provider as ReduxStoreProvider } from 'react-redux'; - -import { FlowTarget } from '../../../../graphql/types'; -import { - apolloClientObservable, - mockIndexPattern, - mockGlobalState, - TestProviders, -} from '../../../../mock'; -import { createStore, networkModel, State } from '../../../../store'; - -import { DomainsTable } from '.'; -import { mockDomainsData } from './mock'; - -jest.mock('../../../../lib/settings/use_kibana_ui_setting'); - -describe('Domains Table Component', () => { - const loadPage = jest.fn(); - const ip = '10.10.10.10'; - const state: State = mockGlobalState; - - let store = createStore(state, apolloClientObservable); - - beforeEach(() => { - store = createStore(state, apolloClientObservable); - }); - - describe('Rendering', () => { - test('it renders the default Domains table', () => { - const wrapper = shallow( - - - - ); - - expect(toJson(wrapper)).toMatchSnapshot(); - }); - }); - - describe('Sorting on Table', () => { - test('when you click on the column header, you should show the sorting icon', () => { - const wrapper = mount( - - - - - - ); - expect(store.getState().network.details.queries!.domains.domainsSortField).toEqual({ - direction: 'desc', - field: 'bytes', - }); - - wrapper - .find('.euiTable thead tr th button') - .at(1) - .simulate('click'); - - wrapper.update(); - - expect(store.getState().network.details.queries!.domains.domainsSortField).toEqual({ - direction: 'asc', - field: 'bytes', - }); - expect( - wrapper - .find('.euiTable thead tr th button') - .first() - .text() - ).toEqual('DomainClick to sort in ascending order'); - expect( - wrapper - .find('.euiTable thead tr th button') - .at(1) - .text() - ).toEqual('BytesClick to sort in descending order'); - expect( - wrapper - .find('.euiTable thead tr th button') - .at(1) - .find('svg') - ).toBeTruthy(); - }); - }); -}); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.tsx deleted file mode 100644 index 52cd8ec70f326..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/index.tsx +++ /dev/null @@ -1,235 +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 { isEqual } from 'lodash/fp'; -import React from 'react'; -import { connect } from 'react-redux'; -import { ActionCreator } from 'redux'; -import { StaticIndexPattern } from 'ui/index_patterns'; - -import { networkActions } from '../../../../store/actions'; -import { - Direction, - DomainsEdges, - DomainsFields, - DomainsSortField, - FlowDirection, - FlowTarget, -} from '../../../../graphql/types'; -import { networkModel, networkSelectors, State } from '../../../../store'; -import { FlowDirectionSelect } from '../../../flow_controls/flow_direction_select'; -import { Criteria, ItemsPerRow, PaginatedTable, SortingBasicTable } from '../../../paginated_table'; - -import { getDomainsColumns } from './columns'; -import * as i18n from './translations'; -const tableType = networkModel.IpDetailsTableType.domains; - -interface OwnProps { - data: DomainsEdges[]; - flowTarget: FlowTarget; - fakeTotalCount: number; - id: string; - isInspect: boolean; - indexPattern: StaticIndexPattern; - ip: string; - loading: boolean; - loadPage: (newActivePage: number) => void; - showMorePagesIndicator: boolean; - totalCount: number; - type: networkModel.NetworkType; -} - -interface DomainsTableReduxProps { - activePage: number; - domainsSortField: DomainsSortField; - flowDirection: FlowDirection; - limit: number; -} - -interface DomainsTableDispatchProps { - updateDomainsDirection: ActionCreator<{ - flowDirection: FlowDirection; - networkType: networkModel.NetworkType; - }>; - updateDomainsLimit: ActionCreator<{ - limit: number; - networkType: networkModel.NetworkType; - }>; - updateDomainsSort: ActionCreator<{ - domainsSort: DomainsSortField; - networkType: networkModel.NetworkType; - }>; - updateTableActivePage: ActionCreator<{ - activePage: number; - tableType: networkModel.IpDetailsTableType; - }>; -} - -type DomainsTableProps = OwnProps & DomainsTableReduxProps & DomainsTableDispatchProps; - -const rowItems: ItemsPerRow[] = [ - { - text: i18n.ROWS_5, - numberOfRow: 5, - }, - { - text: i18n.ROWS_10, - numberOfRow: 10, - }, -]; - -export const DomainsTableId = 'domains-table'; - -class DomainsTableComponent extends React.PureComponent { - public render() { - const { - activePage, - data, - domainsSortField, - fakeTotalCount, - flowDirection, - flowTarget, - id, - indexPattern, - ip, - isInspect, - limit, - loading, - loadPage, - showMorePagesIndicator, - totalCount, - type, - updateDomainsLimit, - updateTableActivePage, - } = this.props; - - return ( - - } - headerTitle={i18n.DOMAINS} - headerUnit={i18n.UNIT(totalCount)} - id={id} - isInspect={isInspect} - itemsPerRow={rowItems} - limit={limit} - loading={loading} - loadPage={newActivePage => loadPage(newActivePage)} - onChange={this.onChange} - pageOfItems={data} - sorting={getSortField(domainsSortField, flowTarget)} - totalCount={fakeTotalCount} - updateActivePage={newPage => - updateTableActivePage({ - activePage: newPage, - tableType, - }) - } - updateLimitPagination={newLimit => - updateDomainsLimit({ limit: newLimit, networkType: type }) - } - /> - ); - } - - private onChange = (criteria: Criteria) => { - if (criteria.sort != null) { - const splitField = criteria.sort.field.split('.'); - const newDomainsSort: DomainsSortField = { - field: getSortFromString(splitField[splitField.length - 1]), - direction: criteria.sort.direction, - }; - if (!isEqual(newDomainsSort, this.props.domainsSortField)) { - this.props.updateDomainsSort({ - domainsSortField: newDomainsSort, - networkType: this.props.type, - }); - } - } - }; - - private onChangeDomainsDirection = (flowDirection: FlowDirection) => - this.props.updateDomainsDirection({ flowDirection, networkType: this.props.type }); -} - -const makeMapStateToProps = () => { - const getDomainsSelector = networkSelectors.domainsSelector(); - const mapStateToProps = (state: State) => ({ - ...getDomainsSelector(state), - }); - return mapStateToProps; -}; - -export const DomainsTable = connect( - makeMapStateToProps, - { - updateDomainsLimit: networkActions.updateDomainsLimit, - updateDomainsDirection: networkActions.updateDomainsFlowDirection, - updateDomainsSort: networkActions.updateDomainsSort, - updateTableActivePage: networkActions.updateIpDetailsTableActivePage, - } -)(DomainsTableComponent); - -const getSortField = (sortField: DomainsSortField, flowTarget: FlowTarget): SortingBasicTable => { - switch (sortField.field) { - case DomainsFields.domainName: - return { - field: `node.${flowTarget}.${sortField.field}`, - direction: sortField.direction, - }; - case DomainsFields.bytes: - return { - field: `node.network.${sortField.field}`, - direction: sortField.direction, - }; - case DomainsFields.packets: - return { - field: `node.network.${sortField.field}`, - direction: sortField.direction, - }; - case DomainsFields.uniqueIpCount: - return { - field: `node.${flowTarget}.${sortField.field}`, - direction: sortField.direction, - }; - default: - return { - field: 'node.network.bytes', - direction: Direction.desc, - }; - } -}; - -const getSortFromString = (sortField: string): DomainsFields => { - switch (sortField) { - case DomainsFields.domainName.valueOf(): - return DomainsFields.domainName; - case DomainsFields.bytes.valueOf(): - return DomainsFields.bytes; - case DomainsFields.packets.valueOf(): - return DomainsFields.packets; - case DomainsFields.uniqueIpCount.valueOf(): - return DomainsFields.uniqueIpCount; - default: - return DomainsFields.bytes; - } -}; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/mock.ts b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/mock.ts deleted file mode 100644 index 624db09f03943..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/mock.ts +++ /dev/null @@ -1,75 +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 { DomainsData } from '../../../../graphql/types'; - -export const mockDomainsData: DomainsData = { - totalCount: 2, - edges: [ - { - node: { - source: null, - destination: { - uniqueIpCount: 96, - domainName: 'samsungtv-kitchen.iot.sr.local.example.com', - firstSeen: null, - lastSeen: null, - }, - network: { - bytes: 1054651765, - direction: [], - packets: 707990, - }, - }, - cursor: { - value: 'samsungtv-kitchen.iot.sr.local.example.com', - }, - }, - { - node: { - source: null, - destination: { - uniqueIpCount: 6, - domainName: '.row.exmaple.com', - firstSeen: null, - lastSeen: null, - }, - network: { - bytes: 0, - direction: [], - packets: 0, - }, - }, - cursor: { - value: 'row.exmaple.com', - }, - }, - { - node: { - source: null, - destination: { - uniqueIpCount: 1, - domainName: '10.10.10.10', - firstSeen: null, - lastSeen: null, - }, - network: { - bytes: 0, - direction: [], - packets: 0, - }, - }, - cursor: { - value: '10.10.10.10', - }, - }, - ], - pageInfo: { - activePage: 1, - fakeTotalCount: 50, - showMorePagesIndicator: true, - }, -}; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/translations.ts b/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/translations.ts deleted file mode 100644 index b702eb0578337..0000000000000 --- a/x-pack/legacy/plugins/siem/public/components/page/network/domains_table/translations.ts +++ /dev/null @@ -1,99 +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 DOMAINS = i18n.translate('xpack.siem.network.ipDetails.domainsTable.domainsTitle', { - defaultMessage: 'Domains', -}); - -export const UNIT = (totalCount: number) => - i18n.translate('xpack.siem.network.ipDetails.domainsTable.unit', { - values: { totalCount }, - defaultMessage: `{totalCount, plural, =1 {domain} other {domains}}`, - }); - -// Columns -export const DOMAIN_NAME = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.domainNameTitle', - { - defaultMessage: 'Domain', - } -); - -export const DIRECTION = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.directionTitle', - { - defaultMessage: 'Direction', - } -); - -export const BYTES = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.bytesTitle', - { - defaultMessage: 'Bytes', - } -); - -export const PACKETS = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.packetsTitle', - { - defaultMessage: 'Packets', - } -); - -export const UNIQUE_DESTINATIONS = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.uniqueDestinationsTitle', - { - defaultMessage: 'Unique destinations', - } -); - -export const UNIQUE_SOURCES = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.uniqueSourcesTitle', - { - defaultMessage: 'Unique sources', - } -); - -export const UNIQUE_CLIENTS = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.uniqueClientsTitle', - { - defaultMessage: 'Unique servers', - } -); - -export const UNIQUE_SERVERS = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.uniqueServersTitle', - { - defaultMessage: 'Unique clients', - } -); - -export const LAST_SEEN = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.lastSeenTitle', - { - defaultMessage: 'Last seen', - } -); - -export const FIRST_LAST_SEEN_TOOLTIP = i18n.translate( - 'xpack.siem.network.ipDetails.domainsTable.columns.firstLastSeenToolTip', - { - defaultMessage: 'Relative to the selected date range', - } -); - -// Row Select -export const ROWS_5 = i18n.translate('xpack.siem.network.ipDetails.domainsTable.rows', { - values: { numRows: 5 }, - defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}', -}); - -export const ROWS_10 = i18n.translate('xpack.siem.network.ipDetails.domainsTable.rows', { - values: { numRows: 10 }, - defaultMessage: '{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}', -}); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/__snapshots__/index.test.tsx.snap b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/__snapshots__/index.test.tsx.snap index bcd7e6a0461a0..498c620312a3a 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/__snapshots__/index.test.tsx.snap @@ -1,6 +1,200 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`NetworkTopNFlow Table Component rendering it renders the default NetworkTopNFlow table 1`] = ` +exports[`NetworkTopNFlow Table Component rendering it renders the default NetworkTopNFlow table on the IP Details page 1`] = ` + +`; + +exports[`NetworkTopNFlow Table Component rendering it renders the default NetworkTopNFlow table on the Network page 1`] = ` ]; +export type NetworkTopNFlowColumnsIpDetails = [ + Columns, + Columns, + Columns, + Columns, + Columns, + Columns +]; + export const getNetworkTopNFlowColumns = ( indexPattern: StaticIndexPattern, - flowTarget: FlowTargetNew, + flowTarget: FlowTargetSourceDest, type: networkModel.NetworkType, tableId: string ): NetworkTopNFlowColumns => [ @@ -211,7 +220,7 @@ export const getNetworkTopNFlowColumns = ( { align: 'right', field: `node.${flowTarget}.${getOppositeField(flowTarget)}_ips`, - name: flowTarget === FlowTargetNew.source ? i18n.DESTINATION_IPS : i18n.SOURCE_IPS, + name: flowTarget === FlowTargetSourceDest.source ? i18n.DESTINATION_IPS : i18n.SOURCE_IPS, sortable: true, render: ips => { if (ips != null) { @@ -223,5 +232,24 @@ export const getNetworkTopNFlowColumns = ( }, ]; -const getOppositeField = (flowTarget: FlowTargetNew): FlowTargetNew => - flowTarget === FlowTargetNew.source ? FlowTargetNew.destination : FlowTargetNew.source; +export const getNFlowColumnsCurated = ( + indexPattern: StaticIndexPattern, + flowTarget: FlowTargetSourceDest, + type: networkModel.NetworkType, + tableId: string +): NetworkTopNFlowColumns | NetworkTopNFlowColumnsIpDetails => { + const columns = getNetworkTopNFlowColumns(indexPattern, flowTarget, type, tableId); + + // Columns to exclude from host details pages + if (type === networkModel.NetworkType.details) { + columns.pop(); + return columns; + } + + return columns; +}; + +const getOppositeField = (flowTarget: FlowTargetSourceDest): FlowTargetSourceDest => + flowTarget === FlowTargetSourceDest.source + ? FlowTargetSourceDest.destination + : FlowTargetSourceDest.source; diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx index d1d3a6a8c462c..aad28521b1c45 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/index.test.tsx @@ -11,7 +11,7 @@ import * as React from 'react'; import { MockedProvider } from 'react-apollo/test-utils'; import { Provider as ReduxStoreProvider } from 'react-redux'; -import { FlowTargetNew } from '../../../../graphql/types'; +import { FlowTargetSourceDest } from '../../../../graphql/types'; import { apolloClientObservable, mockGlobalState, @@ -34,13 +34,13 @@ describe('NetworkTopNFlow Table Component', () => { }); describe('rendering', () => { - test('it renders the default NetworkTopNFlow table', () => { + test('it renders the default NetworkTopNFlow table on the Network page', () => { const wrapper = shallow( { expect(toJson(wrapper)).toMatchSnapshot(); }); + + test('it renders the default NetworkTopNFlow table on the IP Details page', () => { + const wrapper = shallow( + + + + ); + + expect(toJson(wrapper)).toMatchSnapshot(); + }); }); describe('Sorting on Table', () => { @@ -69,7 +95,7 @@ describe('NetworkTopNFlow Table Component', () => { void; @@ -46,7 +47,12 @@ interface NetworkTopNFlowTableReduxProps { } interface NetworkTopNFlowTableDispatchProps { - updateTableActivePage: ActionCreator<{ + setIpDetailsTablesActivePageToZero: ActionCreator; + updateIpDetailsTableActivePage: ActionCreator<{ + activePage: number; + tableType: networkModel.IpDetailsTableType; + }>; + updateNetworkPageTableActivePage: ActionCreator<{ activePage: number; tableType: networkModel.NetworkTableType; }>; @@ -87,18 +93,24 @@ const NetworkTopNFlowTableComponent = React.memo( flowTargeted, id, indexPattern, + ip, isInspect, limit, loading, loadPage, + setIpDetailsTablesActivePageToZero, showMorePagesIndicator, topNFlowSort, totalCount, type, + updateIpDetailsTableActivePage, + updateNetworkPageTableActivePage, updateTopNFlowLimit, updateTopNFlowSort, - updateTableActivePage, }) => { + useEffect(() => { + setIpDetailsTablesActivePageToZero(null); + }, [ip]); const onChange = (criteria: Criteria, tableType: networkModel.TopNTableType) => { if (criteria.sort != null) { const splitField = criteria.sort.field.split('.'); @@ -120,14 +132,23 @@ const NetworkTopNFlowTableComponent = React.memo( }; let tableType: networkModel.TopNTableType; - let headerTitle: string; - - if (flowTargeted === FlowTargetNew.source) { - headerTitle = i18n.SOURCE_IP; - tableType = networkModel.NetworkTableType.topNFlowSource; + const headerTitle: string = + flowTargeted === FlowTargetSourceDest.source ? i18n.SOURCE_IP : i18n.DESTINATION_IP; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let updateTableActivePage: any; + if (type === networkModel.NetworkType.page) { + tableType = + flowTargeted === FlowTargetSourceDest.source + ? networkModel.NetworkTableType.topNFlowSource + : networkModel.NetworkTableType.topNFlowDestination; + updateTableActivePage = updateNetworkPageTableActivePage; } else { - headerTitle = i18n.DESTINATION_IP; - tableType = networkModel.NetworkTableType.topNFlowDestination; + tableType = + flowTargeted === FlowTargetSourceDest.source + ? networkModel.IpDetailsTableType.topNFlowSource + : networkModel.IpDetailsTableType.topNFlowDestination; + updateTableActivePage = updateIpDetailsTableActivePage; } const field = @@ -139,12 +160,7 @@ const NetworkTopNFlowTableComponent = React.memo( return ( ( NetworkTopNFlowTableComponent.displayName = 'NetworkTopNFlowTableComponent'; const mapStateToProps = (state: State, ownProps: OwnProps) => - networkSelectors.topNFlowSelector(ownProps.flowTargeted); + networkSelectors.topNFlowSelector(ownProps.flowTargeted, ownProps.type); export const NetworkTopNFlowTable = connect( mapStateToProps, { + setIpDetailsTablesActivePageToZero: networkActions.setIpDetailsTablesActivePageToZero, updateTopNFlowLimit: networkActions.updateTopNFlowLimit, updateTopNFlowSort: networkActions.updateTopNFlowSort, - updateTableActivePage: networkActions.updateNetworkPageTableActivePage, + updateNetworkPageTableActivePage: networkActions.updateNetworkPageTableActivePage, + updateIpDetailsTableActivePage: networkActions.updateIpDetailsTableActivePage, } )(NetworkTopNFlowTableComponent); diff --git a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/mock.ts b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/mock.ts index 9e7cb9e8b4b6d..9ef63bf6d3167 100644 --- a/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/mock.ts +++ b/x-pack/legacy/plugins/siem/public/components/page/network/network_top_n_flow_table/mock.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { NetworkTopNFlowData, FlowTarget } from '../../../../graphql/types'; +import { NetworkTopNFlowData, FlowTargetSourceDest } from '../../../../graphql/types'; export const mockData: { NetworkTopNFlow: NetworkTopNFlowData } = { NetworkTopNFlow: { @@ -30,7 +30,7 @@ export const mockData: { NetworkTopNFlow: NetworkTopNFlowData } = { region_iso_code: ['US-CA'], region_name: ['California'], }, - flowTarget: FlowTarget.source, + flowTarget: FlowTargetSourceDest.source, }, }, destination: null, @@ -63,7 +63,7 @@ export const mockData: { NetworkTopNFlow: NetworkTopNFlowData } = { region_iso_code: ['MY-10'], region_name: ['Selangor'], }, - flowTarget: FlowTarget.source, + flowTarget: FlowTargetSourceDest.source, }, }, destination: null, diff --git a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx index 257ee03c944bf..1529648b7133e 100644 --- a/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx +++ b/x-pack/legacy/plugins/siem/public/components/paginated_table/index.tsx @@ -21,10 +21,12 @@ import styled, { css } from 'styled-components'; import { Direction } from '../../graphql/types'; import { AuthTableColumns } from '../page/hosts/authentications_table'; -import { DomainsColumns } from '../page/network/domains_table/columns'; import { HostsTableColumns } from '../page/hosts/hosts_table'; import { NetworkDnsColumns } from '../page/network/network_dns_table/columns'; -import { NetworkTopNFlowColumns } from '../page/network/network_top_n_flow_table/columns'; +import { + NetworkTopNFlowColumns, + NetworkTopNFlowColumnsIpDetails, +} from '../page/network/network_top_n_flow_table/columns'; import { TlsColumns } from '../page/network/tls_table/columns'; import { UncommonProcessTableColumns } from '../page/hosts/uncommon_process_table'; import { UsersColumns } from '../page/network/users_table/columns'; @@ -63,12 +65,11 @@ declare type HostsTableColumnsTest = [ declare type BasicTableColumns = | AuthTableColumns - | DomainsColumns - | DomainsColumns | HostsTableColumns | HostsTableColumnsTest | NetworkDnsColumns | NetworkTopNFlowColumns + | NetworkTopNFlowColumnsIpDetails | TlsColumns | UncommonProcessTableColumns | UsersColumns; diff --git a/x-pack/legacy/plugins/siem/public/containers/domains/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/domains/index.gql_query.ts deleted file mode 100644 index 8266a83bcad5e..0000000000000 --- a/x-pack/legacy/plugins/siem/public/containers/domains/index.gql_query.ts +++ /dev/null @@ -1,71 +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 domainsQuery = gql` - query GetDomainsQuery( - $sourceId: ID! - $filterQuery: String - $flowDirection: FlowDirection! - $flowTarget: FlowTarget! - $ip: String! - $pagination: PaginationInputPaginated! - $sort: DomainsSortField! - $timerange: TimerangeInput! - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - Domains( - filterQuery: $filterQuery - flowDirection: $flowDirection - flowTarget: $flowTarget - ip: $ip - pagination: $pagination - sort: $sort - timerange: $timerange - defaultIndex: $defaultIndex - ) { - totalCount - edges { - node { - source { - uniqueIpCount - domainName - firstSeen - lastSeen - } - destination { - uniqueIpCount - domainName - firstSeen - lastSeen - } - network { - bytes - direction - packets - } - } - cursor { - value - } - } - pageInfo { - activePage - fakeTotalCount - showMorePagesIndicator - } - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/legacy/plugins/siem/public/containers/domains/index.tsx b/x-pack/legacy/plugins/siem/public/containers/domains/index.tsx deleted file mode 100644 index 8aca3bc2086ac..0000000000000 --- a/x-pack/legacy/plugins/siem/public/containers/domains/index.tsx +++ /dev/null @@ -1,175 +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 chrome from 'ui/chrome'; -import { DEFAULT_INDEX_KEY } from '../../../common/constants'; -import { - DomainsEdges, - DomainsSortField, - GetDomainsQuery, - FlowDirection, - FlowTarget, - PageInfoPaginated, -} from '../../graphql/types'; -import { inputsModel, networkModel, networkSelectors, State, inputsSelectors } from '../../store'; -import { createFilter, getDefaultFetchPolicy } from '../helpers'; -import { generateTablePaginationOptions } from '../../components/paginated_table/helpers'; -import { QueryTemplatePaginated, QueryTemplatePaginatedProps } from '../query_template_paginated'; -import { domainsQuery } from './index.gql_query'; - -const ID = 'domainsQuery'; - -export interface DomainsArgs { - domains: DomainsEdges[]; - id: string; - inspect: inputsModel.InspectQuery; - isInspected: boolean; - loading: boolean; - loadPage: (newActivePage: number) => void; - pageInfo: PageInfoPaginated; - refetch: inputsModel.Refetch; - totalCount: number; -} - -export interface OwnProps extends QueryTemplatePaginatedProps { - children: (args: DomainsArgs) => React.ReactNode; - flowTarget: FlowTarget; - ip: string; - type: networkModel.NetworkType; -} - -export interface DomainsComponentReduxProps { - activePage: number; - domainsSortField: DomainsSortField; - flowDirection: FlowDirection; - isInspected: boolean; - limit: number; -} - -type DomainsProps = OwnProps & DomainsComponentReduxProps; - -class DomainsComponentQuery extends QueryTemplatePaginated< - DomainsProps, - GetDomainsQuery.Query, - GetDomainsQuery.Variables -> { - public render() { - const { - activePage, - children, - domainsSortField, - endDate, - filterQuery, - flowDirection, - flowTarget, - id = ID, - ip, - isInspected, - limit, - skip, - sourceId, - startDate, - } = this.props; - const variables: GetDomainsQuery.Variables = { - defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY), - filterQuery: createFilter(filterQuery), - flowDirection, - flowTarget, - inspect: isInspected, - ip, - pagination: generateTablePaginationOptions(activePage, limit), - sort: domainsSortField, - sourceId, - timerange: { - interval: '12h', - from: startDate!, - to: endDate!, - }, - }; - return ( - - query={domainsQuery} - fetchPolicy={getDefaultFetchPolicy()} - notifyOnNetworkStatusChange - skip={skip} - variables={{ - defaultIndex: chrome.getUiSettingsClient().get(DEFAULT_INDEX_KEY), - filterQuery: createFilter(filterQuery), - flowDirection, - flowTarget, - inspect: isInspected, - ip, - pagination: generateTablePaginationOptions(activePage, limit), - sort: domainsSortField, - sourceId, - timerange: { - interval: '12h', - from: startDate!, - to: endDate!, - }, - }} - > - {({ data, loading, fetchMore, networkStatus, refetch }) => { - const domains = getOr([], `source.Domains.edges`, data); - this.setFetchMore(fetchMore); - this.setFetchMoreOptions((newActivePage: number) => ({ - variables: { - pagination: generateTablePaginationOptions(newActivePage, limit), - }, - updateQuery: (prev, { fetchMoreResult }) => { - if (!fetchMoreResult) { - return prev; - } - return { - ...fetchMoreResult, - source: { - ...fetchMoreResult.source, - Domains: { - ...fetchMoreResult.source.Domains, - edges: [...fetchMoreResult.source.Domains.edges], - }, - }, - }; - }, - })); - const isLoading = this.isItAValidLoading(loading, variables, networkStatus); - return children({ - domains, - id, - inspect: getOr(null, 'source.Domains.inspect', data), - isInspected, - loading: isLoading, - loadPage: this.wrappedLoadMore, - pageInfo: getOr({}, 'source.Domains.pageInfo', data), - refetch: this.memoizedRefetchQuery(variables, limit, refetch), - totalCount: getOr(-1, 'source.Domains.totalCount', data), - }); - }} - - ); - } -} - -const makeMapStateToProps = () => { - const getDomainsSelector = networkSelectors.domainsSelector(); - const getQuery = inputsSelectors.globalQueryByIdSelector(); - const mapStateToProps = (state: State, { id = ID }: OwnProps) => { - const { isInspected } = getQuery(state, id); - return { - ...getDomainsSelector(state), - isInspected, - }; - }; - - return mapStateToProps; -}; - -export const DomainsQuery = connect(makeMapStateToProps)(DomainsComponentQuery); diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts index 3b15cea33ef31..81a94bc94652b 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query.ts @@ -9,10 +9,11 @@ import gql from 'graphql-tag'; export const networkTopNFlowQuery = gql` query GetNetworkTopNFlowQuery( $sourceId: ID! + $ip: String $filterQuery: String $pagination: PaginationInputPaginated! $sort: NetworkTopNFlowSortField! - $flowTarget: FlowTargetNew! + $flowTarget: FlowTargetSourceDest! $timerange: TimerangeInput! $defaultIndex: [String!]! $inspect: Boolean! @@ -22,6 +23,7 @@ export const networkTopNFlowQuery = gql` NetworkTopNFlow( filterQuery: $filterQuery flowTarget: $flowTarget + ip: $ip pagination: $pagination sort: $sort timerange: $timerange diff --git a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx index 6b7864d48ed08..eba9c5640fb58 100644 --- a/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx +++ b/x-pack/legacy/plugins/siem/public/containers/network_top_n_flow/index.tsx @@ -12,7 +12,7 @@ import { connect } from 'react-redux'; import chrome from 'ui/chrome'; import { DEFAULT_INDEX_KEY } from '../../../common/constants'; import { - FlowTargetNew, + FlowTargetSourceDest, GetNetworkTopNFlowQuery, NetworkTopNFlowEdges, NetworkTopNFlowSortField, @@ -28,6 +28,7 @@ const ID = 'networkTopNFlowQuery'; export interface NetworkTopNFlowArgs { id: string; + ip?: string; inspect: inputsModel.InspectQuery; isInspected: boolean; loading: boolean; @@ -40,7 +41,8 @@ export interface NetworkTopNFlowArgs { export interface OwnProps extends QueryTemplatePaginatedProps { children: (args: NetworkTopNFlowArgs) => React.ReactNode; - flowTarget: FlowTargetNew; + flowTarget: FlowTargetSourceDest; + ip?: string; type: networkModel.NetworkType; } @@ -66,6 +68,7 @@ class NetworkTopNFlowComponentQuery extends QueryTemplatePaginated< flowTarget, filterQuery, id = `${ID}-${flowTarget}`, + ip, isInspected, limit, skip, @@ -78,6 +81,7 @@ class NetworkTopNFlowComponentQuery extends QueryTemplatePaginated< filterQuery: createFilter(filterQuery), flowTarget, inspect: isInspected, + ip, pagination: generateTablePaginationOptions(activePage, limit), sort: topNFlowSort, sourceId, @@ -136,8 +140,11 @@ class NetworkTopNFlowComponentQuery extends QueryTemplatePaginated< } } -const mapStateToProps = (state: State, { flowTarget, id = `${ID}-${flowTarget}` }: OwnProps) => { - const getNetworkTopNFlowSelector = networkSelectors.topNFlowSelector(flowTarget); +const mapStateToProps = ( + state: State, + { flowTarget, id = `${ID}-${flowTarget}`, type }: OwnProps +) => { + const getNetworkTopNFlowSelector = networkSelectors.topNFlowSelector(flowTarget, type); const getQuery = inputsSelectors.globalQueryByIdSelector(); const { isInspected } = getQuery(state, id); return { diff --git a/x-pack/legacy/plugins/siem/public/graphql/introspection.json b/x-pack/legacy/plugins/siem/public/graphql/introspection.json index 9173bbe5295f7..b8bdf27bed7fa 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/introspection.json +++ b/x-pack/legacy/plugins/siem/public/graphql/introspection.json @@ -1193,113 +1193,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "Domains", - "description": "", - "args": [ - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "ip", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "pagination", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "sort", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "DomainsSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "flowDirection", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowDirection", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "flowTarget", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTarget", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "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": "DomainsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "Tls", "description": "", @@ -1665,13 +1558,19 @@ "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "defaultValue": null }, + { + "name": "ip", + "description": "", + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, + "defaultValue": null + }, { "name": "flowTarget", "description": "", "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "ENUM", "name": "FlowTargetNew", "ofType": null } + "ofType": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null } }, "defaultValue": null }, @@ -6384,7 +6283,7 @@ }, { "kind": "INPUT_OBJECT", - "name": "DomainsSortField", + "name": "TlsSortField", "description": "", "fields": null, "inputFields": [ @@ -6394,7 +6293,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "ENUM", "name": "DomainsFields", "ofType": null } + "ofType": { "kind": "ENUM", "name": "TlsFields", "ofType": null } }, "defaultValue": null }, @@ -6415,60 +6314,13 @@ }, { "kind": "ENUM", - "name": "DomainsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "domainName", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "direction", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "bytes", "description": "", "isDeprecated": false, "deprecationReason": null }, - { - "name": "packets", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "uniqueIpCount", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "FlowDirection", + "name": "TlsFields", "description": "", "fields": null, "inputFields": null, "interfaces": null, "enumValues": [ - { - "name": "uniDirectional", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "biDirectional", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } + { "name": "_id", "description": "", "isDeprecated": false, "deprecationReason": null } ], "possibleTypes": null }, @@ -6494,7 +6346,7 @@ }, { "kind": "OBJECT", - "name": "DomainsData", + "name": "TlsData", "description": "", "fields": [ { @@ -6510,7 +6362,7 @@ "ofType": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "DomainsEdges", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "TlsEdges", "ofType": null } } } }, @@ -6557,7 +6409,7 @@ }, { "kind": "OBJECT", - "name": "DomainsEdges", + "name": "TlsEdges", "description": "", "fields": [ { @@ -6567,7 +6419,7 @@ "type": { "kind": "NON_NULL", "name": null, - "ofType": { "kind": "OBJECT", "name": "DomainsNode", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "TlsNode", "ofType": null } }, "isDeprecated": false, "deprecationReason": null @@ -6592,7 +6444,7 @@ }, { "kind": "OBJECT", - "name": "DomainsNode", + "name": "TlsNode", "description": "", "fields": [ { @@ -6612,42 +6464,82 @@ "deprecationReason": null }, { - "name": "source", + "name": "alternativeNames", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "DomainsItem", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "destination", + "name": "notAfter", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "DomainsItem", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "client", + "name": "commonNames", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "DomainsItem", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "server", + "name": "ja3", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "DomainsItem", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null }, { - "name": "network", + "name": "issuerNames", "description": "", "args": [], - "type": { "kind": "OBJECT", "name": "DomainsNetworkField", "ofType": null }, + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + }, "isDeprecated": false, "deprecationReason": null } @@ -6658,419 +6550,23 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "DomainsItem", + "kind": "INPUT_OBJECT", + "name": "UsersSortField", "description": "", - "fields": [ - { - "name": "uniqueIpCount", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "domainName", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, + "fields": null, + "inputFields": [ { - "name": "firstSeen", + "name": "field", "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "ENUM", "name": "UsersFields", "ofType": null } + }, + "defaultValue": null }, { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "DomainsNetworkField", - "description": "", - "fields": [ - { - "name": "bytes", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "packets", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "transport", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "direction", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "NetworkDirectionEcs", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "NetworkDirectionEcs", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "inbound", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outbound", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "internal", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "external", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "incoming", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "outgoing", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "listening", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "unknown", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TlsSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "TlsFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "Direction", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "TlsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { "name": "_id", "description": "", "isDeprecated": false, "deprecationReason": null } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsData", - "description": "", - "fields": [ - { - "name": "edges", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TlsEdges", "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 - }, - { - "name": "pageInfo", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "PageInfoPaginated", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "TlsNode", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "TlsNode", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "timestamp", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "alternativeNames", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "notAfter", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "commonNames", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ja3", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "issuerNames", - "description": "", - "args": [], - "type": { - "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": "INPUT_OBJECT", - "name": "UsersSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "UsersFields", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "direction", + "name": "direction", "description": "", "type": { "kind": "NON_NULL", @@ -7690,7 +7186,7 @@ }, { "kind": "ENUM", - "name": "FlowTargetNew", + "name": "FlowTargetSourceDest", "description": "", "fields": null, "inputFields": null, @@ -8025,7 +7521,7 @@ "name": "flowTarget", "description": "", "args": [], - "type": { "kind": "ENUM", "name": "FlowTarget", "ofType": null }, + "type": { "kind": "ENUM", "name": "FlowTargetSourceDest", "ofType": null }, "isDeprecated": false, "deprecationReason": null } @@ -11283,6 +10779,83 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "ENUM", + "name": "NetworkDirectionEcs", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "inbound", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "outbound", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "internal", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "external", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "incoming", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "outgoing", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "listening", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "unknown", "description": "", "isDeprecated": false, "deprecationReason": null } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "FlowDirection", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "uniDirectional", + "description": "", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "biDirectional", + "description": "", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "FavoriteTimelineInput", diff --git a/x-pack/legacy/plugins/siem/public/graphql/types.ts b/x-pack/legacy/plugins/siem/public/graphql/types.ts index 2d82dcb7b30f3..7514259caa2a7 100644 --- a/x-pack/legacy/plugins/siem/public/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/public/graphql/types.ts @@ -67,12 +67,6 @@ export interface HostsSortField { direction: Direction; } -export interface DomainsSortField { - field: DomainsFields; - - direction: Direction; -} - export interface TlsSortField { field: TlsFields; @@ -245,17 +239,8 @@ export enum HostsFields { lastSeen = 'lastSeen', } -export enum DomainsFields { - domainName = 'domainName', - direction = 'direction', - bytes = 'bytes', - packets = 'packets', - uniqueIpCount = 'uniqueIpCount', -} - -export enum FlowDirection { - uniDirectional = 'uniDirectional', - biDirectional = 'biDirectional', +export enum TlsFields { + _id = '_id', } export enum FlowTarget { @@ -265,27 +250,12 @@ export enum FlowTarget { source = 'source', } -export enum NetworkDirectionEcs { - inbound = 'inbound', - outbound = 'outbound', - internal = 'internal', - external = 'external', - incoming = 'incoming', - outgoing = 'outgoing', - listening = 'listening', - unknown = 'unknown', -} - -export enum TlsFields { - _id = '_id', -} - export enum UsersFields { name = 'name', count = 'count', } -export enum FlowTargetNew { +export enum FlowTargetSourceDest { destination = 'destination', source = 'source', } @@ -313,6 +283,22 @@ export enum SortFieldTimeline { created = 'created', } +export enum NetworkDirectionEcs { + inbound = 'inbound', + outbound = 'outbound', + internal = 'internal', + external = 'external', + incoming = 'incoming', + outgoing = 'outgoing', + listening = 'listening', + unknown = 'unknown', +} + +export enum FlowDirection { + uniDirectional = 'uniDirectional', + biDirectional = 'biDirectional', +} + export type ToStringArray = string[]; export type Date = string; @@ -431,8 +417,6 @@ export interface Source { IpOverview?: Maybe; - Domains: DomainsData; - Tls: TlsData; Users: UsersData; @@ -1328,58 +1312,6 @@ export interface AutonomousSystemOrganization { name?: Maybe; } -export interface DomainsData { - edges: DomainsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface DomainsEdges { - node: DomainsNode; - - cursor: CursorType; -} - -export interface DomainsNode { - _id?: Maybe; - - timestamp?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - client?: Maybe; - - server?: Maybe; - - network?: Maybe; -} - -export interface DomainsItem { - uniqueIpCount?: Maybe; - - domainName?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - -export interface DomainsNetworkField { - bytes?: Maybe; - - packets?: Maybe; - - transport?: Maybe; - - direction?: Maybe; -} - export interface TlsData { edges: TlsEdges[]; @@ -1573,7 +1505,7 @@ export interface AutonomousSystemItem { export interface GeoItem { geo?: Maybe; - flowTarget?: Maybe; + flowTarget?: Maybe; } export interface TopNFlowItemDestination { @@ -2068,25 +2000,6 @@ export interface IpOverviewSourceArgs { defaultIndex: string[]; } -export interface DomainsSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: DomainsSortField; - - flowDirection: FlowDirection; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} export interface TlsSourceArgs { filterQuery?: Maybe; @@ -2153,7 +2066,9 @@ export interface NetworkTopNFlowSourceArgs { filterQuery?: Maybe; - flowTarget: FlowTargetNew; + ip?: Maybe; + + flowTarget: FlowTargetSourceDest; pagination: PaginationInputPaginated; @@ -2396,123 +2311,6 @@ export namespace GetAuthenticationsQuery { }; } -export namespace GetDomainsQuery { - export type Variables = { - sourceId: string; - filterQuery?: Maybe; - flowDirection: FlowDirection; - flowTarget: FlowTarget; - ip: string; - pagination: PaginationInputPaginated; - sort: DomainsSortField; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Domains: Domains; - }; - - export type Domains = { - __typename?: 'DomainsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'DomainsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'DomainsNode'; - - source: Maybe<_Source>; - - destination: Maybe; - - network: Maybe; - }; - - export type _Source = { - __typename?: 'DomainsItem'; - - uniqueIpCount: Maybe; - - domainName: Maybe; - - firstSeen: Maybe; - - lastSeen: Maybe; - }; - - export type Destination = { - __typename?: 'DomainsItem'; - - uniqueIpCount: Maybe; - - domainName: Maybe; - - firstSeen: Maybe; - - lastSeen: Maybe; - }; - - export type Network = { - __typename?: 'DomainsNetworkField'; - - bytes: Maybe; - - direction: Maybe; - - packets: Maybe; - }; - - export type Cursor = { - __typename?: 'CursorType'; - - value: Maybe; - }; - - export type PageInfo = { - __typename?: 'PageInfoPaginated'; - - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; -} - export namespace GetEventsOverTimeQuery { export type Variables = { sourceId: string; @@ -3276,10 +3074,11 @@ export namespace GetNetworkDnsQuery { export namespace GetNetworkTopNFlowQuery { export type Variables = { sourceId: string; + ip?: Maybe; filterQuery?: Maybe; pagination: PaginationInputPaginated; sort: NetworkTopNFlowSortField; - flowTarget: FlowTargetNew; + flowTarget: FlowTargetSourceDest; timerange: TimerangeInput; defaultIndex: string[]; inspect: boolean; @@ -3358,7 +3157,7 @@ export namespace GetNetworkTopNFlowQuery { geo: Maybe; - flowTarget: Maybe; + flowTarget: Maybe; }; export type Geo = { @@ -3406,7 +3205,7 @@ export namespace GetNetworkTopNFlowQuery { geo: Maybe<_Geo>; - flowTarget: Maybe; + flowTarget: Maybe; }; export type _Geo = { diff --git a/x-pack/legacy/plugins/siem/public/mock/global_state.ts b/x-pack/legacy/plugins/siem/public/mock/global_state.ts index 83fa30c97145f..02f098cb7b9a9 100644 --- a/x-pack/legacy/plugins/siem/public/mock/global_state.ts +++ b/x-pack/legacy/plugins/siem/public/mock/global_state.ts @@ -7,8 +7,6 @@ import { DEFAULT_TIMELINE_WIDTH } from '../components/timeline/body/helpers'; import { Direction, - DomainsFields, - FlowDirection, FlowTarget, HostsFields, NetworkDnsFields, @@ -16,7 +14,7 @@ import { TlsFields, UsersFields, } from '../graphql/types'; -import { State } from '../store'; +import { networkModel, State } from '../store'; import { defaultHeaders } from './header'; import { @@ -71,17 +69,17 @@ export const mockGlobalState: State = { network: { page: { queries: { - topNFlowSource: { + [networkModel.NetworkTableType.topNFlowSource]: { activePage: 0, limit: 10, topNFlowSort: { field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc }, }, - topNFlowDestination: { + [networkModel.NetworkTableType.topNFlowDestination]: { activePage: 0, limit: 10, topNFlowSort: { field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc }, }, - dns: { + [networkModel.NetworkTableType.dns]: { activePage: 0, limit: 10, dnsSortField: { field: NetworkDnsFields.queryCount, direction: Direction.desc }, @@ -96,18 +94,22 @@ export const mockGlobalState: State = { filterQueryDraft: null, flowTarget: FlowTarget.source, queries: { - domains: { + [networkModel.IpDetailsTableType.topNFlowSource]: { activePage: 0, limit: 10, - flowDirection: FlowDirection.uniDirectional, - domainsSortField: { field: DomainsFields.bytes, direction: Direction.desc }, + topNFlowSort: { field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc }, + }, + [networkModel.IpDetailsTableType.topNFlowDestination]: { + activePage: 0, + limit: 10, + topNFlowSort: { field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc }, }, - tls: { + [networkModel.IpDetailsTableType.tls]: { activePage: 0, limit: 10, tlsSortField: { field: TlsFields._id, direction: Direction.desc }, }, - users: { + [networkModel.IpDetailsTableType.users]: { activePage: 0, limit: 10, usersSortField: { field: UsersFields.name, direction: Direction.asc }, diff --git a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx b/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx index d815b37496bf1..80fcce20a4982 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/ip_details.tsx @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EuiHorizontalRule, EuiSpacer } from '@elastic/eui'; +import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; import { getOr } from 'lodash/fp'; import React from 'react'; import { connect } from 'react-redux'; @@ -17,23 +17,23 @@ import { HeaderPage } from '../../components/header_page'; import { LastEventTime } from '../../components/last_event_time'; import { getNetworkUrl } from '../../components/link_to/redirect_to_network'; import { manageQuery } from '../../components/page/manage_query'; -import { DomainsTable } from '../../components/page/network/domains_table'; import { FlowTargetSelectConnected } from '../../components/page/network/flow_target_select_connected'; import { IpOverview } from '../../components/page/network/ip_overview'; import { UsersTable } from '../../components/page/network/users_table'; import { TlsTable } from '../../components/page/network/tls_table'; -import { DomainsQuery } from '../../containers/domains'; import { IpOverviewQuery } from '../../containers/ip_overview'; import { indicesExistOrDataTemporarilyUnavailable, WithSource } from '../../containers/source'; import { TlsQuery } from '../../containers/tls'; import { UsersQuery } from '../../containers/users'; -import { LastEventIndexKey } from '../../graphql/types'; +import { FlowTargetSourceDest, LastEventIndexKey } from '../../graphql/types'; import { decodeIpv6 } from '../../lib/helpers'; import { networkModel, networkSelectors, State } from '../../store'; import { setAbsoluteRangeDatePicker as dispatchAbsoluteRangeDatePicker } from '../../store/inputs/actions'; import { NetworkKql } from './kql'; import { NetworkEmptyPage } from './network_empty_page'; +import { NetworkTopNFlowQuery } from '../../containers/network_top_n_flow'; +import { NetworkTopNFlowTable } from '../../components/page/network/network_top_n_flow_table'; import * as i18n from './translations'; import { IPDetailsComponentProps } from './types'; import { AnomalyTableProvider } from '../../components/ml/anomaly/anomaly_table_provider'; @@ -41,11 +41,12 @@ import { scoreIntervalToDateTime } from '../../components/ml/score/score_interva import { AnomaliesNetworkTable } from '../../components/ml/tables/anomalies_network_table'; import { networkToCriteria } from '../../components/ml/criteria/network_to_criteria'; import { SpyRoute } from '../../utils/route/spy_routes'; +import { ConditionalFlexGroup } from '../../pages/network/navigation/conditional_flex_group'; -const DomainsTableManage = manageQuery(DomainsTable); const TlsTableManage = manageQuery(TlsTable); const UsersTableManage = manageQuery(UsersTable); const IpOverviewManage = manageQuery(IpOverview); +const NetworkTopNFlowTableManage = manageQuery(NetworkTopNFlowTable); export const IPDetailsComponent = pure( ({ @@ -127,46 +128,92 @@ export const IPDetailsComponent = pure( - - {({ - id, - inspect, - isInspected, - domains, - totalCount, - pageInfo, - loading, - loadPage, - refetch, - }) => ( - + + - )} - + > + {({ + id, + inspect, + isInspected, + loading, + loadPage, + networkTopNFlow, + pageInfo, + refetch, + totalCount, + }) => ( + + )} + + + + + + {({ + id, + inspect, + isInspected, + loading, + loadPage, + networkTopNFlow, + pageInfo, + refetch, + totalCount, + }) => ( + + )} + + + diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx index 08d9252357b37..0ed652804cc8e 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/network_routes.tsx @@ -8,7 +8,7 @@ import React, { useCallback } from 'react'; import { Route, Switch } from 'react-router-dom'; import { EuiFlexItem } from '@elastic/eui'; -import { FlowTargetNew } from '../../../graphql/types'; +import { FlowTargetSourceDest } from '../../../graphql/types'; import { scoreIntervalToDateTime } from '../../../components/ml/score/score_interval_to_datetime'; import { IPsQueryTabBody } from './ips_query_tab_body'; @@ -70,11 +70,11 @@ export const NetworkRoutes = ({ render={() => ( - + - + )} diff --git a/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts b/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts index 838aaea38608f..bcdc0ef7aa790 100644 --- a/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts +++ b/x-pack/legacy/plugins/siem/public/pages/network/navigation/types.ts @@ -7,7 +7,7 @@ import { StaticIndexPattern } from 'ui/index_patterns'; import { NavTab } from '../../../components/navigation/types'; -import { FlowTargetNew } from '../../../graphql/types'; +import { FlowTargetSourceDest } from '../../../graphql/types'; import { networkModel } from '../../../store'; import { ESTermQuery } from '../../../../common/typed_json'; import { NarrowDateRange } from '../../../components/ml/types'; @@ -25,7 +25,7 @@ export type DnsQueryTabBodyProps = QueryTabBodyProps & GlobalTimeArgs; export type IPsQueryTabBodyProps = QueryTabBodyProps & GlobalTimeArgs & { indexPattern: StaticIndexPattern; - flowTarget: FlowTargetNew; + flowTarget: FlowTargetSourceDest; }; export type AnomaliesQueryTabBodyProps = QueryTabBodyProps & diff --git a/x-pack/legacy/plugins/siem/public/store/network/actions.ts b/x-pack/legacy/plugins/siem/public/store/network/actions.ts index 7408037b9f835..c2c71a4643e6a 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/actions.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/actions.ts @@ -7,8 +7,6 @@ import actionCreatorFactory from 'typescript-fsa'; import { - DomainsSortField, - FlowDirection, FlowTarget, NetworkDnsSortField, NetworkTopNFlowSortField, @@ -17,59 +15,61 @@ import { } from '../../graphql/types'; import { KueryFilterQuery, networkModel, SerializedFilterQuery } from '../model'; -import { IpDetailsTableType, NetworkTableType, NetworkType } from './model'; - const actionCreator = actionCreatorFactory('x-pack/siem/local/network'); export const updateNetworkPageTableActivePage = actionCreator<{ activePage: number; - tableType: NetworkTableType; + tableType: networkModel.NetworkTableType; }>('UPDATE_NETWORK_PAGE_TABLE_ACTIVE_PAGE'); -export const setNetworkTablesActivePageToZero = actionCreator( - 'SET_NETWORK_TABLES_ACTIVE_PAGE_TO_ZERO' -); - export const updateIpDetailsTableActivePage = actionCreator<{ activePage: number; - tableType: IpDetailsTableType; + tableType: networkModel.IpDetailsTableType; }>('UPDATE_NETWORK_DETAILS_TABLE_ACTIVE_PAGE'); +export const setIpDetailsTablesActivePageToZero = actionCreator( + 'SET_IP_DETAILS_TABLES_ACTIVE_PAGE_TO_ZERO' +); + +export const setNetworkTablesActivePageToZero = actionCreator( + 'SET_NETWORK_TABLES_ACTIVE_PAGE_TO_ZERO' +); + export const updateDnsLimit = actionCreator<{ limit: number; - networkType: NetworkType; + networkType: networkModel.NetworkType; }>('UPDATE_DNS_LIMIT'); export const updateDnsSort = actionCreator<{ dnsSortField: NetworkDnsSortField; - networkType: NetworkType; + networkType: networkModel.NetworkType; }>('UPDATE_DNS_SORT'); export const updateIsPtrIncluded = actionCreator<{ isPtrIncluded: boolean; - networkType: NetworkType; + networkType: networkModel.NetworkType; }>('UPDATE_DNS_IS_PTR_INCLUDED'); export const updateTopNFlowLimit = actionCreator<{ limit: number; - networkType: NetworkType; + networkType: networkModel.NetworkType; tableType: networkModel.TopNTableType; }>('UPDATE_TOP_N_FLOW_LIMIT'); export const updateTopNFlowSort = actionCreator<{ topNFlowSort: NetworkTopNFlowSortField; - networkType: NetworkType; - tableType: networkModel.NetworkTableType; + networkType: networkModel.NetworkType; + tableType: networkModel.TopNTableType; }>('UPDATE_TOP_N_FLOW_SORT'); export const setNetworkFilterQueryDraft = actionCreator<{ filterQueryDraft: KueryFilterQuery; - networkType: NetworkType; + networkType: networkModel.NetworkType; }>('SET_NETWORK_FILTER_QUERY_DRAFT'); export const applyNetworkFilterQuery = actionCreator<{ filterQuery: SerializedFilterQuery; - networkType: NetworkType; + networkType: networkModel.NetworkType; }>('APPLY_NETWORK_FILTER_QUERY'); // IP Details Actions @@ -77,19 +77,6 @@ export const updateIpDetailsFlowTarget = actionCreator<{ flowTarget: FlowTarget; }>('UPDATE_IP_DETAILS_TARGET'); -// Domains Table Actions -export const updateDomainsLimit = actionCreator<{ - limit: number; -}>('UPDATE_DOMAINS_LIMIT'); - -export const updateDomainsFlowDirection = actionCreator<{ - flowDirection: FlowDirection; -}>('UPDATE_DOMAINS_DIRECTION'); - -export const updateDomainsSort = actionCreator<{ - domainsSortField: DomainsSortField; -}>('UPDATE_DOMAINS_SORT'); - // TLS Table Actions export const updateTlsSort = actionCreator<{ tlsSortField: TlsSortField; diff --git a/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts b/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts index 91b918cb45436..13c98eb800916 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/helpers.test.ts @@ -8,8 +8,6 @@ import { Direction, NetworkTopNFlowFields, NetworkDnsFields, - FlowDirection, - DomainsFields, TlsFields, UsersFields, FlowTarget, @@ -52,12 +50,19 @@ export const mockNetworkState: NetworkModel = { }, details: { queries: { - [IpDetailsTableType.domains]: { - activePage: 8, - flowDirection: FlowDirection.uniDirectional, + [IpDetailsTableType.topNFlowSource]: { + activePage: 7, limit: DEFAULT_TABLE_LIMIT, - domainsSortField: { - field: DomainsFields.bytes, + topNFlowSort: { + field: NetworkTopNFlowFields.bytes_out, + direction: Direction.desc, + }, + }, + [IpDetailsTableType.topNFlowDestination]: { + activePage: 3, + limit: DEFAULT_TABLE_LIMIT, + topNFlowSort: { + field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc, }, }, @@ -88,17 +93,17 @@ describe('Network redux store', () => { describe('#setNetworkQueriesActivePageToZero', () => { test('set activePage to zero for all queries in hosts page ', () => { expect(setNetworkQueriesActivePageToZero(mockNetworkState, NetworkType.page)).toEqual({ - topNFlowSource: { + [NetworkTableType.topNFlowSource]: { activePage: 0, limit: 10, topNFlowSort: { field: 'bytes_out', direction: 'desc' }, }, - topNFlowDestination: { + [NetworkTableType.topNFlowDestination]: { activePage: 0, limit: 10, topNFlowSort: { field: 'bytes_out', direction: 'desc' }, }, - dns: { + [NetworkTableType.dns]: { activePage: 0, limit: 10, dnsSortField: { field: 'uniqueDomains', direction: 'desc' }, @@ -109,14 +114,26 @@ describe('Network redux store', () => { test('set activePage to zero for all queries in host details ', () => { expect(setNetworkQueriesActivePageToZero(mockNetworkState, NetworkType.details)).toEqual({ - domains: { + [IpDetailsTableType.topNFlowSource]: { + activePage: 0, + limit: 10, + topNFlowSort: { field: 'bytes_out', direction: 'desc' }, + }, + [IpDetailsTableType.topNFlowDestination]: { + activePage: 0, + limit: 10, + topNFlowSort: { field: 'bytes_out', direction: 'desc' }, + }, + [IpDetailsTableType.tls]: { + activePage: 0, + limit: 10, + tlsSortField: { field: '_id', direction: 'desc' }, + }, + [IpDetailsTableType.users]: { activePage: 0, - flowDirection: 'uniDirectional', limit: 10, - domainsSortField: { field: 'bytes', direction: 'desc' }, + usersSortField: { field: 'name', direction: 'asc' }, }, - tls: { activePage: 0, limit: 10, tlsSortField: { field: '_id', direction: 'desc' } }, - users: { activePage: 0, limit: 10, usersSortField: { field: 'name', direction: 'asc' } }, }); }); }); diff --git a/x-pack/legacy/plugins/siem/public/store/network/helpers.ts b/x-pack/legacy/plugins/siem/public/store/network/helpers.ts index 2d19ad4f44213..b9876457625fb 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/helpers.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/helpers.ts @@ -34,8 +34,12 @@ export const setNetworkDetailsQueriesActivePageToZero = ( state: NetworkModel ): IpOverviewQueries => ({ ...state.details.queries, - [IpDetailsTableType.domains]: { - ...state.details.queries[IpDetailsTableType.domains], + [IpDetailsTableType.topNFlowSource]: { + ...state.details.queries[IpDetailsTableType.topNFlowSource], + activePage: DEFAULT_TABLE_ACTIVE_PAGE, + }, + [IpDetailsTableType.topNFlowDestination]: { + ...state.details.queries[IpDetailsTableType.topNFlowDestination], activePage: DEFAULT_TABLE_ACTIVE_PAGE, }, [IpDetailsTableType.tls]: { diff --git a/x-pack/legacy/plugins/siem/public/store/network/model.ts b/x-pack/legacy/plugins/siem/public/store/network/model.ts index 8fefb6099da6b..541a2fe1a02e3 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/model.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/model.ts @@ -5,15 +5,13 @@ */ import { - DomainsSortField, - FlowDirection, FlowTarget, NetworkDnsSortField, NetworkTopNFlowSortField, TlsSortField, UsersSortField, } from '../../graphql/types'; -import { KueryFilterQuery, networkModel, SerializedFilterQuery } from '../model'; +import { KueryFilterQuery, SerializedFilterQuery } from '../model'; export enum NetworkType { page = 'page', @@ -27,11 +25,14 @@ export enum NetworkTableType { } export type TopNTableType = - | networkModel.NetworkTableType.topNFlowDestination - | networkModel.NetworkTableType.topNFlowSource; + | NetworkTableType.topNFlowDestination + | NetworkTableType.topNFlowSource + | IpDetailsTableType.topNFlowDestination + | IpDetailsTableType.topNFlowSource; export enum IpDetailsTableType { - domains = 'domains', + topNFlowSource = 'topNFlowSourceIp', + topNFlowDestination = 'topNFlowDestinationIp', tls = 'tls', users = 'users', } @@ -64,10 +65,6 @@ export interface NetworkPageModel { } // IP Details Models -export interface DomainsQuery extends BasicQueryPaginated { - flowDirection: FlowDirection; - domainsSortField: DomainsSortField; -} export interface TlsQuery extends BasicQueryPaginated { tlsSortField: TlsSortField; @@ -78,7 +75,8 @@ export interface UsersQuery extends BasicQueryPaginated { } export interface IpOverviewQueries { - [IpDetailsTableType.domains]: DomainsQuery; + [IpDetailsTableType.topNFlowSource]: TopNFlowQuery; + [IpDetailsTableType.topNFlowDestination]: TopNFlowQuery; [IpDetailsTableType.tls]: TlsQuery; [IpDetailsTableType.users]: UsersQuery; } diff --git a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts index 84f0772ee4ec6..df7d496714530 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/reducer.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/reducer.ts @@ -8,8 +8,6 @@ import { reducerWithInitialState } from 'typescript-fsa-reducers'; import { Direction, - DomainsFields, - FlowDirection, FlowTarget, NetworkDnsFields, NetworkTopNFlowFields, @@ -20,29 +18,27 @@ import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../constants'; import { applyNetworkFilterQuery, + setIpDetailsTablesActivePageToZero, setNetworkFilterQueryDraft, + setNetworkTablesActivePageToZero, updateDnsLimit, updateDnsSort, - updateDomainsFlowDirection, - updateDomainsLimit, - updateTlsLimit, - updateDomainsSort, updateIpDetailsFlowTarget, - updateIsPtrIncluded, updateIpDetailsTableActivePage, + updateIsPtrIncluded, updateNetworkPageTableActivePage, + updateTlsLimit, + updateTlsSort, updateTopNFlowLimit, updateTopNFlowSort, - updateTlsSort, updateUsersLimit, updateUsersSort, - setNetworkTablesActivePageToZero, } from './actions'; import { IpDetailsTableType, NetworkModel, NetworkTableType, NetworkType } from './model'; import { - setNetworkQueriesActivePageToZero, - setNetworkPageQueriesActivePageToZero, setNetworkDetailsQueriesActivePageToZero, + setNetworkPageQueriesActivePageToZero, + setNetworkQueriesActivePageToZero, } from './helpers'; export type NetworkState = NetworkModel; @@ -81,12 +77,19 @@ export const initialNetworkState: NetworkState = { }, details: { queries: { - [IpDetailsTableType.domains]: { + [IpDetailsTableType.topNFlowSource]: { activePage: DEFAULT_TABLE_ACTIVE_PAGE, - flowDirection: FlowDirection.uniDirectional, limit: DEFAULT_TABLE_LIMIT, - domainsSortField: { - field: DomainsFields.bytes, + topNFlowSort: { + field: NetworkTopNFlowFields.bytes_out, + direction: Direction.desc, + }, + }, + [IpDetailsTableType.topNFlowDestination]: { + activePage: DEFAULT_TABLE_ACTIVE_PAGE, + limit: DEFAULT_TABLE_LIMIT, + topNFlowSort: { + field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc, }, }, @@ -125,6 +128,13 @@ export const networkReducer = reducerWithInitialState(initialNetworkState) queries: setNetworkDetailsQueriesActivePageToZero(state), }, })) + .case(setIpDetailsTablesActivePageToZero, state => ({ + ...state, + details: { + ...state.details, + queries: setNetworkDetailsQueriesActivePageToZero(state), + }, + })) .case(updateIpDetailsTableActivePage, (state, { activePage, tableType }) => ({ ...state, [NetworkType.details]: { @@ -190,32 +200,84 @@ export const networkReducer = reducerWithInitialState(initialNetworkState) }, }, })) - .case(updateTopNFlowLimit, (state, { limit, networkType, tableType }) => ({ - ...state, - [networkType]: { - ...state[networkType], - queries: { - ...state[networkType].queries, - [tableType]: { - ...state[NetworkType.page].queries[tableType], - limit, + .case(updateTopNFlowLimit, (state, { limit, networkType, tableType }) => { + if ( + networkType === NetworkType.page && + (tableType === NetworkTableType.topNFlowSource || + tableType === NetworkTableType.topNFlowDestination) + ) { + return { + ...state, + [networkType]: { + ...state[networkType], + queries: { + ...state[networkType].queries, + [tableType]: { + ...state[networkType].queries[tableType], + limit, + }, + }, }, - }, - }, - })) - .case(updateTopNFlowSort, (state, { topNFlowSort, networkType, tableType }) => ({ - ...state, - [networkType]: { - ...state[networkType], - queries: { - ...state[networkType].queries, - [tableType]: { - ...state[NetworkType.page].queries[tableType], - topNFlowSort, + }; + } else if ( + tableType === IpDetailsTableType.topNFlowDestination || + tableType === IpDetailsTableType.topNFlowSource + ) { + return { + ...state, + [NetworkType.details]: { + ...state[NetworkType.details], + queries: { + ...state[NetworkType.details].queries, + [tableType]: { + ...state[NetworkType.details].queries[tableType], + limit, + }, + }, }, - }, - }, - })) + }; + } + return state; + }) + .case(updateTopNFlowSort, (state, { topNFlowSort, networkType, tableType }) => { + if ( + networkType === NetworkType.page && + (tableType === NetworkTableType.topNFlowSource || + tableType === NetworkTableType.topNFlowDestination) + ) { + return { + ...state, + [networkType]: { + ...state[networkType], + queries: { + ...state[networkType].queries, + [tableType]: { + ...state[networkType].queries[tableType], + topNFlowSort, + }, + }, + }, + }; + } else if ( + tableType === IpDetailsTableType.topNFlowDestination || + tableType === IpDetailsTableType.topNFlowSource + ) { + return { + ...state, + [NetworkType.details]: { + ...state[NetworkType.details], + queries: { + ...state[NetworkType.details].queries, + [tableType]: { + ...state[NetworkType.details].queries[tableType], + topNFlowSort, + }, + }, + }, + }; + } + return state; + }) .case(setNetworkFilterQueryDraft, (state, { filterQueryDraft, networkType }) => ({ ...state, [networkType]: { @@ -239,19 +301,6 @@ export const networkReducer = reducerWithInitialState(initialNetworkState) flowTarget, }, })) - .case(updateDomainsLimit, (state, { limit }) => ({ - ...state, - [NetworkType.details]: { - ...state[NetworkType.details], - queries: { - ...state[NetworkType.details].queries, - [IpDetailsTableType.domains]: { - ...state[NetworkType.details].queries.domains, - limit, - }, - }, - }, - })) .case(updateTlsLimit, (state, { limit }) => ({ ...state, [NetworkType.details]: { @@ -265,32 +314,6 @@ export const networkReducer = reducerWithInitialState(initialNetworkState) }, }, })) - .case(updateDomainsFlowDirection, (state, { flowDirection }) => ({ - ...state, - [NetworkType.details]: { - ...state[NetworkType.details], - queries: { - ...state[NetworkType.details].queries, - [IpDetailsTableType.domains]: { - ...state[NetworkType.details].queries.domains, - flowDirection, - }, - }, - }, - })) - .case(updateDomainsSort, (state, { domainsSortField }) => ({ - ...state, - [NetworkType.details]: { - ...state[NetworkType.details], - queries: { - ...state[NetworkType.details].queries, - [IpDetailsTableType.domains]: { - ...state[NetworkType.details].queries.domains, - domainsSortField, - }, - }, - }, - })) .case(updateTlsSort, (state, { tlsSortField }) => ({ ...state, [NetworkType.details]: { diff --git a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts index 3a11949b3990b..c2d1fa2988e1d 100644 --- a/x-pack/legacy/plugins/siem/public/store/network/selectors.ts +++ b/x-pack/legacy/plugins/siem/public/store/network/selectors.ts @@ -10,8 +10,8 @@ import { createSelector } from 'reselect'; import { isFromKueryExpressionValid } from '../../lib/keury'; import { State } from '../reducer'; -import { NetworkDetailsModel, NetworkPageModel, NetworkType } from './model'; -import { FlowTargetNew } from '../../graphql/types'; +import { IpDetailsTableType, NetworkDetailsModel, NetworkPageModel, NetworkType } from './model'; +import { FlowTargetSourceDest } from '../../graphql/types'; const selectNetworkPage = (state: State): NetworkPageModel => state.network.page; @@ -31,14 +31,24 @@ export enum NetworkTableType { topNFlowSource = 'topNFlowSource', topNFlowDestination = 'topNFlowDestination', } -export const topNFlowSelector = (flowTarget: FlowTargetNew) => - createSelector( - selectNetworkPage, +export const topNFlowSelector = (flowTarget: FlowTargetSourceDest, networkType: NetworkType) => { + if (networkType === NetworkType.page) { + return createSelector( + selectNetworkPage, + network => + flowTarget === FlowTargetSourceDest.source + ? network.queries[NetworkTableType.topNFlowSource] + : network.queries[NetworkTableType.topNFlowDestination] + ); + } + return createSelector( + selectNetworkDetails, network => - flowTarget === FlowTargetNew.source - ? network.queries[NetworkTableType.topNFlowSource] - : network.queries[NetworkTableType.topNFlowDestination] + flowTarget === FlowTargetSourceDest.source + ? network.queries[IpDetailsTableType.topNFlowSource] + : network.queries[IpDetailsTableType.topNFlowDestination] ); +}; // Filter Query Selectors export const networkFilterQueryAsJson = () => @@ -79,12 +89,6 @@ export const ipDetailsFlowTargetSelector = () => network => network.flowTarget ); -export const domainsSelector = () => - createSelector( - selectNetworkDetails, - network => network.queries.domains - ); - export const tlsSelector = () => createSelector( selectNetworkDetails, diff --git a/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts index 102cc4d0ae08c..fb65883de12d8 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ip_details/resolvers.ts @@ -6,12 +6,7 @@ import { SourceResolvers } from '../../graphql/types'; import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { - DomainsRequestOptions, - IpDetails, - TlsRequestOptions, - UsersRequestOptions, -} from '../../lib/ip_details'; +import { IpDetails, TlsRequestOptions, UsersRequestOptions } from '../../lib/ip_details'; import { createOptions, createOptionsPaginated } from '../../utils/build_query/create_options'; import { QuerySourceResolver } from '../sources/resolvers'; @@ -20,11 +15,6 @@ export type QueryIpOverviewResolver = ChildResolverOf< QuerySourceResolver >; -export type QueryDomainsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - export type QueryTlsResolver = ChildResolverOf< AppResolverOf, QuerySourceResolver @@ -44,7 +34,6 @@ export const createIpDetailsResolvers = ( ): { Source: { IpOverview: QueryIpOverviewResolver; - Domains: QueryDomainsResolver; Tls: QueryTlsResolver; Users: QueryUsersResolver; }; @@ -54,16 +43,6 @@ export const createIpDetailsResolvers = ( const options = { ...createOptions(source, args, info), ip: args.ip }; return libs.ipDetails.getIpOverview(req, options); }, - async Domains(source, args, { req }, info) { - const options: DomainsRequestOptions = { - ...createOptionsPaginated(source, args, info), - ip: args.ip, - domainsSortField: args.sort, - flowTarget: args.flowTarget, - flowDirection: args.flowDirection, - }; - return libs.ipDetails.getDomains(req, options); - }, async Tls(source, args, { req }, info) { const options: TlsRequestOptions = { ...createOptionsPaginated(source, args, info), diff --git a/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts index 1566c54c7d56b..3acbed3977d73 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/ip_details/schema.gql.ts @@ -42,71 +42,6 @@ const ipOverviewSchema = gql` } `; -const domainsSchema = gql` - enum DomainsFields { - domainName - direction - bytes - packets - uniqueIpCount - } - - input DomainsSortField { - field: DomainsFields! - direction: Direction! - } - - type DomainsNetworkField { - bytes: Float - packets: Float - transport: String - direction: [NetworkDirectionEcs!] - } - - type DomainsItem { - uniqueIpCount: Float - domainName: String - firstSeen: Date - lastSeen: Date - } - - type DomainsNode { - _id: String - timestamp: Date - source: DomainsItem - destination: DomainsItem - client: DomainsItem - server: DomainsItem - network: DomainsNetworkField - } - - type DomainsEdges { - node: DomainsNode! - cursor: CursorType! - } - - type DomainsData { - edges: [DomainsEdges!]! - totalCount: Float! - pageInfo: PageInfoPaginated! - inspect: Inspect - } - - extend type Source { - Domains( - filterQuery: String - id: String - ip: String! - pagination: PaginationInputPaginated! - sort: DomainsSortField! - flowDirection: FlowDirection! - flowTarget: FlowTarget! - timerange: TimerangeInput! - defaultIndex: [String!]! - ): DomainsData! - } -`; - const tlsSchema = gql` enum TlsFields { _id @@ -199,4 +134,4 @@ const usersSchema = gql` } `; -export const ipDetailsSchemas = [ipOverviewSchema, domainsSchema, tlsSchema, usersSchema]; +export const ipDetailsSchemas = [ipOverviewSchema, tlsSchema, usersSchema]; diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts index eb358395bd5b6..23a8d4694ccae 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/resolvers.ts @@ -38,6 +38,7 @@ export const createNetworkResolvers = ( ...createOptionsPaginated(source, args, info), flowTarget: args.flowTarget, networkTopNFlowSort: args.sort, + ip: args.ip, }; return libs.network.getNetworkTopNFlow(req, options); }, diff --git a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts index 52be207fcd871..acd19b6efc0ed 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/network/schema.gql.ts @@ -25,7 +25,7 @@ export const networkSchema = gql` type GeoItem { geo: GeoEcsFields - flowTarget: FlowTarget + flowTarget: FlowTargetSourceDest } type AutonomousSystemItem { @@ -122,7 +122,8 @@ export const networkSchema = gql` NetworkTopNFlow( id: String filterQuery: String - flowTarget: FlowTargetNew! + ip: String + flowTarget: FlowTargetSourceDest! pagination: PaginationInputPaginated! sort: NetworkTopNFlowSortField! timerange: TimerangeInput! diff --git a/x-pack/legacy/plugins/siem/server/graphql/types.ts b/x-pack/legacy/plugins/siem/server/graphql/types.ts index ae17c9ef067b6..8505d3efc4341 100644 --- a/x-pack/legacy/plugins/siem/server/graphql/types.ts +++ b/x-pack/legacy/plugins/siem/server/graphql/types.ts @@ -69,12 +69,6 @@ export interface HostsSortField { direction: Direction; } -export interface DomainsSortField { - field: DomainsFields; - - direction: Direction; -} - export interface TlsSortField { field: TlsFields; @@ -247,17 +241,8 @@ export enum HostsFields { lastSeen = 'lastSeen', } -export enum DomainsFields { - domainName = 'domainName', - direction = 'direction', - bytes = 'bytes', - packets = 'packets', - uniqueIpCount = 'uniqueIpCount', -} - -export enum FlowDirection { - uniDirectional = 'uniDirectional', - biDirectional = 'biDirectional', +export enum TlsFields { + _id = '_id', } export enum FlowTarget { @@ -267,27 +252,12 @@ export enum FlowTarget { source = 'source', } -export enum NetworkDirectionEcs { - inbound = 'inbound', - outbound = 'outbound', - internal = 'internal', - external = 'external', - incoming = 'incoming', - outgoing = 'outgoing', - listening = 'listening', - unknown = 'unknown', -} - -export enum TlsFields { - _id = '_id', -} - export enum UsersFields { name = 'name', count = 'count', } -export enum FlowTargetNew { +export enum FlowTargetSourceDest { destination = 'destination', source = 'source', } @@ -315,6 +285,22 @@ export enum SortFieldTimeline { created = 'created', } +export enum NetworkDirectionEcs { + inbound = 'inbound', + outbound = 'outbound', + internal = 'internal', + external = 'external', + incoming = 'incoming', + outgoing = 'outgoing', + listening = 'listening', + unknown = 'unknown', +} + +export enum FlowDirection { + uniDirectional = 'uniDirectional', + biDirectional = 'biDirectional', +} + export type ToStringArray = string[] | string; export type Date = string; @@ -433,8 +419,6 @@ export interface Source { IpOverview?: Maybe; - Domains: DomainsData; - Tls: TlsData; Users: UsersData; @@ -1330,58 +1314,6 @@ export interface AutonomousSystemOrganization { name?: Maybe; } -export interface DomainsData { - edges: DomainsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface DomainsEdges { - node: DomainsNode; - - cursor: CursorType; -} - -export interface DomainsNode { - _id?: Maybe; - - timestamp?: Maybe; - - source?: Maybe; - - destination?: Maybe; - - client?: Maybe; - - server?: Maybe; - - network?: Maybe; -} - -export interface DomainsItem { - uniqueIpCount?: Maybe; - - domainName?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - -export interface DomainsNetworkField { - bytes?: Maybe; - - packets?: Maybe; - - transport?: Maybe; - - direction?: Maybe; -} - export interface TlsData { edges: TlsEdges[]; @@ -1575,7 +1507,7 @@ export interface AutonomousSystemItem { export interface GeoItem { geo?: Maybe; - flowTarget?: Maybe; + flowTarget?: Maybe; } export interface TopNFlowItemDestination { @@ -2070,25 +2002,6 @@ export interface IpOverviewSourceArgs { defaultIndex: string[]; } -export interface DomainsSourceArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: DomainsSortField; - - flowDirection: FlowDirection; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} export interface TlsSourceArgs { filterQuery?: Maybe; @@ -2155,7 +2068,9 @@ export interface NetworkTopNFlowSourceArgs { filterQuery?: Maybe; - flowTarget: FlowTargetNew; + ip?: Maybe; + + flowTarget: FlowTargetSourceDest; pagination: PaginationInputPaginated; @@ -2618,8 +2533,6 @@ export namespace SourceResolvers { IpOverview?: IpOverviewResolver, TypeParent, TContext>; - Domains?: DomainsResolver; - Tls?: TlsResolver; Users?: UsersResolver; @@ -2796,32 +2709,6 @@ export namespace SourceResolvers { defaultIndex: string[]; } - export type DomainsResolver = Resolver< - R, - Parent, - TContext, - DomainsArgs - >; - export interface DomainsArgs { - filterQuery?: Maybe; - - id?: Maybe; - - ip: string; - - pagination: PaginationInputPaginated; - - sort: DomainsSortField; - - flowDirection: FlowDirection; - - flowTarget: FlowTarget; - - timerange: TimerangeInput; - - defaultIndex: string[]; - } - export type TlsResolver = Resolver< R, Parent, @@ -2925,7 +2812,9 @@ export namespace SourceResolvers { filterQuery?: Maybe; - flowTarget: FlowTargetNew; + ip?: Maybe; + + flowTarget: FlowTargetSourceDest; pagination: PaginationInputPaginated; @@ -5892,178 +5781,6 @@ export namespace AutonomousSystemOrganizationResolvers { > = Resolver; } -export namespace DomainsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = DomainsEdges[], - Parent = DomainsData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver< - R = number, - Parent = DomainsData, - TContext = SiemContext - > = Resolver; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = DomainsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = DomainsData, - TContext = SiemContext - > = Resolver; -} - -export namespace DomainsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver< - R = DomainsNode, - Parent = DomainsEdges, - TContext = SiemContext - > = Resolver; - export type CursorResolver< - R = CursorType, - Parent = DomainsEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace DomainsNodeResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - timestamp?: TimestampResolver, TypeParent, TContext>; - - source?: SourceResolver, TypeParent, TContext>; - - destination?: DestinationResolver, TypeParent, TContext>; - - client?: ClientResolver, TypeParent, TContext>; - - server?: ServerResolver, TypeParent, TContext>; - - network?: NetworkResolver, TypeParent, TContext>; - } - - export type _IdResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type TimestampResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type SourceResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type DestinationResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type ClientResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type ServerResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; - export type NetworkResolver< - R = Maybe, - Parent = DomainsNode, - TContext = SiemContext - > = Resolver; -} - -export namespace DomainsItemResolvers { - export interface Resolvers { - uniqueIpCount?: UniqueIpCountResolver, TypeParent, TContext>; - - domainName?: DomainNameResolver, TypeParent, TContext>; - - firstSeen?: FirstSeenResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - } - - export type UniqueIpCountResolver< - R = Maybe, - Parent = DomainsItem, - TContext = SiemContext - > = Resolver; - export type DomainNameResolver< - R = Maybe, - Parent = DomainsItem, - TContext = SiemContext - > = Resolver; - export type FirstSeenResolver< - R = Maybe, - Parent = DomainsItem, - TContext = SiemContext - > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = DomainsItem, - TContext = SiemContext - > = Resolver; -} - -export namespace DomainsNetworkFieldResolvers { - export interface Resolvers { - bytes?: BytesResolver, TypeParent, TContext>; - - packets?: PacketsResolver, TypeParent, TContext>; - - transport?: TransportResolver, TypeParent, TContext>; - - direction?: DirectionResolver, TypeParent, TContext>; - } - - export type BytesResolver< - R = Maybe, - Parent = DomainsNetworkField, - TContext = SiemContext - > = Resolver; - export type PacketsResolver< - R = Maybe, - Parent = DomainsNetworkField, - TContext = SiemContext - > = Resolver; - export type TransportResolver< - R = Maybe, - Parent = DomainsNetworkField, - TContext = SiemContext - > = Resolver; - export type DirectionResolver< - R = Maybe, - Parent = DomainsNetworkField, - TContext = SiemContext - > = Resolver; -} - export namespace TlsDataResolvers { export interface Resolvers { edges?: EdgesResolver; @@ -6743,7 +6460,7 @@ export namespace GeoItemResolvers { export interface Resolvers { geo?: GeoResolver, TypeParent, TContext>; - flowTarget?: FlowTargetResolver, TypeParent, TContext>; + flowTarget?: FlowTargetResolver, TypeParent, TContext>; } export type GeoResolver< @@ -6752,7 +6469,7 @@ export namespace GeoItemResolvers { TContext = SiemContext > = Resolver; export type FlowTargetResolver< - R = Maybe, + R = Maybe, Parent = GeoItem, TContext = SiemContext > = Resolver; @@ -8193,11 +7910,6 @@ export type IResolvers = { Overview?: OverviewResolvers.Resolvers; AutonomousSystem?: AutonomousSystemResolvers.Resolvers; AutonomousSystemOrganization?: AutonomousSystemOrganizationResolvers.Resolvers; - DomainsData?: DomainsDataResolvers.Resolvers; - DomainsEdges?: DomainsEdgesResolvers.Resolvers; - DomainsNode?: DomainsNodeResolvers.Resolvers; - DomainsItem?: DomainsItemResolvers.Resolvers; - DomainsNetworkField?: DomainsNetworkFieldResolvers.Resolvers; TlsData?: TlsDataResolvers.Resolvers; TlsEdges?: TlsEdgesResolvers.Resolvers; TlsNode?: TlsNodeResolvers.Resolvers; diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.test.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.test.ts index 09eed2af8a980..6493a3e05bfc9 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.test.ts @@ -5,21 +5,13 @@ */ import { FlowTarget } from '../../graphql/types'; -import { - formatDomainsEdges, - getIpOverviewAgg, - getIpOverviewHostAgg, - getUsersEdges, -} from './elasticsearch_adapter'; +import { getIpOverviewAgg, getIpOverviewHostAgg, getUsersEdges } from './elasticsearch_adapter'; import { formattedDestination, formattedEmptySource, formattedHost, formattedSource, - mockDomainsResponseBuckets, - mockFormattedDestination, - mockFormattedSource, mockFormattedUsersEdges, mockUsersData, responseAggs, @@ -51,18 +43,6 @@ describe('elasticsearch_adapter', () => { }); }); - describe('#getDomains', () => { - test('will return a source correctly', () => { - const source = formatDomainsEdges(mockDomainsResponseBuckets, FlowTarget.source); - expect(source).toEqual(mockFormattedSource); - }); - - test('will return a destination correctly', () => { - const destination = formatDomainsEdges(mockDomainsResponseBuckets, FlowTarget.destination); - expect(destination).toEqual(mockFormattedDestination); - }); - }); - describe('#getUsers', () => { test('will format edges correctly', () => { // @ts-ignore Re-work `DatabaseSearchResponse` types as mock ES Response won't match diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.ts index cb781021b7e61..5443ff62f6227 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ip_details/elasticsearch_adapter.ts @@ -8,9 +8,6 @@ import { get, getOr } from 'lodash/fp'; import { AutonomousSystem, - DomainsData, - DomainsEdges, - FlowTarget, GeoEcsFields, HostEcsFields, IpOverviewData, @@ -23,16 +20,9 @@ import { inspectStringifyObject } from '../../utils/build_query'; import { DatabaseSearchResponse, FrameworkAdapter, FrameworkRequest } from '../framework'; import { TermAggregation } from '../types'; import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants'; -import { - DomainsRequestOptions, - IpOverviewRequestOptions, - TlsRequestOptions, - UsersRequestOptions, -} from './index'; -import { buildDomainsQuery } from './query_domains.dsl'; +import { IpOverviewRequestOptions, TlsRequestOptions, UsersRequestOptions } from './index'; import { buildOverviewQuery } from './query_overview.dsl'; import { - DomainsBuckets, IpDetailsAdapter, IpOverviewHit, OverviewHit, @@ -72,42 +62,6 @@ export class ElasticsearchIpOverviewAdapter implements IpDetailsAdapter { }; } - public async getDomains( - request: FrameworkRequest, - options: DomainsRequestOptions - ): Promise { - if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { - throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); - } - const dsl = buildDomainsQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - - const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination; - const totalCount = getOr(0, 'aggregations.domain_count.value', response); - const domainsEdges: DomainsEdges[] = getDomainsEdges(response, options); - const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount; - const edges = domainsEdges.splice(cursorStart, querySize - cursorStart); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - const showMorePagesIndicator = totalCount > fakeTotalCount; - return { - edges, - inspect, - pageInfo: { - activePage: activePage ? activePage : 0, - fakeTotalCount, - showMorePagesIndicator, - }, - totalCount, - }; - } - public async getTls(request: FrameworkRequest, options: TlsRequestOptions): Promise { if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); @@ -219,40 +173,6 @@ export const getIpOverviewHostAgg = (overviewHostHit: OverviewHostHit | {}) => { }; }; -const getDomainsEdges = ( - response: DatabaseSearchResponse, - options: DomainsRequestOptions -): DomainsEdges[] => { - return formatDomainsEdges( - getOr([], `aggregations.${options.flowTarget}_domains.buckets`, response), - options.flowTarget - ); -}; - -export const formatDomainsEdges = ( - buckets: DomainsBuckets[], - flowTarget: FlowTarget -): DomainsEdges[] => - buckets.map((bucket: DomainsBuckets) => ({ - node: { - _id: bucket.key, - [flowTarget]: { - uniqueIpCount: getOrNumber('uniqueIpCount.value', bucket), - domainName: bucket.key, - lastSeen: get('lastSeen.value_as_string', bucket), - }, - network: { - bytes: getOrNumber('bytes.value', bucket), - packets: getOrNumber('packets.value', bucket), - direction: bucket.direction.buckets.map(bucketDir => bucketDir.key), - }, - }, - cursor: { - value: bucket.key, - tiebreaker: null, - }, - })); - const getTlsEdges = ( response: DatabaseSearchResponse, options: TlsRequestOptions @@ -281,14 +201,6 @@ export const formatTlsEdges = (buckets: TlsBuckets[]): TlsEdges[] => { }); }; -const getOrNumber = (path: string, bucket: DomainsBuckets) => { - const numb = get(path, bucket); - if (numb == null) { - return null; - } - return numb; -}; - export const getUsersEdges = ( response: DatabaseSearchResponse ): UsersEdges[] => diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/index.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/index.ts index d06ce065931a7..4a16664790a05 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ip_details/index.ts @@ -5,9 +5,6 @@ */ import { - DomainsData, - DomainsSortField, - FlowDirection, FlowTarget, IpOverviewData, TlsSortField, @@ -25,13 +22,6 @@ export interface IpOverviewRequestOptions extends RequestOptions { ip: string; } -export interface DomainsRequestOptions extends RequestOptionsPaginated { - ip: string; - domainsSortField: DomainsSortField; - flowTarget: FlowTarget; - flowDirection: FlowDirection; -} - export interface TlsRequestOptions extends RequestOptionsPaginated { ip: string; tlsSortField: TlsSortField; @@ -53,13 +43,6 @@ export class IpDetails { return this.adapter.getIpDetails(req, options); } - public async getDomains( - req: FrameworkRequest, - options: DomainsRequestOptions - ): Promise { - return this.adapter.getDomains(req, options); - } - public async getTls(req: FrameworkRequest, options: TlsRequestOptions): Promise { return this.adapter.getTls(req, options); } diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/mock.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/mock.ts index 9466f9d437fa3..1db86e7766fcf 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/mock.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ip_details/mock.ts @@ -4,9 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DomainsEdges, NetworkDirectionEcs, UsersEdges } from '../../graphql/types'; +import { UsersEdges } from '../../graphql/types'; -import { DomainsBuckets, IpOverviewHit, UsersResponse } from './types'; +import { IpOverviewHit, UsersResponse } from './types'; export const responseAggs: IpOverviewHit = { aggregations: { @@ -252,75 +252,6 @@ export const formattedEmptySource = { }, }; -export const mockDomainsResponseBuckets: DomainsBuckets[] = [ - { - key: 'example.com', - uniqueIpCount: { - value: 805, - }, - lastSeen: { - value: 1554920919000, - value_as_string: '2019-04-10T18:28:39.000Z', - }, - bytes: { - value: 974964465, - }, - packets: { - value: 16946245, - }, - direction: { - buckets: [ - { - key: NetworkDirectionEcs.outbound, - doc_count: 51668, - }, - { - key: NetworkDirectionEcs.inbound, - doc_count: 25681, - }, - ], - }, - }, -]; - -export const mockFormattedSource: DomainsEdges[] = [ - { - cursor: { tiebreaker: null, value: 'example.com' }, - node: { - _id: 'example.com', - network: { - bytes: 974964465, - direction: [NetworkDirectionEcs.outbound, NetworkDirectionEcs.inbound], - packets: 16946245, - }, - source: { - domainName: 'example.com', - lastSeen: '2019-04-10T18:28:39.000Z', - uniqueIpCount: 805, - }, - }, - }, -]; - -export const mockFormattedDestination: DomainsEdges[] = [ - { - cursor: { tiebreaker: null, value: 'example.com' }, - node: { - _id: 'example.com', - destination: { - domainName: 'example.com', - lastSeen: '2019-04-10T18:28:39.000Z', - uniqueIpCount: 805, - }, - network: { - bytes: 974964465, - direction: [NetworkDirectionEcs.outbound, NetworkDirectionEcs.inbound], - packets: 16946245, - }, - }, - }, -]; - export const mockUsersData: UsersResponse = { took: 445, timed_out: false, diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/query_domains.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/query_domains.dsl.ts deleted file mode 100644 index e81a337458203..0000000000000 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/query_domains.dsl.ts +++ /dev/null @@ -1,204 +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 { - Direction, - DomainsFields, - DomainsSortField, - FlowDirection, - FlowTarget, -} from '../../graphql/types'; -import { assertUnreachable, createQueryFilterClauses } from '../../utils/build_query'; - -import { DomainsRequestOptions } from './index'; - -const getAggs = ( - ip: string, - flowTarget: FlowTarget, - flowDirection: FlowDirection, - domainsSortField: DomainsSortField, - querySize: number -) => { - return { - domain_count: { - cardinality: { - field: `${flowTarget}.domain`, - }, - }, - [`${flowTarget}_domains`]: { - terms: { - field: `${flowTarget}.domain`, - size: querySize, - order: { - ...getQueryOrder(domainsSortField), - }, - }, - aggs: { - lastSeen: { - max: { - field: '@timestamp', - }, - }, - bytes: { - sum: { - field: - flowDirection === FlowDirection.uniDirectional - ? 'network.bytes' - : `${flowTarget}.bytes`, - }, - }, - direction: { - terms: { - field: 'network.direction', - }, - }, - uniqueIpCount: { - cardinality: { - field: `${getOppositeField(flowTarget)}.ip`, - }, - }, - packets: { - sum: { - field: - flowDirection === FlowDirection.uniDirectional - ? 'network.packets' - : `${flowTarget}.packets`, - }, - }, - }, - }, - }; -}; - -const getUniDirectionalFilter = (flowDirection: FlowDirection) => - flowDirection === FlowDirection.uniDirectional - ? { - must_not: [ - { - exists: { - field: 'destination.bytes', - }, - }, - ], - } - : {}; - -const getBiDirectionalFilter = (flowDirection: FlowDirection, flowTarget: FlowTarget) => { - if ( - flowDirection === FlowDirection.biDirectional && - [FlowTarget.source, FlowTarget.destination].includes(flowTarget) - ) { - return [ - { - exists: { - field: 'source.bytes', - }, - }, - { - exists: { - field: 'destination.bytes', - }, - }, - ]; - } else if ( - flowDirection === FlowDirection.biDirectional && - [FlowTarget.client, FlowTarget.server].includes(flowTarget) - ) { - return [ - { - exists: { - field: 'client.bytes', - }, - }, - { - exists: { - field: 'server.bytes', - }, - }, - ]; - } - return []; -}; - -export const buildDomainsQuery = ({ - ip, - domainsSortField, - filterQuery, - flowDirection, - flowTarget, - pagination: { querySize }, - defaultIndex, - sourceConfiguration: { - fields: { timestamp }, - }, - timerange: { from, to }, -}: DomainsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { range: { [timestamp]: { gte: from, lte: to } } }, - { term: { [`${flowTarget}.ip`]: ip } }, - ...getBiDirectionalFilter(flowDirection, flowTarget), - ]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - body: { - aggs: { - ...getAggs(ip, flowTarget, flowDirection, domainsSortField, querySize), - }, - query: { - bool: { - filter, - ...getUniDirectionalFilter(flowDirection), - }, - }, - size: 0, - track_total_hits: false, - }, - }; - - return dslQuery; -}; - -const getOppositeField = (flowTarget: FlowTarget): FlowTarget => { - switch (flowTarget) { - case FlowTarget.source: - return FlowTarget.destination; - case FlowTarget.destination: - return FlowTarget.source; - case FlowTarget.server: - return FlowTarget.client; - case FlowTarget.client: - return FlowTarget.server; - default: - return assertUnreachable(flowTarget); - } -}; - -type QueryOrder = - | { _key: Direction } - | { bytes: Direction } - | { packets: Direction } - | { uniqueIpCount: Direction }; - -const getQueryOrder = (domainsSortField: DomainsSortField): QueryOrder => { - switch (domainsSortField.field) { - case DomainsFields.bytes: - return { bytes: domainsSortField.direction }; - case DomainsFields.packets: - return { packets: domainsSortField.direction }; - case DomainsFields.uniqueIpCount: - return { uniqueIpCount: domainsSortField.direction }; - case DomainsFields.domainName: - return { _key: domainsSortField.direction }; - case DomainsFields.direction: - return { _key: domainsSortField.direction }; - default: - return assertUnreachable(domainsSortField.field); - } -}; diff --git a/x-pack/legacy/plugins/siem/server/lib/ip_details/types.ts b/x-pack/legacy/plugins/siem/server/lib/ip_details/types.ts index a53d04544007d..be7519e64b651 100644 --- a/x-pack/legacy/plugins/siem/server/lib/ip_details/types.ts +++ b/x-pack/legacy/plugins/siem/server/lib/ip_details/types.ts @@ -4,14 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { DomainsData, IpOverviewData, NetworkDirectionEcs, UsersData } from '../../graphql/types'; +import { TlsData, IpOverviewData, UsersData } from '../../graphql/types'; import { FrameworkRequest, RequestBasicOptions } from '../framework'; import { Hit, ShardsResponse, TotalValue } from '../types'; export interface IpDetailsAdapter { getIpDetails(request: FrameworkRequest, options: RequestBasicOptions): Promise; - getDomains(request: FrameworkRequest, options: RequestBasicOptions): Promise; - getTls(request: FrameworkRequest, options: RequestBasicOptions): Promise; + getTls(request: FrameworkRequest, options: RequestBasicOptions): Promise; getUsers(request: FrameworkRequest, options: RequestBasicOptions): Promise; } @@ -82,39 +81,6 @@ export interface IpOverviewHit { timeout: number; } -export interface DirectionBuckets { - key: NetworkDirectionEcs; - doc_count?: number; -} - -export interface DomainsBuckets { - key: string; - timestamp?: { - value: number; - value_as_string: string; - }; - uniqueIpCount: { - value: number; - }; - bytes: { - value: number; - }; - packets: { - value: number; - }; - direction: { - buckets: DirectionBuckets[]; - }; - firstSeen?: { - value: number; - value_as_string: string; - }; - lastSeen?: { - value: number; - value_as_string: string; - }; -} - export interface TlsBuckets { key: string; timestamp?: { diff --git a/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts b/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts index fcf29c1c283c6..c3bcfafac8757 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/elastic_adapter.test.ts @@ -6,11 +6,21 @@ import { cloneDeep } from 'lodash/fp'; -import { FlowTargetNew, NetworkTopNFlowData } from '../../graphql/types'; +import { FlowTargetSourceDest, NetworkTopNFlowData } from '../../graphql/types'; import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { ElasticsearchNetworkAdapter } from './elasticsearch_adapter'; -import { mockOptions, mockRequest, mockResponse, mockResult, mockTopNFlowQueryDsl } from './mock'; +import { + mockOptions, + mockRequest, + mockResponse, + mockResult, + mockOptionsIp, + mockRequestIp, + mockResponseIp, + mockResultIp, + mockTopNFlowQueryDsl, +} from './mock'; jest.mock('./query_top_n_flow.dsl', () => { const r = jest.requireActual('./query_top_n_flow.dsl'); @@ -49,7 +59,7 @@ describe('Network Top N flow elasticsearch_adapter with FlowTarget=source', () = describe('Unhappy Path - No data', () => { const mockNoDataResponse = cloneDeep(mockResponse); mockNoDataResponse.aggregations.top_n_flow_count.value = 0; - mockNoDataResponse.aggregations[FlowTargetNew.source].buckets = []; + mockNoDataResponse.aggregations[FlowTargetSourceDest.source].buckets = []; const mockCallWithRequest = jest.fn(); mockCallWithRequest.mockResolvedValue(mockNoDataResponse); const mockFramework: FrameworkAdapter = { @@ -90,8 +100,11 @@ describe('Network Top N flow elasticsearch_adapter with FlowTarget=source', () = const mockNoPaginationResponse = cloneDeep(mockResponse); mockNoPaginationResponse.aggregations.top_n_flow_count.value = 10; mockNoPaginationResponse.aggregations[ - FlowTargetNew.source - ].buckets = mockNoPaginationResponse.aggregations[FlowTargetNew.source].buckets.slice(0, -1); + FlowTargetSourceDest.source + ].buckets = mockNoPaginationResponse.aggregations[FlowTargetSourceDest.source].buckets.slice( + 0, + -1 + ); const mockCallWithRequest = jest.fn(); mockCallWithRequest.mockResolvedValue(mockNoPaginationResponse); const mockFramework: FrameworkAdapter = { @@ -115,4 +128,29 @@ describe('Network Top N flow elasticsearch_adapter with FlowTarget=source', () = expect(data.pageInfo.showMorePagesIndicator).toBeFalsy(); }); }); + + describe('Filter by IP', () => { + const mockCallWithRequest = jest.fn(); + mockCallWithRequest.mockResolvedValue(mockResponseIp); + const mockFramework: FrameworkAdapter = { + version: 'mock', + callWithRequest: mockCallWithRequest, + exposeStaticDir: jest.fn(), + getIndexPatternsService: jest.fn(), + getSavedObjectsService: jest.fn(), + registerGraphQLEndpoint: jest.fn(), + }; + jest.doMock('../framework', () => ({ + callWithRequest: mockCallWithRequest, + })); + + test('getNetworkTopNFlow', async () => { + const EsNetworkTopNFlow = new ElasticsearchNetworkAdapter(mockFramework); + const data: NetworkTopNFlowData = await EsNetworkTopNFlow.getNetworkTopNFlow( + mockRequestIp as FrameworkRequest, + mockOptionsIp + ); + expect(data).toEqual(mockResultIp); + }); + }); }); diff --git a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts index 925e40de32f71..0b787a08cec17 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/elasticsearch_adapter.ts @@ -7,9 +7,8 @@ import { get, getOr } from 'lodash/fp'; import { - FlowTargetNew, + FlowTargetSourceDest, AutonomousSystemItem, - FlowTarget, GeoItem, NetworkDnsData, NetworkDnsEdges, @@ -114,10 +113,10 @@ const getTopNFlowEdges = ( }; const getFlowTargetFromString = (flowAsString: string) => - flowAsString === 'source' ? FlowTarget.source : FlowTarget.destination; + flowAsString === 'source' ? FlowTargetSourceDest.source : FlowTargetSourceDest.destination; const getGeoItem = (result: NetworkTopNFlowBuckets): GeoItem | null => - result.location.top_geo.hits.hits.length > 0 + result.location.top_geo.hits.hits.length > 0 && result.location.top_geo.hits.hits[0]._source ? { geo: getOr( '', @@ -154,7 +153,7 @@ const getAsItem = (result: NetworkTopNFlowBuckets): AutonomousSystemItem | null const formatTopNFlowEdges = ( buckets: NetworkTopNFlowBuckets[], - flowTarget: FlowTargetNew + flowTarget: FlowTargetSourceDest ): NetworkTopNFlowEdges[] => buckets.map((bucket: NetworkTopNFlowBuckets) => ({ node: { diff --git a/x-pack/legacy/plugins/siem/server/lib/network/index.ts b/x-pack/legacy/plugins/siem/server/lib/network/index.ts index 774a6d02ce576..c183122af998f 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/index.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/index.ts @@ -5,7 +5,8 @@ */ import { - FlowTargetNew, + FlowTargetSourceDest, + Maybe, NetworkDnsSortField, NetworkTopNFlowData, NetworkTopNFlowSortField, @@ -18,7 +19,8 @@ export * from './types'; export interface NetworkTopNFlowRequestOptions extends RequestOptionsPaginated { networkTopNFlowSort: NetworkTopNFlowSortField; - flowTarget: FlowTargetNew; + flowTarget: FlowTargetSourceDest; + ip?: Maybe; } export interface NetworkDnsRequestOptions extends RequestOptionsPaginated { diff --git a/x-pack/legacy/plugins/siem/server/lib/network/mock.ts b/x-pack/legacy/plugins/siem/server/lib/network/mock.ts index 2e36acefa0cdb..b0df45ab60a2c 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/mock.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/mock.ts @@ -5,7 +5,7 @@ */ import { defaultIndexPattern } from '../../../default_index_pattern'; -import { Direction, FlowTargetNew, NetworkTopNFlowFields } from '../../graphql/types'; +import { Direction, FlowTargetSourceDest, NetworkTopNFlowFields } from '../../graphql/types'; import { NetworkTopNFlowRequestOptions } from '.'; @@ -55,7 +55,7 @@ export const mockOptions: NetworkTopNFlowRequestOptions = { '__typename', ], networkTopNFlowSort: { field: NetworkTopNFlowFields.bytes_out, direction: Direction.desc }, - flowTarget: FlowTargetNew.source, + flowTarget: FlowTargetSourceDest.source, }; export const mockRequest = { @@ -64,7 +64,7 @@ export const mockRequest = { operationName: 'GetNetworkTopNFlowQuery', variables: { filterQuery: '', - flowTarget: FlowTargetNew.source, + flowTarget: FlowTargetSourceDest.source, pagination: { activePage: 0, cursorStart: 0, @@ -74,56 +74,96 @@ export const mockRequest = { sourceId: 'default', timerange: { interval: '12h', from: 1549765830772, to: 1549852230772 }, }, - query: `query GetNetworkTopNFlowQuery($sourceId: ID!, $sort: NetworkTopNFlowSortField!, $flowTarget: FlowTargetNew!, $timerange: TimerangeInput!, $pagination: PaginationInput!, $filterQuery: String) { - source(id: $sourceId) { - id - NetworkTopNFlow(sort: $sort, flowTarget: $flowTarget, timerange: $timerange, pagination: $pagination, filterQuery: $filterQuery) { - totalCount - edges { - node { - source { - autonomous_system - domain - ip - location - flows - destination_ips - __typename + query: ` + query GetNetworkTopNFlowQuery( + $sourceId: ID! + $ip: String + $filterQuery: String + $pagination: PaginationInputPaginated! + $sort: NetworkTopNFlowSortField! + $flowTarget: FlowTargetSourceDest! + $timerange: TimerangeInput! + $defaultIndex: [String!]! + $inspect: Boolean! + ) { + source(id: $sourceId) { + id + NetworkTopNFlow( + filterQuery: $filterQuery + flowTarget: $flowTarget + ip: $ip + pagination: $pagination + sort: $sort + timerange: $timerange + defaultIndex: $defaultIndex + ) { + totalCount + edges { + node { + source { + autonomous_system { + name + number + } + domain + ip + location { + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name } - destination { - autonomous_system - domain - ip - location - source_ips - __typename - } - network { - bytes_in - bytes_out - __typename + flowTarget + } + flows + destination_ips + } + destination { + autonomous_system { + name + number + } + domain + ip + location { + geo { + continent_name + country_name + country_iso_code + city_name + region_iso_code + region_name } - __typename + flowTarget + } + flows + source_ips } - cursor { - value - __typename + network { + bytes_in + bytes_out } - __typename } - pageInfo { - activePage - __typename - fakeTotalCount - __typename - showMorePagesIndicator - __typename + cursor { + value } - __typename } - __typename + pageInfo { + activePage + fakeTotalCount + showMorePagesIndicator + } + inspect @include(if: $inspect) { + dsl + response + } } - }`, + } + } +`, }, }; @@ -144,7 +184,7 @@ export const mockResponse = { top_n_flow_count: { value: 545, }, - [FlowTargetNew.source]: { + [FlowTargetSourceDest.source]: { buckets: [ { key: '1.1.1.1', @@ -1459,3 +1499,178 @@ export const mockResult = { }, totalCount: 545, }; + +export const mockOptionsIp: NetworkTopNFlowRequestOptions = { + ...mockOptions, + ip: '1.1.1.1', +}; + +export const mockRequestIp = { + ...mockRequest, + payload: { + ...mockRequest.payload, + variables: { + ...mockRequest.payload.variables, + ip: '1.1.1.1', + }, + }, +}; + +export const mockResponseIp = { + took: 122, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + max_score: null, + hits: [], + }, + aggregations: { + top_n_flow_count: { + value: 1, + }, + [FlowTargetSourceDest.source]: { + buckets: [ + { + key: '1.1.1.1', + flows: { value: 1234567 }, + destination_ips: { value: 345345 }, + bytes_in: { + value: 11276023407, + }, + bytes_out: { + value: 1025631, + }, + location: { + doc_count: 14, + top_geo: { + hits: { + total: { + value: 14, + relation: 'eq', + }, + max_score: 1, + hits: [ + { + _index: 'filebeat-8.0.0-2019.06.19-000005', + _type: '_doc', + _id: 'dd4fa2d4bd-692279846149410', + _score: 1, + _source: { + source: { + geo: { + continent_name: 'North America', + region_iso_code: 'US-PA', + city_name: 'Philadelphia', + country_iso_code: 'US', + region_name: 'Pennsylvania', + location: { + lon: -75.1534, + lat: 39.9359, + }, + }, + }, + }, + }, + ], + }, + }, + }, + autonomous_system: { + doc_count: 14, + top_as: { + hits: { + total: { + value: 14, + relation: 'eq', + }, + max_score: 1, + hits: [ + { + _index: 'filebeat-8.0.0-2019.06.19-000005', + _type: '_doc', + _id: 'dd4fa2d4bd-692279846149410', + _score: 1, + _source: { + source: { + as: { + number: 3356, + organization: { + name: 'Level 3 Parent, LLC', + }, + }, + }, + }, + }, + ], + }, + }, + }, + domain: { + buckets: [ + { + key: 'test.1.net', + }, + ], + }, + }, + ], + }, + }, +}; + +export const mockResultIp = { + inspect: { + dsl: [JSON.stringify(mockTopNFlowQueryDsl, null, 2)], + response: [JSON.stringify(mockResponseIp, null, 2)], + }, + edges: [ + { + cursor: { + tiebreaker: null, + value: '1.1.1.1', + }, + node: { + _id: '1.1.1.1', + network: { + bytes_in: 11276023407, + bytes_out: 1025631, + }, + source: { + domain: ['test.1.net'], + ip: '1.1.1.1', + autonomous_system: { + name: 'Level 3 Parent, LLC', + number: 3356, + }, + location: { + flowTarget: 'source', + geo: { + city_name: 'Philadelphia', + continent_name: 'North America', + country_iso_code: 'US', + location: { + lat: 39.9359, + lon: -75.1534, + }, + region_iso_code: 'US-PA', + region_name: 'Pennsylvania', + }, + }, + flows: 1234567, + destination_ips: 345345, + }, + }, + }, + ], + pageInfo: { + activePage: 0, + fakeTotalCount: 1, + showMorePagesIndicator: false, + }, + totalCount: 1, +}; diff --git a/x-pack/legacy/plugins/siem/server/lib/network/query_top_n_flow.dsl.ts b/x-pack/legacy/plugins/siem/server/lib/network/query_top_n_flow.dsl.ts index acc921606c8e8..5fcd5bf5d7187 100644 --- a/x-pack/legacy/plugins/siem/server/lib/network/query_top_n_flow.dsl.ts +++ b/x-pack/legacy/plugins/siem/server/lib/network/query_top_n_flow.dsl.ts @@ -6,7 +6,7 @@ import { Direction, - FlowTargetNew, + FlowTargetSourceDest, NetworkTopNFlowSortField, NetworkTopNFlowFields, } from '../../graphql/types'; @@ -14,7 +14,7 @@ import { assertUnreachable, createQueryFilterClauses } from '../../utils/build_q import { NetworkTopNFlowRequestOptions } from './index'; -const getCountAgg = (flowTarget: FlowTargetNew) => ({ +const getCountAgg = (flowTarget: FlowTargetSourceDest) => ({ top_n_flow_count: { cardinality: { field: `${flowTarget}.ip`, @@ -32,6 +32,7 @@ export const buildTopNFlowQuery = ({ fields: { timestamp }, }, timerange: { from, to }, + ip, }: NetworkTopNFlowRequestOptions) => { const filter = [ ...createQueryFilterClauses(filterQuery), @@ -48,9 +49,21 @@ export const buildTopNFlowQuery = ({ ...getFlowTargetAggs(networkTopNFlowSort, flowTarget, querySize), }, query: { - bool: { - filter, - }, + bool: ip + ? { + filter, + should: [ + { + term: { + [`${getOppositeField(flowTarget)}.ip`]: ip, + }, + }, + ], + minimum_should_match: 1, + } + : { + filter, + }, }, }, size: 0, @@ -61,7 +74,7 @@ export const buildTopNFlowQuery = ({ const getFlowTargetAggs = ( networkTopNFlowSortField: NetworkTopNFlowSortField, - flowTarget: FlowTargetNew, + flowTarget: FlowTargetSourceDest, querySize: number ) => ({ [flowTarget]: { @@ -142,12 +155,12 @@ const getFlowTargetAggs = ( }, }); -export const getOppositeField = (flowTarget: FlowTargetNew): FlowTargetNew => { +export const getOppositeField = (flowTarget: FlowTargetSourceDest): FlowTargetSourceDest => { switch (flowTarget) { - case FlowTargetNew.source: - return FlowTargetNew.destination; - case FlowTargetNew.destination: - return FlowTargetNew.source; + case FlowTargetSourceDest.source: + return FlowTargetSourceDest.destination; + case FlowTargetSourceDest.destination: + return FlowTargetSourceDest.source; } assertUnreachable(flowTarget); }; diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0f7fe7c0eefc0..c6cf439c20b9b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9581,19 +9581,6 @@ "xpack.siem.network.emptyActionPrimary": "セットアップの手順を表示", "xpack.siem.network.emptyActionSecondary": "ドキュメントに移動", "xpack.siem.network.emptyTitle": "SIEM アプリケーションのネットワークに関連したインデックスがないようです", - "xpack.siem.network.ipDetails.domainsTable.columns.bytesTitle": "バイト", - "xpack.siem.network.ipDetails.domainsTable.columns.directionTitle": "方向", - "xpack.siem.network.ipDetails.domainsTable.columns.domainNameTitle": "ドメイン名", - "xpack.siem.network.ipDetails.domainsTable.columns.firstLastSeenToolTip": "選択された日付範囲との相関付けです", - "xpack.siem.network.ipDetails.domainsTable.columns.lastSeenTitle": "前回の認識", - "xpack.siem.network.ipDetails.domainsTable.columns.packetsTitle": "パケット", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueClientsTitle": "固有のサーバー", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueDestinationsTitle": "固有のデスティネーション", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueServersTitle": "固有のクライアント", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueSourcesTitle": "固有のソース", - "xpack.siem.network.ipDetails.domainsTable.domainsTitle": "ドメイン", - "xpack.siem.network.ipDetails.domainsTable.rows": "{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}", - "xpack.siem.network.ipDetails.domainsTable.unit": "{totalCount, plural, =1 {domain} other {domains}}", "xpack.siem.network.ipDetails.ipOverview.autonomousSystemTitle": "自動システム", "xpack.siem.network.ipDetails.ipOverview.firstSeenTitle": "初回の認識", "xpack.siem.network.ipDetails.ipOverview.hostIdTitle": "ホスト ID", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b485eef915d57..5e34e8d6eec3d 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9746,19 +9746,6 @@ "xpack.siem.network.emptyActionPrimary": "查看设置说明", "xpack.siem.network.emptyActionSecondary": "前往文档", "xpack.siem.network.emptyTitle": "似乎您在 SIEM 应用程序中没有与网络相关的索引", - "xpack.siem.network.ipDetails.domainsTable.columns.bytesTitle": "字节", - "xpack.siem.network.ipDetails.domainsTable.columns.directionTitle": "方向", - "xpack.siem.network.ipDetails.domainsTable.columns.domainNameTitle": "域名", - "xpack.siem.network.ipDetails.domainsTable.columns.firstLastSeenToolTip": "相对于选定日期范围", - "xpack.siem.network.ipDetails.domainsTable.columns.lastSeenTitle": "最后看到时间", - "xpack.siem.network.ipDetails.domainsTable.columns.packetsTitle": "数据包", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueClientsTitle": "唯一服务器", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueDestinationsTitle": "唯一目标", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueServersTitle": "唯一客户端", - "xpack.siem.network.ipDetails.domainsTable.columns.uniqueSourcesTitle": "唯一源", - "xpack.siem.network.ipDetails.domainsTable.domainsTitle": "域", - "xpack.siem.network.ipDetails.domainsTable.rows": "{numRows} {numRows, plural, =0 {rows} =1 {row} other {rows}}", - "xpack.siem.network.ipDetails.domainsTable.unit": "{totalCount, plural, =1 {domain} other {domains}}", "xpack.siem.network.ipDetails.ipOverview.autonomousSystemTitle": "自治系统", "xpack.siem.network.ipDetails.ipOverview.firstSeenTitle": "首次看到时间", "xpack.siem.network.ipDetails.ipOverview.hostIdTitle": "主机 ID", diff --git a/x-pack/test/api_integration/apis/siem/domains.ts b/x-pack/test/api_integration/apis/siem/domains.ts deleted file mode 100644 index 7965feb0e30f4..0000000000000 --- a/x-pack/test/api_integration/apis/siem/domains.ts +++ /dev/null @@ -1,141 +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 { domainsQuery } from '../../../../legacy/plugins/siem/public/containers/domains/index.gql_query'; -import { - Direction, - DomainsFields, - FlowDirection, - FlowTarget, - GetDomainsQuery, -} from '../../../../legacy/plugins/siem/public/graphql/types'; -import { FtrProviderContext } from '../../ftr_provider_context'; - -const FROM = new Date('2000-01-01T00:00:00.000Z').valueOf(); -const TO = new Date('3000-01-01T00:00:00.000Z').valueOf(); -const IP = '10.100.7.196'; - -export default function({ getService }: FtrProviderContext) { - const esArchiver = getService('esArchiver'); - const client = getService('siemGraphQLClient'); - describe('Domains', () => { - describe('With filebeat', () => { - before(() => esArchiver.load('filebeat/default')); - after(() => esArchiver.unload('filebeat/default')); - - it('Ensure data is returned for FlowTarget.Source and Direction.Unidirectional', () => { - return client - .query({ - query: domainsQuery, - variables: { - sourceId: 'default', - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - ip: IP, - flowDirection: FlowDirection.uniDirectional, - flowTarget: FlowTarget.source, - sort: { field: DomainsFields.bytes, direction: Direction.desc }, - pagination: { - activePage: 0, - cursorStart: 0, - fakePossibleCount: 30, - querySize: 10, - }, - defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - inspect: false, - }, - }) - .then(resp => { - const domains = resp.data.source.Domains; - expect(domains.edges.length).to.be(1); - expect(domains.totalCount).to.be(1); - expect(domains.edges[0].node.source!.uniqueIpCount).to.be(122); - expect(domains.edges[0].node.source!.domainName).to.be( - 'samsungtv-kitchen.iot.sr.local.crowbird.com' - ); - expect(domains.edges[0].node.network!.bytes).to.be(25209932); - }); - }); - - it('Ensure data is returned for FlowTarget.Source and Direction.Bidirectional', () => { - return client - .query({ - query: domainsQuery, - variables: { - sourceId: 'default', - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - ip: IP, - flowDirection: FlowDirection.biDirectional, - flowTarget: FlowTarget.source, - sort: { field: DomainsFields.bytes, direction: Direction.desc }, - pagination: { - activePage: 0, - cursorStart: 0, - fakePossibleCount: 30, - querySize: 10, - }, - defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - inspect: false, - }, - }) - .then(resp => { - const domains = resp.data.source.Domains; - expect(domains.edges.length).to.be(1); - expect(domains.totalCount).to.be(1); - expect(domains.edges[0].node.source!.domainName).to.be( - 'samsungtv-kitchen.iot.sr.local.crowbird.com' - ); - expect(domains.edges[0].node.source!.uniqueIpCount).to.be(81); - expect(domains.edges[0].node.network!.bytes).to.be(27033419); - }); - }); - - it('Ensure data is returned for FlowTarget.Destination and Direction.Unidirectional and Pagination works', () => { - return client - .query({ - query: domainsQuery, - variables: { - sourceId: 'default', - timerange: { - interval: '12h', - to: TO, - from: FROM, - }, - ip: IP, - flowDirection: FlowDirection.uniDirectional, - flowTarget: FlowTarget.destination, - sort: { field: DomainsFields.bytes, direction: Direction.desc }, - pagination: { - activePage: 0, - cursorStart: 0, - fakePossibleCount: 30, - querySize: 10, - }, - defaultIndex: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'], - inspect: false, - }, - }) - .then(resp => { - const domains = resp.data.source.Domains; - expect(domains.edges.length).to.be(10); - expect(domains.totalCount).to.be(12); - expect(domains.edges.map(i => i.node.destination!.domainName).join(',')).to.be( - 'samsungtv-kitchen.iot.sr.local.crowbird.com,12s3.lvlt.dash.row.aiv-cdn.net,151.205.0.17,151.205.0.19,151.205.0.21,151.205.0.23,15s3.lvlt.dash.row.aiv-cdn.net,api-global.netflix.com,d25xi40x97liuc.cloudfront.net,d2lkq7nlcrdi7q.cloudfront.net' - ); - expect(domains.pageInfo.fakeTotalCount).to.equal(12); - }); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/siem/index.js b/x-pack/test/api_integration/apis/siem/index.js index a28c2f42a52df..77edf1e55c63c 100644 --- a/x-pack/test/api_integration/apis/siem/index.js +++ b/x-pack/test/api_integration/apis/siem/index.js @@ -7,7 +7,6 @@ export default function ({ loadTestFile }) { describe('Siem GraphQL Endpoints', () => { loadTestFile(require.resolve('./authentications')); - loadTestFile(require.resolve('./domains')); loadTestFile(require.resolve('./events_over_time')); loadTestFile(require.resolve('./hosts')); loadTestFile(require.resolve('./kpi_network')); diff --git a/x-pack/test/api_integration/apis/siem/network_top_n_flow.ts b/x-pack/test/api_integration/apis/siem/network_top_n_flow.ts index 9b5861dfedb4c..efa0dc9c72d9c 100644 --- a/x-pack/test/api_integration/apis/siem/network_top_n_flow.ts +++ b/x-pack/test/api_integration/apis/siem/network_top_n_flow.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { networkTopNFlowQuery } from '../../../../legacy/plugins/siem/public/containers/network_top_n_flow/index.gql_query'; import { Direction, - FlowTargetNew, + FlowTargetSourceDest, GetNetworkTopNFlowQuery, NetworkTopNFlowFields, } from '../../../../legacy/plugins/siem/public/graphql/types'; @@ -38,7 +38,7 @@ export default function({ getService }: FtrProviderContext) { to: TO, from: FROM, }, - flowTarget: FlowTargetNew.source, + flowTarget: FlowTargetSourceDest.source, sort: { field: NetworkTopNFlowFields.bytes_in, direction: Direction.desc }, pagination: { activePage: 0, @@ -75,7 +75,7 @@ export default function({ getService }: FtrProviderContext) { to: TO, from: FROM, }, - flowTarget: FlowTargetNew.source, + flowTarget: FlowTargetSourceDest.source, sort: { field: NetworkTopNFlowFields.bytes_in, direction: Direction.asc }, pagination: { activePage: 0, @@ -113,7 +113,7 @@ export default function({ getService }: FtrProviderContext) { from: FROM, }, sort: { field: NetworkTopNFlowFields.bytes_in, direction: Direction.desc }, - flowTarget: FlowTargetNew.destination, + flowTarget: FlowTargetSourceDest.destination, pagination: { activePage: 0, cursorStart: 0, @@ -147,7 +147,7 @@ export default function({ getService }: FtrProviderContext) { from: FROM, }, sort: { field: NetworkTopNFlowFields.bytes_in, direction: Direction.desc }, - flowTarget: FlowTargetNew.source, + flowTarget: FlowTargetSourceDest.source, pagination: { activePage: 1, cursorStart: 10,