diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/all/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/all/index.ts index 24fb5f1a95cd2e..974e892a7312fa 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/all/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/all/index.ts @@ -8,7 +8,7 @@ import { IEsSearchResponse } from '../../../../../../../../src/plugins/data/common'; import { HostItem, HostsFields } from '../common'; -import { CursorType, Inspect, Maybe, PageInfoPaginated } from '../../../common'; +import { CursorType, Direction, Inspect, Maybe, PageInfoPaginated } from '../../../common'; import { RequestOptionsPaginated } from '../..'; export interface HostsEdges { @@ -26,3 +26,9 @@ export interface HostsStrategyResponse extends IEsSearchResponse { export interface HostsRequestOptions extends RequestOptionsPaginated { defaultIndex: string[]; } + +export interface HostsSortField { + field: HostsFields; + + direction: Direction; +} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/common/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/common/index.ts index 11dc8ee2f6a825..a579d8f8d8ef3e 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/common/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/common/index.ts @@ -32,7 +32,7 @@ export interface HostItem { cloud?: Maybe; endpoint?: Maybe; host?: Maybe; - lastSeen?: Maybe; + lastSeen?: Maybe; } export interface HostValue { diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts index 485d41895a4a69..34b32115a089d8 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { estypes } from '@elastic/elasticsearch'; import { IEsSearchResponse } from '../../../../../../../../src/plugins/data/common'; import { Inspect, Maybe, TimerangeInput } from '../../../common'; @@ -22,3 +23,7 @@ export interface HostDetailsRequestOptions extends Partial; } + +export interface AggregationRequest { + [aggField: string]: estypes.AggregationContainer; +} diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/first_last_seen/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/first_last_seen/index.ts index b3e7b14aed000a..df95f859e3f37e 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/first_last_seen/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/first_last_seen/index.ts @@ -6,14 +6,14 @@ */ import { IEsSearchResponse } from '../../../../../../../../src/plugins/data/common'; -import { Inspect, Maybe } from '../../../common'; +import { Inspect, Maybe, Direction } from '../../../common'; import { RequestOptionsPaginated } from '../..'; import { HostsFields } from '../common'; export interface HostFirstLastSeenRequestOptions extends Partial> { hostName: string; - order: 'asc' | 'desc'; + order: Direction.asc | Direction.desc; } export interface HostFirstLastSeenStrategyResponse extends IEsSearchResponse { diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts index fa3029405dc225..3926fdc72f73a5 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/index.ts @@ -16,7 +16,7 @@ export * from './uncommon_processes'; export enum HostsQueries { authentications = 'authentications', - details = 'details', + details = 'hostDetails', firstOrLastSeen = 'firstOrLastSeen', hosts = 'hosts', overview = 'overviewHost', diff --git a/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.test.ts b/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.test.ts index 2a792c29fd37a3..a89d34e2fa43d3 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { HostItem } from '../../../../graphql/types'; +import { HostItem } from '../../../../../common/search_strategy/security_solution/hosts'; import { CriteriaFields } from '../types'; import { hostToCriteria } from './host_to_criteria'; @@ -28,6 +28,7 @@ describe('host_to_criteria', () => { test('returns an empty array if the host.name is null', () => { const hostItem: HostItem = { host: { + // @ts-expect-error name: null, }, }; diff --git a/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.ts b/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.ts index 57a05dc943fa36..19eae997578495 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/criteria/host_to_criteria.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { HostItem } from '../../../../../common/search_strategy/security_solution/hosts'; import { CriteriaFields } from '../types'; -import { HostItem } from '../../../../graphql/types'; export const hostToCriteria = (hostItem: HostItem): CriteriaFields[] => { if (hostItem.host != null && hostItem.host.name != null) { diff --git a/x-pack/plugins/security_solution/public/common/components/ml/influencers/host_to_influencers.ts b/x-pack/plugins/security_solution/public/common/components/ml/influencers/host_to_influencers.ts index 2f64c6e043d6b4..3a63958e2de12c 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/influencers/host_to_influencers.ts +++ b/x-pack/plugins/security_solution/public/common/components/ml/influencers/host_to_influencers.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { HostItem } from '../../../../../common/search_strategy/security_solution/hosts'; import { InfluencerInput } from '../types'; -import { HostItem } from '../../../../graphql/types'; export const hostToInfluencers = (hostItem: HostItem): InfluencerInput[] | null => { if (hostItem.host != null && hostItem.host.name != null) { diff --git a/x-pack/plugins/security_solution/public/graphql/introspection.json b/x-pack/plugins/security_solution/public/graphql/introspection.json index 1df8716ba76e42..0a41ca05b8753b 100644 --- a/x-pack/plugins/security_solution/public/graphql/introspection.json +++ b/x-pack/plugins/security_solution/public/graphql/introspection.json @@ -687,231 +687,6 @@ }, "isDeprecated": false, "deprecationReason": null - }, - { - "name": "Hosts", - "description": "Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "timerange", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "INPUT_OBJECT", "name": "TimerangeInput", "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": "HostsSortField", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "filterQuery", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "docValueFields", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "docValueFieldsInput", - "ofType": null - } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostsData", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "HostOverview", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "hostName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "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": "HostItem", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "HostFirstLastSeen", - "description": "", - "args": [ - { - "name": "id", - "description": "", - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "defaultValue": null - }, - { - "name": "hostName", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "defaultIndex", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "defaultValue": null - }, - { - "name": "docValueFields", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "docValueFieldsInput", - "ofType": null - } - } - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "FirstLastSeenHost", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null } ], "inputFields": null, @@ -1104,851 +879,7 @@ "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } } } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "TimerangeInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "interval", - "description": "The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "to", - "description": "The end of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "from", - "description": "The beginning of the timerange", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "PaginationInputPaginated", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "activePage", - "description": "The activePage parameter defines the page of results you want to fetch", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "cursorStart", - "description": "The cursorStart parameter defines the start of the results to be displayed", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "fakePossibleCount", - "description": "The fakePossibleCount parameter determines the total count in order to show 5 additional pages", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "querySize", - "description": "The querySize parameter is the number of items to be returned", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "HostsSortField", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "ENUM", "name": "HostsFields", "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": "HostsFields", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "hostName", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "docValueFieldsInput", - "description": "", - "fields": null, - "inputFields": [ - { - "name": "field", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - }, - { - "name": "format", - "description": "", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostsData", - "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": "HostsEdges", "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": "HostsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "HostItem", "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": "HostItem", - "description": "", - "fields": [ - { - "name": "_id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "agent", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "AgentFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cloud", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endpoint", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "EndpointFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "host", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "HostEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": 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": "AgentFields", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudFields", - "description": "", - "fields": [ - { - "name": "instance", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudInstance", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "machine", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "CloudMachine", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "provider", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "region", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudInstance", - "description": "", - "fields": [ - { - "name": "id", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CloudMachine", - "description": "", - "fields": [ - { - "name": "type", - "description": "", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "EndpointFields", - "description": "", - "fields": [ - { - "name": "endpointPolicy", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "sensorVersion", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "policyStatus", - "description": "", - "args": [], - "type": { "kind": "ENUM", "name": "HostPolicyResponseActionStatus", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "HostPolicyResponseActionStatus", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "success", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "failure", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "warning", - "description": "", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "unsupported", - "description": "", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "HostEcsFields", - "description": "", - "fields": [ - { - "name": "architecture", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mac", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "os", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "OsEcsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ToStringArray", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "OsEcsFields", - "description": "", - "fields": [ - { - "name": "platform", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "family", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kernel", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Inspect", - "description": "", - "fields": [ - { - "name": "dsl", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "response", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Date", - "description": "", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "CursorType", - "description": "", - "fields": [ - { - "name": "value", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "tiebreaker", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PageInfoPaginated", - "description": "", - "fields": [ - { - "name": "activePage", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fakeTotalCount", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "showMorePagesIndicator", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FirstLastSeenHost", - "description": "", - "fields": [ - { - "name": "inspect", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "Inspect", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "firstSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "lastSeen", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "Date", "ofType": null }, + }, "isDeprecated": false, "deprecationReason": null } @@ -1958,6 +889,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "Boolean", + "description": "The `Boolean` scalar type represents `true` or `false`.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "TimelineType", @@ -5045,6 +3986,16 @@ ], "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "ToStringArray", + "description": "", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "SCALAR", "name": "ToStringArrayNoNullable", @@ -5523,6 +4474,132 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "OsEcsFields", + "description": "", + "fields": [ + { + "name": "platform", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "full", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "family", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "version", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "kernel", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "HostEcsFields", + "description": "", + "fields": [ + { + "name": "architecture", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ip", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "mac", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "os", + "description": "", + "args": [], + "type": { "kind": "OBJECT", "name": "OsEcsFields", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "", + "args": [], + "type": { "kind": "SCALAR", "name": "ToStringArray", "ofType": null }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Thread", @@ -7900,146 +6977,57 @@ "possibleTypes": null }, { - "kind": "OBJECT", - "name": "EcsEdges", - "description": "", - "fields": [ - { - "name": "node", - "description": "", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { "kind": "OBJECT", "name": "ECS", "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": "OsFields", + "kind": "SCALAR", + "name": "Date", "description": "", - "fields": [ - { - "name": "platform", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "full", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "family", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "version", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "kernel", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - } - ], + "fields": null, "inputFields": null, - "interfaces": [], + "interfaces": null, "enumValues": null, "possibleTypes": null }, { "kind": "OBJECT", - "name": "HostFields", + "name": "EcsEdges", "description": "", "fields": [ { - "name": "architecture", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "id", - "description": "", - "args": [], - "type": { "kind": "SCALAR", "name": "String", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ip", + "name": "node", "description": "", "args": [], "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "ECS", "ofType": null } }, "isDeprecated": false, "deprecationReason": null }, { - "name": "mac", + "name": "cursor", "description": "", "args": [], "type": { - "kind": "LIST", + "kind": "NON_NULL", "name": null, - "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + "ofType": { "kind": "OBJECT", "name": "CursorType", "ofType": null } }, "isDeprecated": false, "deprecationReason": null - }, + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CursorType", + "description": "", + "fields": [ { - "name": "name", + "name": "value", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, @@ -8047,15 +7035,7 @@ "deprecationReason": null }, { - "name": "os", - "description": "", - "args": [], - "type": { "kind": "OBJECT", "name": "OsFields", "ofType": null }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", + "name": "tiebreaker", "description": "", "args": [], "type": { "kind": "SCALAR", "name": "String", "ofType": null }, @@ -8205,6 +7185,78 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "TimerangeInput", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "interval", + "description": "The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "to", + "description": "The end of the timerange", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "from", + "description": "The beginning of the timerange", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "docValueFieldsInput", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "field", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "format", + "description": "", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "PaginationInput", @@ -8238,6 +7290,57 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "PaginationInputPaginated", + "description": "", + "fields": null, + "inputFields": [ + { + "name": "activePage", + "description": "The activePage parameter defines the page of results you want to fetch", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "cursorStart", + "description": "The cursorStart parameter defines the start of the results to be displayed", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "fakePossibleCount", + "description": "The fakePossibleCount parameter determines the total count in order to show 5 additional pages", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "defaultValue": null + }, + { + "name": "querySize", + "description": "The querySize parameter is the number of items to be returned", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "FlowTarget", @@ -8357,6 +7460,104 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "Inspect", + "description": "", + "fields": [ + { + "name": "dsl", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "response", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PageInfoPaginated", + "description": "", + "fields": [ + { + "name": "activePage", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "fakeTotalCount", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Float", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "showMorePagesIndicator", + "description": "", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { "kind": "SCALAR", "name": "Boolean", "ofType": null } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "FavoriteTimelineInput", diff --git a/x-pack/plugins/security_solution/public/graphql/types.ts b/x-pack/plugins/security_solution/public/graphql/types.ts index 88c1ec4e6e3289..8ffd2995d0d978 100644 --- a/x-pack/plugins/security_solution/public/graphql/types.ts +++ b/x-pack/plugins/security_solution/public/graphql/types.ts @@ -21,38 +21,6 @@ export interface SortNote { sortOrder: Direction; } -export interface TimerangeInput { - /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ - interval: string; - /** The end of the timerange */ - to: string; - /** The beginning of the timerange */ - from: string; -} - -export interface PaginationInputPaginated { - /** The activePage parameter defines the page of results you want to fetch */ - activePage: number; - /** The cursorStart parameter defines the start of the results to be displayed */ - cursorStart: number; - /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ - fakePossibleCount: number; - /** The querySize parameter is the number of items to be returned */ - querySize: number; -} - -export interface HostsSortField { - field: HostsFields; - - direction: Direction; -} - -export interface DocValueFieldsInput { - field: string; - - format: string; -} - export interface PageInfoTimeline { pageIndex: number; @@ -245,6 +213,21 @@ export interface SortTimelineInput { sortDirection?: Maybe; } +export interface TimerangeInput { + /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ + interval: string; + /** The end of the timerange */ + to: string; + /** The beginning of the timerange */ + from: string; +} + +export interface DocValueFieldsInput { + field: string; + + format: string; +} + export interface PaginationInput { /** The limit parameter allows you to configure the maximum amount of items to be returned */ limit: number; @@ -254,6 +237,17 @@ export interface PaginationInput { tiebreaker?: Maybe; } +export interface PaginationInputPaginated { + /** The activePage parameter defines the page of results you want to fetch */ + activePage: number; + /** The cursorStart parameter defines the start of the results to be displayed */ + cursorStart: number; + /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ + fakePossibleCount: number; + /** The querySize parameter is the number of items to be returned */ + querySize: number; +} + export interface SortField { sortFieldId: string; @@ -278,18 +272,6 @@ export enum Direction { desc = 'desc', } -export enum HostsFields { - hostName = 'hostName', - lastSeen = 'lastSeen', -} - -export enum HostPolicyResponseActionStatus { - success = 'success', - failure = 'failure', - warning = 'warning', - unsupported = 'unsupported', -} - export enum TimelineType { default = 'default', template = 'template', @@ -349,12 +331,10 @@ export enum FlowDirection { biDirectional = 'biDirectional', } -export type ToStringArray = string[]; - -export type Date = string; - export type ToAny = any; +export type ToStringArray = string[]; + export type ToStringArrayNoNullable = any; export type ToDateArray = string[]; @@ -363,6 +343,8 @@ export type ToNumberArray = number[]; export type ToBooleanArray = boolean[]; +export type Date = string; + export type ToIFieldSubTypeNonNullable = any; // ==================================================== @@ -452,12 +434,6 @@ export interface Source { configuration: SourceConfiguration; /** The status of the source */ status: SourceStatus; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts: HostsData; - - HostOverview: HostItem; - - HostFirstLastSeen: FirstLastSeenHost; } /** A set of configuration options for a security data source */ @@ -490,126 +466,6 @@ export interface SourceStatus { indexFields: string[]; } -export interface HostsData { - edges: HostsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface HostsEdges { - node: HostItem; - - cursor: CursorType; -} - -export interface HostItem { - _id?: Maybe; - - agent?: Maybe; - - cloud?: Maybe; - - endpoint?: Maybe; - - host?: Maybe; - - inspect?: Maybe; - - lastSeen?: Maybe; -} - -export interface AgentFields { - id?: Maybe; -} - -export interface CloudFields { - instance?: Maybe; - - machine?: Maybe; - - provider?: Maybe<(Maybe)[]>; - - region?: Maybe<(Maybe)[]>; -} - -export interface CloudInstance { - id?: Maybe<(Maybe)[]>; -} - -export interface CloudMachine { - type?: Maybe<(Maybe)[]>; -} - -export interface EndpointFields { - endpointPolicy?: Maybe; - - sensorVersion?: Maybe; - - policyStatus?: Maybe; -} - -export interface HostEcsFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe; - - mac?: Maybe; - - name?: Maybe; - - os?: Maybe; - - type?: Maybe; -} - -export interface OsEcsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface Inspect { - dsl: string[]; - - response: string[]; -} - -export interface CursorType { - value?: Maybe; - - tiebreaker?: Maybe; -} - -export interface PageInfoPaginated { - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; -} - -export interface FirstLastSeenHost { - inspect?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - export interface TimelineResult { columns?: Maybe; @@ -985,6 +841,36 @@ export interface AuditdEcsFields { sequence?: Maybe; } +export interface OsEcsFields { + platform?: Maybe; + + name?: Maybe; + + full?: Maybe; + + family?: Maybe; + + version?: Maybe; + + kernel?: Maybe; +} + +export interface HostEcsFields { + architecture?: Maybe; + + id?: Maybe; + + ip?: Maybe; + + mac?: Maybe; + + name?: Maybe; + + os?: Maybe; + + type?: Maybe; +} + export interface Thread { id?: Maybe; @@ -1547,34 +1433,10 @@ export interface EcsEdges { cursor: CursorType; } -export interface OsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface HostFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe<(Maybe)[]>; - - mac?: Maybe<(Maybe)[]>; - - name?: Maybe; - - os?: Maybe; +export interface CursorType { + value?: Maybe; - type?: Maybe; + tiebreaker?: Maybe; } /** A descriptor of a field in an index */ @@ -1609,6 +1471,20 @@ export interface PageInfo { hasNextPage?: Maybe; } +export interface Inspect { + dsl: string[]; + + response: string[]; +} + +export interface PageInfoPaginated { + activePage: number; + + fakeTotalCount: number; + + showMorePagesIndicator: boolean; +} + // ==================================================== // Arguments // ==================================================== @@ -1654,39 +1530,6 @@ export interface GetAllTimelineQueryArgs { status?: Maybe; } -export interface HostsSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - sort: HostsSortField; - - filterQuery?: Maybe; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} -export interface HostOverviewSourceArgs { - id?: Maybe; - - hostName: string; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface HostFirstLastSeenSourceArgs { - id?: Maybe; - - hostName: string; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} export interface IndicesExistSourceStatusArgs { defaultIndex: string[]; } @@ -1745,254 +1588,6 @@ export interface DeleteTimelineMutationArgs { // Documents // ==================================================== -export namespace GetHostOverviewQuery { - export type Variables = { - sourceId: string; - hostName: string; - timerange: TimerangeInput; - defaultIndex: string[]; - inspect: boolean; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - HostOverview: HostOverview; - }; - - export type HostOverview = { - __typename?: 'HostItem'; - - _id: Maybe; - - agent: Maybe; - - host: Maybe; - - cloud: Maybe; - - inspect: Maybe; - - endpoint: Maybe; - }; - - export type Agent = { - __typename?: 'AgentFields'; - - id: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - architecture: Maybe; - - id: Maybe; - - ip: Maybe; - - mac: Maybe; - - name: Maybe; - - os: Maybe; - - type: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - family: Maybe; - - name: Maybe; - - platform: Maybe; - - version: Maybe; - }; - - export type Cloud = { - __typename?: 'CloudFields'; - - instance: Maybe; - - machine: Maybe; - - provider: Maybe<(Maybe)[]>; - - region: Maybe<(Maybe)[]>; - }; - - export type Instance = { - __typename?: 'CloudInstance'; - - id: Maybe<(Maybe)[]>; - }; - - export type Machine = { - __typename?: 'CloudMachine'; - - type: Maybe<(Maybe)[]>; - }; - - export type Inspect = { - __typename?: 'Inspect'; - - dsl: string[]; - - response: string[]; - }; - - export type Endpoint = { - __typename?: 'EndpointFields'; - - endpointPolicy: Maybe; - - policyStatus: Maybe; - - sensorVersion: Maybe; - }; -} - -export namespace GetHostFirstLastSeenQuery { - export type Variables = { - sourceId: string; - hostName: string; - defaultIndex: string[]; - docValueFields: DocValueFieldsInput[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - HostFirstLastSeen: HostFirstLastSeen; - }; - - export type HostFirstLastSeen = { - __typename?: 'FirstLastSeenHost'; - - firstSeen: Maybe; - - lastSeen: Maybe; - }; -} - -export namespace GetHostsTableQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInputPaginated; - sort: HostsSortField; - filterQuery?: Maybe; - defaultIndex: string[]; - inspect: boolean; - docValueFields: DocValueFieldsInput[]; - }; - - export type Query = { - __typename?: 'Query'; - - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - - id: string; - - Hosts: Hosts; - }; - - export type Hosts = { - __typename?: 'HostsData'; - - totalCount: number; - - edges: Edges[]; - - pageInfo: PageInfo; - - inspect: Maybe; - }; - - export type Edges = { - __typename?: 'HostsEdges'; - - node: Node; - - cursor: Cursor; - }; - - export type Node = { - __typename?: 'HostItem'; - - _id: Maybe; - - lastSeen: Maybe; - - host: Maybe; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - - id: Maybe; - - name: Maybe; - - os: Maybe; - }; - - export type Os = { - __typename?: 'OsEcsFields'; - - name: Maybe; - - version: 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 GetAllTimeline { export type Variables = { pageInfo: PageInfoTimeline; diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap index 1d70f4f72ac8bd..59a00cbf190f68 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/__snapshots__/index.test.tsx.snap @@ -6,73 +6,38 @@ exports[`Hosts Table rendering it renders the default Hosts table 1`] = ` Array [ Object { "cursor": Object { - "value": "98966fa2013c396155c460d35c0902be", + "tiebreaker": null, + "value": "beats-ci-immutable-ubuntu-1804-1615475026535098510", }, "node": Object { - "_id": "cPsuhGcB0WOhS6qyTKC0", + "_id": "beats-ci-immutable-ubuntu-1804-1615475026535098510", "host": Object { "name": Array [ - "elrond.elstc.co", + "beats-ci-immutable-ubuntu-1804-1615475026535098510", ], "os": Object { "name": Array [ "Ubuntu", ], "version": Array [ - "18.04.1 LTS (Bionic Beaver)", - ], - }, - }, - }, - }, - Object { - "cursor": Object { - "value": "aa7ca589f1b8220002f2fc61c64cfbf1", - }, - "node": Object { - "_id": "KwQDiWcB0WOhS6qyXmrW", - "cloud": Object { - "instance": Object { - "id": Array [ - "423232333829362673777", - ], - }, - "machine": Object { - "type": Array [ - "custom-4-16384", - ], - }, - "provider": Array [ - "gce", - ], - "region": Array [ - "us-east-1", - ], - }, - "host": Object { - "name": Array [ - "siem-kibana", - ], - "os": Object { - "name": Array [ - "Debian GNU/Linux", - ], - "version": Array [ - "9 (stretch)", + "18.04.5 LTS (Bionic Beaver)", ], }, }, + "lastSeen": Array [ + "2021-03-11T15:05:36.783Z", + ], }, }, ] } - fakeTotalCount={50} + fakeTotalCount={0} id="hostsQuery" isInspect={false} loadPage={[MockFunction]} loading={false} - showMorePagesIndicator={true} - totalCount={4} + showMorePagesIndicator={false} + totalCount={-1} type="page" /> `; diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx index 6f43a18431a275..d6c51b2bfe05e9 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/columns.tsx @@ -78,7 +78,7 @@ export const getHostsColumns = (): HostsTableColumns => [ hideForMobile: false, sortable: true, render: (lastSeen: Maybe | undefined) => { - if (lastSeen != null) { + if (lastSeen != null && lastSeen.length > 0) { return ( { const wrapper = shallow( @@ -93,14 +92,10 @@ describe('Hosts Table', () => { id="hostsQuery" isInspect={false} loading={false} - data={mockData.Hosts.edges} - totalCount={mockData.Hosts.totalCount} - fakeTotalCount={getOr(50, 'fakeTotalCount', mockData.Hosts.pageInfo)} - showMorePagesIndicator={getOr( - false, - 'showMorePagesIndicator', - mockData.Hosts.pageInfo - )} + data={mockData} + totalCount={0} + fakeTotalCount={-1} + showMorePagesIndicator={false} loadPage={loadPage} type={hostsModel.HostsType.page} /> diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.tsx index 75bf524ab1e866..d20333d2105596 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/index.tsx @@ -9,15 +9,6 @@ import React, { useMemo, useCallback } from 'react'; import { useDispatch } from 'react-redux'; import { assertUnreachable } from '../../../../common/utility_types'; -import { - Direction, - HostFields, - HostItem, - HostsEdges, - HostsFields, - HostsSortField, - OsFields, -} from '../../../graphql/types'; import { Columns, Criteria, @@ -29,6 +20,14 @@ import { useDeepEqualSelector } from '../../../common/hooks/use_selector'; import { hostsActions, hostsModel, hostsSelectors } from '../../store'; import { getHostsColumns } from './columns'; import * as i18n from './translations'; +import { + HostsEdges, + HostItem, + HostsSortField, + HostsFields, +} from '../../../../common/search_strategy/security_solution/hosts'; +import { Direction } from '../../../../common/search_strategy'; +import { HostEcs, OsEcs } from '../../../../common/ecs/host'; const tableType = hostsModel.HostsTableType.hosts; @@ -45,10 +44,10 @@ interface HostsTableProps { } export type HostsTableColumns = [ - Columns, + Columns, Columns, - Columns, - Columns + Columns, + Columns ]; const rowItems: ItemsPerRow[] = [ @@ -82,7 +81,6 @@ const HostsTableComponent: React.FC = ({ const { activePage, direction, limit, sortField } = useDeepEqualSelector((state) => getHostsSelector(state, type) ); - const updateLimitPagination = useCallback( (newLimit) => dispatch( @@ -178,6 +176,7 @@ const getNodeField = (field: HostsFields): string => { } assertUnreachable(field); }; + export const HostsTable = React.memo(HostsTableComponent); HostsTable.displayName = 'HostsTable'; diff --git a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/mock.ts b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/mock.ts index 9c5d7bb152d918..525d5ce3681471 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/hosts_table/mock.ts +++ b/x-pack/plugins/security_solution/public/hosts/components/hosts_table/mock.ts @@ -5,57 +5,18 @@ * 2.0. */ -import { HostsData } from '../../../graphql/types'; +import { HostsEdges } from '../../../../common/search_strategy/security_solution/hosts'; -export const mockData: { Hosts: HostsData } = { - Hosts: { - totalCount: 4, - edges: [ - { - node: { - _id: 'cPsuhGcB0WOhS6qyTKC0', - host: { - name: ['elrond.elstc.co'], - os: { - name: ['Ubuntu'], - version: ['18.04.1 LTS (Bionic Beaver)'], - }, - }, - }, - cursor: { - value: '98966fa2013c396155c460d35c0902be', - }, +export const mockData: HostsEdges[] = [ + { + node: { + _id: 'beats-ci-immutable-ubuntu-1804-1615475026535098510', + lastSeen: ['2021-03-11T15:05:36.783Z'], + host: { + name: ['beats-ci-immutable-ubuntu-1804-1615475026535098510'], + os: { name: ['Ubuntu'], version: ['18.04.5 LTS (Bionic Beaver)'] }, }, - { - node: { - _id: 'KwQDiWcB0WOhS6qyXmrW', - host: { - name: ['siem-kibana'], - os: { - name: ['Debian GNU/Linux'], - version: ['9 (stretch)'], - }, - }, - cloud: { - instance: { - id: ['423232333829362673777'], - }, - machine: { - type: ['custom-4-16384'], - }, - provider: ['gce'], - region: ['us-east-1'], - }, - }, - cursor: { - value: 'aa7ca589f1b8220002f2fc61c64cfbf1', - }, - }, - ], - pageInfo: { - activePage: 1, - fakeTotalCount: 50, - showMorePagesIndicator: true, }, + cursor: { value: 'beats-ci-immutable-ubuntu-1804-1615475026535098510', tiebreaker: null }, }, -}; +]; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx deleted file mode 100644 index 532b9f262e136a..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/_index.tsx +++ /dev/null @@ -1,161 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -// REPLACE WHEN HOST ENDPOINT DATA IS AVAILABLE - -import deepEqual from 'fast-deep-equal'; -import { noop } from 'lodash/fp'; -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Subscription } from 'rxjs'; - -import { inputsModel } from '../../../../common/store'; -import { useKibana } from '../../../../common/lib/kibana'; -import { - HostItem, - HostsQueries, - HostDetailsRequestOptions, - HostDetailsStrategyResponse, -} from '../../../../../common/search_strategy/security_solution/hosts'; - -import * as i18n from './translations'; -import { - isCompleteResponse, - isErrorResponse, -} from '../../../../../../../../src/plugins/data/common'; -import { getInspectResponse } from '../../../../helpers'; -import { InspectResponse } from '../../../../types'; - -const ID = 'hostsDetailsQuery'; - -export interface HostDetailsArgs { - id: string; - inspect: InspectResponse; - hostDetails: HostItem; - refetch: inputsModel.Refetch; - startDate: string; - endDate: string; -} - -interface UseHostDetails { - endDate: string; - hostName: string; - id?: string; - indexNames: string[]; - skip?: boolean; - startDate: string; -} - -export const useHostDetails = ({ - endDate, - hostName, - indexNames, - id = ID, - skip = false, - startDate, -}: UseHostDetails): [boolean, HostDetailsArgs] => { - const { data, notifications } = useKibana().services; - const refetch = useRef(noop); - const abortCtrl = useRef(new AbortController()); - const searchSubscription$ = useRef(new Subscription()); - const [loading, setLoading] = useState(false); - const [hostDetailsRequest, setHostDetailsRequest] = useState( - null - ); - - const [hostDetailsResponse, setHostDetailsResponse] = useState({ - endDate, - hostDetails: {}, - id, - inspect: { - dsl: [], - response: [], - }, - refetch: refetch.current, - startDate, - }); - - const hostDetailsSearch = useCallback( - (request: HostDetailsRequestOptions | null) => { - if (request == null || skip) { - return; - } - - const asyncSearch = async () => { - abortCtrl.current = new AbortController(); - setLoading(true); - - searchSubscription$.current = data.search - .search(request, { - strategy: 'securitySolutionSearchStrategy', - abortSignal: abortCtrl.current.signal, - }) - .subscribe({ - next: (response) => { - if (isCompleteResponse(response)) { - setLoading(false); - setHostDetailsResponse((prevResponse) => ({ - ...prevResponse, - hostDetails: response.hostDetails, - inspect: getInspectResponse(response, prevResponse.inspect), - refetch: refetch.current, - })); - searchSubscription$.current.unsubscribe(); - } else if (isErrorResponse(response)) { - setLoading(false); - // TODO: Make response error status clearer - notifications.toasts.addWarning(i18n.ERROR_HOST_OVERVIEW); - searchSubscription$.current.unsubscribe(); - } - }, - error: (msg) => { - setLoading(false); - notifications.toasts.addDanger({ - title: i18n.FAIL_HOST_OVERVIEW, - text: msg.message, - }); - searchSubscription$.current.unsubscribe(); - }, - }); - }; - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - asyncSearch(); - refetch.current = asyncSearch; - }, - [data.search, notifications.toasts, skip] - ); - - useEffect(() => { - setHostDetailsRequest((prevRequest) => { - const myRequest = { - ...(prevRequest ?? {}), - defaultIndex: indexNames, - factoryQueryType: HostsQueries.details, - hostName, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - }; - if (!deepEqual(prevRequest, myRequest)) { - return myRequest; - } - return prevRequest; - }); - return () => { - searchSubscription$.current.unsubscribe(); - abortCtrl.current.abort(); - }; - }, [endDate, hostName, indexNames, startDate]); - - useEffect(() => { - hostDetailsSearch(hostDetailsRequest); - }, [hostDetailsRequest, hostDetailsSearch]); - - return [loading, hostDetailsResponse]; -}; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/host_overview.gql_query.ts b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/host_overview.gql_query.ts deleted file mode 100644 index 70c07bc55fd23a..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/host_overview.gql_query.ts +++ /dev/null @@ -1,61 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import gql from 'graphql-tag'; - -export const HostOverviewQuery = gql` - query GetHostOverviewQuery( - $sourceId: ID! - $hostName: String! - $timerange: TimerangeInput! - $defaultIndex: [String!]! - $inspect: Boolean! - ) { - source(id: $sourceId) { - id - HostOverview(hostName: $hostName, timerange: $timerange, defaultIndex: $defaultIndex) { - _id - agent { - id - } - host { - architecture - id - ip - mac - name - os { - family - name - platform - version - } - type - } - cloud { - instance { - id - } - machine { - type - } - provider - region - } - inspect @include(if: $inspect) { - dsl - response - } - endpoint { - endpointPolicy - policyStatus - sensorVersion - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx index 26b4c0e55e56a7..1eaa89575de260 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/details/index.tsx @@ -5,107 +5,155 @@ * 2.0. */ -import { getOr } from 'lodash/fp'; -import React from 'react'; -import { Query } from 'react-apollo'; -import { connect } from 'react-redux'; -import { compose } from 'redux'; +import deepEqual from 'fast-deep-equal'; +import { noop } from 'lodash/fp'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { Subscription } from 'rxjs'; -import { inputsModel, inputsSelectors, State } from '../../../../common/store'; -import { getDefaultFetchPolicy } from '../../../../common/containers/helpers'; -import { QueryTemplate, QueryTemplateProps } from '../../../../common/containers/query_template'; +import { inputsModel } from '../../../../common/store'; +import { useKibana } from '../../../../common/lib/kibana'; +import { + HostItem, + HostsQueries, + HostDetailsRequestOptions, + HostDetailsStrategyResponse, +} from '../../../../../common/search_strategy/security_solution/hosts'; -import { HostOverviewQuery } from './host_overview.gql_query'; -import { GetHostOverviewQuery, HostItem } from '../../../../graphql/types'; +import * as i18n from './translations'; +import { + isCompleteResponse, + isErrorResponse, +} from '../../../../../../../../src/plugins/data/common'; +import { getInspectResponse } from '../../../../helpers'; +import { InspectResponse } from '../../../../types'; -const ID = 'hostOverviewQuery'; +export const ID = 'hostsDetailsQuery'; -export interface HostOverviewArgs { +export interface HostDetailsArgs { id: string; - inspect: inputsModel.InspectQuery; - hostOverview: HostItem; - loading: boolean; + inspect: InspectResponse; + hostDetails: HostItem; refetch: inputsModel.Refetch; startDate: string; endDate: string; } -export interface HostOverviewReduxProps { - isInspected: boolean; -} - -export interface OwnProps extends QueryTemplateProps { - children: (args: HostOverviewArgs) => React.ReactNode; +interface UseHostDetails { + endDate: string; hostName: string; + id?: string; + indexNames: string[]; + skip?: boolean; startDate: string; - endDate: string; } -type HostsOverViewProps = OwnProps & HostOverviewReduxProps; +export const useHostDetails = ({ + endDate, + hostName, + indexNames, + id = ID, + skip = false, + startDate, +}: UseHostDetails): [boolean, HostDetailsArgs] => { + const { data, notifications } = useKibana().services; + const refetch = useRef(noop); + const abortCtrl = useRef(new AbortController()); + const searchSubscription$ = useRef(new Subscription()); + const [loading, setLoading] = useState(false); + const [hostDetailsRequest, setHostDetailsRequest] = useState( + null + ); + + const [hostDetailsResponse, setHostDetailsResponse] = useState({ + endDate, + hostDetails: {}, + id, + inspect: { + dsl: [], + response: [], + }, + refetch: refetch.current, + startDate, + }); + + const hostDetailsSearch = useCallback( + (request: HostDetailsRequestOptions | null) => { + if (request == null || skip) { + return; + } -class HostOverviewByNameComponentQuery extends QueryTemplate< - HostsOverViewProps, - GetHostOverviewQuery.Query, - GetHostOverviewQuery.Variables -> { - public render() { - const { - id = ID, - indexNames, - isInspected, - children, - hostName, - skip, - sourceId, - startDate, - endDate, - } = this.props; - return ( - - query={HostOverviewQuery} - fetchPolicy={getDefaultFetchPolicy()} - notifyOnNetworkStatusChange - skip={skip} - variables={{ - sourceId, - hostName, - timerange: { - interval: '12h', - from: startDate, - to: endDate, - }, - defaultIndex: indexNames, - inspect: isInspected, - }} - > - {({ data, loading, refetch }) => { - const hostOverview = getOr([], 'source.HostOverview', data); - return children({ - id, - inspect: getOr(null, 'source.HostOverview.inspect', data), - refetch, - loading, - hostOverview, - startDate, - endDate, + const asyncSearch = async () => { + abortCtrl.current = new AbortController(); + setLoading(true); + + searchSubscription$.current = data.search + .search(request, { + strategy: 'securitySolutionSearchStrategy', + abortSignal: abortCtrl.current.signal, + }) + .subscribe({ + next: (response) => { + if (isCompleteResponse(response)) { + setLoading(false); + setHostDetailsResponse((prevResponse) => ({ + ...prevResponse, + hostDetails: response.hostDetails, + inspect: getInspectResponse(response, prevResponse.inspect), + refetch: refetch.current, + })); + searchSubscription$.current.unsubscribe(); + } else if (isErrorResponse(response)) { + setLoading(false); + // TODO: Make response error status clearer + notifications.toasts.addWarning(i18n.ERROR_HOST_OVERVIEW); + searchSubscription$.current.unsubscribe(); + } + }, + error: (msg) => { + setLoading(false); + notifications.toasts.addDanger({ + title: i18n.FAIL_HOST_OVERVIEW, + text: msg.message, + }); + searchSubscription$.current.unsubscribe(); + }, }); - }} - - ); - } -} + }; + searchSubscription$.current.unsubscribe(); + abortCtrl.current.abort(); + asyncSearch(); + refetch.current = asyncSearch; + }, + [data.search, notifications.toasts, skip] + ); -const makeMapStateToProps = () => { - const getQuery = inputsSelectors.globalQueryByIdSelector(); - const mapStateToProps = (state: State, { id = ID }: OwnProps) => { - const { isInspected } = getQuery(state, id); - return { - isInspected, + useEffect(() => { + setHostDetailsRequest((prevRequest) => { + const myRequest = { + ...(prevRequest ?? {}), + defaultIndex: indexNames, + factoryQueryType: HostsQueries.details, + hostName, + timerange: { + interval: '12h', + from: startDate, + to: endDate, + }, + }; + if (!deepEqual(prevRequest, myRequest)) { + return myRequest; + } + return prevRequest; + }); + return () => { + searchSubscription$.current.unsubscribe(); + abortCtrl.current.abort(); }; - }; - return mapStateToProps; -}; + }, [endDate, hostName, indexNames, startDate]); -export const HostOverviewByNameQuery = compose>( - connect(makeMapStateToProps) -)(HostOverviewByNameComponentQuery); + useEffect(() => { + hostDetailsSearch(hostDetailsRequest); + }, [hostDetailsRequest, hostDetailsSearch]); + + return [loading, hostDetailsResponse]; +}; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/first_last_seen.gql_query.ts b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/first_last_seen.gql_query.ts deleted file mode 100644 index 789a1d4ff5a82d..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/first_last_seen.gql_query.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import gql from 'graphql-tag'; - -export const HostFirstLastSeenGqlQuery = gql` - query GetHostFirstLastSeenQuery( - $sourceId: ID! - $hostName: String! - $defaultIndex: [String!]! - $docValueFields: [docValueFieldsInput!]! - ) { - source(id: $sourceId) { - id - HostFirstLastSeen( - hostName: $hostName - defaultIndex: $defaultIndex - docValueFields: $docValueFields - ) { - firstSeen - lastSeen - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx index bd49d6be34e5cd..380e6b05471a89 100644 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/containers/hosts/first_last_seen/index.tsx @@ -17,7 +17,7 @@ import { } from '../../../../../common/search_strategy/security_solution'; import * as i18n from './translations'; -import { DocValueFields } from '../../../../../common/search_strategy'; +import { Direction, DocValueFields } from '../../../../../common/search_strategy'; import { isCompleteResponse, isErrorResponse, @@ -30,13 +30,13 @@ export interface FirstLastSeenHostArgs { errorMessage: string | null; firstSeen?: string | null; lastSeen?: string | null; - order: 'asc' | 'desc' | null; + order: Direction.asc | Direction.desc | null; } interface UseHostFirstLastSeen { docValueFields: DocValueFields[]; hostName: string; indexNames: string[]; - order: 'asc' | 'desc'; + order: Direction.asc | Direction.desc; } export const useFirstLastSeenHost = ({ diff --git a/x-pack/plugins/security_solution/public/hosts/containers/hosts/hosts_table.gql_query.ts b/x-pack/plugins/security_solution/public/hosts/containers/hosts/hosts_table.gql_query.ts deleted file mode 100644 index 35fba31eeaa583..00000000000000 --- a/x-pack/plugins/security_solution/public/hosts/containers/hosts/hosts_table.gql_query.ts +++ /dev/null @@ -1,61 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import gql from 'graphql-tag'; - -export const HostsTableQuery = gql` - query GetHostsTableQuery( - $sourceId: ID! - $timerange: TimerangeInput! - $pagination: PaginationInputPaginated! - $sort: HostsSortField! - $filterQuery: String - $defaultIndex: [String!]! - $inspect: Boolean! - $docValueFields: [docValueFieldsInput!]! - ) { - source(id: $sourceId) { - id - Hosts( - timerange: $timerange - pagination: $pagination - sort: $sort - filterQuery: $filterQuery - defaultIndex: $defaultIndex - docValueFields: $docValueFields - ) { - totalCount - edges { - node { - _id - lastSeen - host { - id - name - os { - name - version - } - } - } - cursor { - value - } - } - pageInfo { - activePage - fakeTotalCount - showMorePagesIndicator - } - inspect @include(if: $inspect) { - dsl - response - } - } - } - } -`; diff --git a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx index faa240f98e53e9..1ff4abb78b210a 100644 --- a/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/pages/details/index.tsx @@ -24,10 +24,8 @@ import { scoreIntervalToDateTime } from '../../../common/components/ml/score/sco import { SiemNavigation } from '../../../common/components/navigation'; import { HostsDetailsKpiComponent } from '../../components/kpi_hosts'; import { HostOverview } from '../../../overview/components/host_overview'; -import { manageQuery } from '../../../common/components/page/manage_query'; import { SiemSearchBar } from '../../../common/components/search_bar'; import { WrapperPage } from '../../../common/components/wrapper_page'; -import { HostOverviewByNameQuery } from '../../containers/hosts/details'; import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useKibana } from '../../../common/lib/kibana'; import { convertToBuildEsQuery } from '../../../common/lib/keury'; @@ -51,8 +49,7 @@ import { TimelineId } from '../../../../common/types/timeline'; import { timelineDefaults } from '../../../timelines/store/timeline/defaults'; import { useSourcererScope } from '../../../common/containers/sourcerer'; import { useDeepEqualSelector, useShallowEqualSelector } from '../../../common/hooks/use_selector'; - -const HostOverviewManage = manageQuery(HostOverview); +import { useHostDetails } from '../../containers/hosts/details'; const HostDetailsComponent: React.FC = ({ detailName, hostDetailsPagePath }) => { const dispatch = useDispatch(); @@ -96,6 +93,12 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta ); const { docValueFields, indicesExist, indexPattern, selectedPatterns } = useSourcererScope(); + const [loading, { hostDetails: hostOverview, id }] = useHostDetails({ + endDate: to, + startDate: from, + hostName: detailName, + indexNames: selectedPatterns, + }); const filterQuery = convertToBuildEsQuery({ config: esQuery.getEsQueryConfig(kibana.services.uiSettings), indexPattern, @@ -131,49 +134,35 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta title={detailName} /> - - {({ hostOverview, loading, id, inspect, refetch }) => ( - ( + - {({ isLoadingAnomaliesData, anomaliesData }) => ( - { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }} - /> - )} - + narrowDateRange={(score, interval) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }} + /> )} - + diff --git a/x-pack/plugins/security_solution/public/hosts/store/actions.ts b/x-pack/plugins/security_solution/public/hosts/store/actions.ts index 0416a00be78b6d..ab4033ebe7f5ac 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/actions.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/actions.ts @@ -6,8 +6,7 @@ */ import actionCreatorFactory from 'typescript-fsa'; - -import { HostsSortField } from '../../graphql/types'; +import { HostsSortField } from '../../../common/search_strategy/security_solution/hosts'; import { HostsTableType, HostsType } from './model'; const actionCreator = actionCreatorFactory('x-pack/security_solution/local/hosts'); diff --git a/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts b/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts index 320df452af5699..c9dcc3a60b4a93 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/helpers.test.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { Direction, HostsFields } from '../../graphql/types'; import { DEFAULT_TABLE_LIMIT } from '../../common/store/constants'; import { HostsModel, HostsTableType, HostsType } from './model'; import { setHostsQueriesActivePageToZero } from './helpers'; +import { Direction, HostsFields } from '../../../common/search_strategy'; export const mockHostsState: HostsModel = { page: { diff --git a/x-pack/plugins/security_solution/public/hosts/store/model.ts b/x-pack/plugins/security_solution/public/hosts/store/model.ts index 4c3f90879d5e57..b610971f703058 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/model.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/model.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { Direction, HostsFields } from '../../graphql/types'; +import { HostsFields } from '../../../common/search_strategy/security_solution/hosts'; +import { Direction } from '../../graphql/types'; export enum HostsType { page = 'page', diff --git a/x-pack/plugins/security_solution/public/hosts/store/reducer.ts b/x-pack/plugins/security_solution/public/hosts/store/reducer.ts index d35117e3533c98..eebf3ca1684a1d 100644 --- a/x-pack/plugins/security_solution/public/hosts/store/reducer.ts +++ b/x-pack/plugins/security_solution/public/hosts/store/reducer.ts @@ -6,8 +6,8 @@ */ import { reducerWithInitialState } from 'typescript-fsa-reducers'; +import { Direction, HostsFields } from '../../../common/search_strategy'; -import { Direction, HostsFields } from '../../graphql/types'; import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from '../../common/store/constants'; import { diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.test.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.test.tsx index 9c970876661981..b43d5af029ec47 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.test.tsx @@ -13,7 +13,7 @@ import '../../../../common/mock/react_beautiful_dnd'; import { TestProviders } from '../../../../common/mock'; import { EndpointOverview } from './index'; -import { HostPolicyResponseActionStatus } from '../../../../graphql/types'; +import { HostPolicyResponseActionStatus } from '../../../../../common/search_strategy/security_solution/hosts'; describe('EndpointOverview Component', () => { test('it renders with endpoint data', () => { diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx index 4caf854278cc2e..1b05b600c8e3ea 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx @@ -13,9 +13,11 @@ import { OverviewDescriptionList } from '../../../../common/components/overview_ import { DescriptionList } from '../../../../../common/utility_types'; import { getEmptyTagValue } from '../../../../common/components/empty_value'; import { DefaultFieldRenderer } from '../../../../timelines/components/field_renderers/field_renderers'; -import { EndpointFields, HostPolicyResponseActionStatus } from '../../../../graphql/types'; - import * as i18n from './translations'; +import { + EndpointFields, + HostPolicyResponseActionStatus, +} from '../../../../../common/search_strategy/security_solution/hosts'; interface Props { contextID?: string; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/__snapshots__/expandable_host.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/__snapshots__/expandable_host.test.tsx.snap index e42b5263189dc3..84611e0b7f02c4 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/__snapshots__/expandable_host.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/__snapshots__/expandable_host.test.tsx.snap @@ -1,669 +1,1067 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Expandable Host Component ExpandableHostDetails: rendering it should render the HostOverview of the ExpandableHostDetails 1`] = ` +.c3 { + color: #535966; +} + +.c0 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-flex: 1; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} + +.c0 > * { + max-width: 100%; +} + +.c0 .inspectButtonComponent { + pointer-events: none; + opacity: 0; + -webkit-transition: opacity 250ms ease; + transition: opacity 250ms ease; +} + +.c0:hover .inspectButtonComponent { + pointer-events: auto; + opacity: 1; +} + +.c4 { + padding: 16px; + background: rgba(250,251,253,0.9); + bottom: 0; + left: 0; + position: absolute; + right: 0; + top: 0; + z-index: 1000; +} + +.c5 { + height: 100%; +} + +.c2 dt { + font-size: 12px !important; +} + +.c2 dd { + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} + +.c2 dd > div { + width: -webkit-fit-content; + width: -moz-fit-content; + width: fit-content; +} + +.c1 { + position: relative; +} + +.c1 .euiButtonIcon { + position: absolute; + right: 12px; + top: 6px; + z-index: 2; +} + - - - +
+ + +
+ + — + , + "title": "Host ID", }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "id", + Object { + "description": + — + , + "title": "First seen", + }, + Object { + "description": + — + , + "title": "Last seen", + }, + ] + } + key="0" + > + +
+ + — + , + "title": "Host ID", }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [ + Object { + "description": + — + , + "title": "First seen", + }, + Object { + "description": + — + , + "title": "Last seen", + }, + ] + } + > + + — + , + "title": "Host ID", }, Object { - "kind": "Argument", - "name": Object { - "kind": "Name", - "value": "timerange", - }, - "value": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "timerange", - }, - }, + "description": + — + , + "title": "First seen", }, Object { - "kind": "Argument", - "name": Object { - "kind": "Name", - "value": "defaultIndex", - }, - "value": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "defaultIndex", - }, - }, + "description": + — + , + "title": "Last seen", }, - ], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "HostOverview", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "_id", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "agent", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "id", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "host", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "architecture", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "id", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "ip", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "mac", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "name", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "os", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "family", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "name", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "platform", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "version", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "type", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "cloud", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "instance", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "id", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "machine", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "type", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "provider", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "region", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [ - Object { - "arguments": Array [ - Object { - "kind": "Argument", - "name": Object { - "kind": "Name", - "value": "if", - }, - "value": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "inspect", - }, - }, - }, - ], - "kind": "Directive", - "name": Object { - "kind": "Name", - "value": "include", - }, - }, - ], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "inspect", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "dsl", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "response", - }, - "selectionSet": undefined, - }, - ], - }, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "endpoint", - }, - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [ - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "endpointPolicy", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "policyStatus", - }, - "selectionSet": undefined, - }, - Object { - "alias": undefined, - "arguments": Array [], - "directives": Array [], - "kind": "Field", - "name": Object { - "kind": "Name", - "value": "sensorVersion", - }, - "selectionSet": undefined, - }, - ], - }, - }, - ], - }, - }, - ], + ] + } + > +
+ +
+ Host ID +
+
+ +
+ + + — + + +
+
+ +
+ First seen +
+
+ +
+ + + — + + +
+
+ +
+ Last seen +
+
+ +
+ + + — + + +
+
+
+
+
+
+
+
+ , + "title": "IP addresses", }, - }, - ], - }, - "variableDefinitions": Array [ - Object { - "defaultValue": undefined, - "kind": "VariableDefinition", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ID", - }, + Object { + "description": , + "title": "MAC addresses", }, - }, - "variable": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "sourceId", + Object { + "description": , + "title": "Platform", }, - }, - }, - Object { - "defaultValue": undefined, - "kind": "VariableDefinition", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, + ] + } + key="1" + > + +
+ , + "title": "IP addresses", + }, + Object { + "description": , + "title": "MAC addresses", + }, + Object { + "description": , + "title": "Platform", + }, + ] + } + > + , + "title": "IP addresses", + }, + Object { + "description": , + "title": "MAC addresses", + }, + Object { + "description": , + "title": "Platform", + }, + ] + } + > +
+ +
+ IP addresses +
+
+ +
+ + + + — + + + +
+
+ +
+ MAC addresses +
+
+ +
+ + + + — + + + +
+
+ +
+ Platform +
+
+ +
+ + + + — + + + +
+
+
+
+
+
+
+
+ , + "title": "Operating system", }, - }, - "variable": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "hostName", + Object { + "description": , + "title": "Family", }, - }, - }, - Object { - "defaultValue": undefined, - "kind": "VariableDefinition", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "TimerangeInput", - }, + Object { + "description": , + "title": "Version", }, - }, - "variable": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "timerange", + Object { + "description": , + "title": "Architecture", }, - }, - }, - Object { - "defaultValue": undefined, - "kind": "VariableDefinition", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", + ] + } + key="2" + > + +
+ , + "title": "Operating system", + }, + Object { + "description": , + "title": "Family", + }, + Object { + "description": , + "title": "Version", + }, + Object { + "description": , + "title": "Architecture", }, - }, - }, + ] + } + > + , + "title": "Operating system", + }, + Object { + "description": , + "title": "Family", + }, + Object { + "description": , + "title": "Version", + }, + Object { + "description": , + "title": "Architecture", + }, + ] + } + > +
+ +
+ Operating system +
+
+ +
+ + + + — + + + +
+
+ +
+ Family +
+
+ +
+ + + + — + + + +
+
+ +
+ Version +
+
+ +
+ + + + — + + + +
+
+ +
+ Architecture +
+
+ +
+ + + + — + + + +
+
+
+
+
+
+
+
+ , + "title": "Cloud provider", }, - }, - "variable": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "defaultIndex", + Object { + "description": , + "title": "Region", }, - }, - }, - Object { - "defaultValue": undefined, - "kind": "VariableDefinition", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Boolean", - }, + Object { + "description": , + "title": "Instance ID", }, - }, - "variable": Object { - "kind": "Variable", - "name": Object { - "kind": "Name", - "value": "inspect", + Object { + "description": , + "title": "Machine type", }, - }, - }, - ], - }, - ], - "kind": "Document", - "loc": Object { - "end": 930, - "start": 0, - }, - } - } - skip={false} - variables={ - Object { - "defaultIndex": Array [ - "IShouldBeUsed", - ], - "hostName": "testHostName", - "inspect": false, - "sourceId": "default", - "timerange": Object { - "from": "2020-07-07T08:20:18.966Z", - "interval": "12h", - "to": "2020-07-08T08:20:18.966Z", - }, - } - } - /> - - + ] + } + key="3" + > + +
+ , + "title": "Cloud provider", + }, + Object { + "description": , + "title": "Region", + }, + Object { + "description": , + "title": "Instance ID", + }, + Object { + "description": , + "title": "Machine type", + }, + ] + } + > + , + "title": "Cloud provider", + }, + Object { + "description": , + "title": "Region", + }, + Object { + "description": , + "title": "Instance ID", + }, + Object { + "description": , + "title": "Machine type", + }, + ] + } + > +
+ +
+ Cloud provider +
+
+ +
+ + + + — + + + +
+
+ +
+ Region +
+
+ +
+ + + + — + + + +
+
+ +
+ Instance ID +
+
+ +
+ + + + — + + + +
+
+ +
+ Machine type +
+
+ +
+ + + + — + + + +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ + +
`; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.test.tsx index 2ce7090a5b83af..a9ab89359d0ae8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.test.tsx @@ -70,9 +70,7 @@ describe('Expandable Host Component', () => { ); - expect(wrapper.find('HostOverviewByNameComponentQuery').prop('indexNames')).toStrictEqual([ - 'IShouldBeUsed', - ]); + expect(wrapper.find('HostOverview').prop('indexNames')).toStrictEqual(['IShouldBeUsed']); }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx index 78367d17d7b629..f18f1eb993ee23 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx @@ -19,7 +19,7 @@ import { HostItem } from '../../../../../common/search_strategy'; import { AnomalyTableProvider } from '../../../../common/components/ml/anomaly/anomaly_table_provider'; import { hostToCriteria } from '../../../../common/components/ml/criteria/host_to_criteria'; import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; -import { HostOverviewByNameQuery } from '../../../../hosts/containers/hosts/details'; +import { useHostDetails, ID } from '../../../../hosts/containers/hosts/details'; import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; interface ExpandableHostProps { @@ -71,48 +71,42 @@ export const ExpandableHostDetails = ({ [] ); const allPatterns = useDeepEqualSelector(allExistingIndexNamesSelector); - + const [loading, { hostDetails: hostOverview }] = useHostDetails({ + endDate: to, + hostName, + indexNames: allPatterns, + startDate: from, + }); return ( - - {({ hostOverview, loading, id }) => ( - ( + - {({ isLoadingAnomaliesData, anomaliesData }) => ( - { - const fromTo = scoreIntervalToDateTime(score, interval); - setAbsoluteRangeDatePicker({ - id: 'global', - from: fromTo.from, - to: fromTo.to, - }); - }} - /> - )} - + narrowDateRange={(score, interval) => { + const fromTo = scoreIntervalToDateTime(score, interval); + setAbsoluteRangeDatePicker({ + id: 'global', + from: fromTo.from, + to: fromTo.to, + }); + }} + /> )} - + ); }; diff --git a/x-pack/plugins/security_solution/server/graphql/hosts/index.ts b/x-pack/plugins/security_solution/server/graphql/hosts/index.ts deleted file mode 100644 index 400405509b55a7..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/hosts/index.ts +++ /dev/null @@ -1,9 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { createHostsResolvers } from './resolvers'; -export { hostsSchema } from './schema.gql'; diff --git a/x-pack/plugins/security_solution/server/graphql/hosts/resolvers.ts b/x-pack/plugins/security_solution/server/graphql/hosts/resolvers.ts deleted file mode 100644 index cc867a3a314639..00000000000000 --- a/x-pack/plugins/security_solution/server/graphql/hosts/resolvers.ts +++ /dev/null @@ -1,80 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getOr } from 'lodash/fp'; - -import { SourceResolvers } from '../../graphql/types'; -import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; -import { - Hosts, - HostOverviewRequestOptions, - HostsRequestOptions, - HostLastFirstSeenRequestOptions, -} from '../../lib/hosts'; -import { getFields } from '../../utils/build_query'; -import { createOptionsPaginated } from '../../utils/build_query/create_options'; -import { QuerySourceResolver } from '../sources/resolvers'; - -type QueryHostsResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryHostOverviewResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -type QueryHostFirstLastSeenResolver = ChildResolverOf< - AppResolverOf, - QuerySourceResolver ->; - -export interface HostsResolversDeps { - hosts: Hosts; -} - -export const createHostsResolvers = ( - libs: HostsResolversDeps -): { - Source: { - Hosts: QueryHostsResolver; - HostOverview: QueryHostOverviewResolver; - HostFirstLastSeen: QueryHostFirstLastSeenResolver; - }; -} => ({ - Source: { - async Hosts(source, args, { req }, info) { - const options: HostsRequestOptions = { - ...createOptionsPaginated(source, args, info), - sort: args.sort, - defaultIndex: args.defaultIndex, - }; - return libs.hosts.getHosts(req, options); - }, - async HostOverview(source, args, { req }, info) { - const fields = getFields(getOr([], 'fieldNodes[0]', info)); - const options: HostOverviewRequestOptions = { - defaultIndex: args.defaultIndex, - sourceConfiguration: source.configuration, - fields: fields.map((field) => field.replace('edges.node.', '')), - hostName: args.hostName, - timerange: args.timerange, - }; - return libs.hosts.getHostOverview(req, options); - }, - async HostFirstLastSeen(source, args, { req }) { - const options: HostLastFirstSeenRequestOptions = { - sourceConfiguration: source.configuration, - hostName: args.hostName, - defaultIndex: args.defaultIndex, - docValueFields: args.docValueFields, - }; - return libs.hosts.getHostFirstLastSeen(req, options); - }, - }, -}); diff --git a/x-pack/plugins/security_solution/server/graphql/index.ts b/x-pack/plugins/security_solution/server/graphql/index.ts index baef73b8a8b0d1..ba3a1371f1829b 100644 --- a/x-pack/plugins/security_solution/server/graphql/index.ts +++ b/x-pack/plugins/security_solution/server/graphql/index.ts @@ -9,7 +9,6 @@ import { rootSchema } from '../../common/graphql/root'; import { sharedSchema } from '../../common/graphql/shared'; import { ecsSchema } from './ecs'; -import { hostsSchema } from './hosts'; import { dateSchema } from './scalar_date'; import { noteSchema } from './note'; import { pinnedEventSchema } from './pinned_event'; @@ -27,7 +26,6 @@ export const schemas = [ toNumberSchema, toDateSchema, toBooleanSchema, - hostsSchema, noteSchema, pinnedEventSchema, rootSchema, diff --git a/x-pack/plugins/security_solution/server/graphql/types.ts b/x-pack/plugins/security_solution/server/graphql/types.ts index 06476616d4a61f..29d366e20c2998 100644 --- a/x-pack/plugins/security_solution/server/graphql/types.ts +++ b/x-pack/plugins/security_solution/server/graphql/types.ts @@ -23,38 +23,6 @@ export interface SortNote { sortOrder: Direction; } -export interface TimerangeInput { - /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ - interval: string; - /** The end of the timerange */ - to: string; - /** The beginning of the timerange */ - from: string; -} - -export interface PaginationInputPaginated { - /** The activePage parameter defines the page of results you want to fetch */ - activePage: number; - /** The cursorStart parameter defines the start of the results to be displayed */ - cursorStart: number; - /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ - fakePossibleCount: number; - /** The querySize parameter is the number of items to be returned */ - querySize: number; -} - -export interface HostsSortField { - field: HostsFields; - - direction: Direction; -} - -export interface DocValueFieldsInput { - field: string; - - format: string; -} - export interface PageInfoTimeline { pageIndex: number; @@ -247,6 +215,21 @@ export interface SortTimelineInput { sortDirection?: Maybe; } +export interface TimerangeInput { + /** The interval string to use for last bucket. The format is '{value}{unit}'. For example '5m' would return the metrics for the last 5 minutes of the timespan. */ + interval: string; + /** The end of the timerange */ + to: string; + /** The beginning of the timerange */ + from: string; +} + +export interface DocValueFieldsInput { + field: string; + + format: string; +} + export interface PaginationInput { /** The limit parameter allows you to configure the maximum amount of items to be returned */ limit: number; @@ -256,6 +239,17 @@ export interface PaginationInput { tiebreaker?: Maybe; } +export interface PaginationInputPaginated { + /** The activePage parameter defines the page of results you want to fetch */ + activePage: number; + /** The cursorStart parameter defines the start of the results to be displayed */ + cursorStart: number; + /** The fakePossibleCount parameter determines the total count in order to show 5 additional pages */ + fakePossibleCount: number; + /** The querySize parameter is the number of items to be returned */ + querySize: number; +} + export interface SortField { sortFieldId: string; @@ -280,18 +274,6 @@ export enum Direction { desc = 'desc', } -export enum HostsFields { - hostName = 'hostName', - lastSeen = 'lastSeen', -} - -export enum HostPolicyResponseActionStatus { - success = 'success', - failure = 'failure', - warning = 'warning', - unsupported = 'unsupported', -} - export enum TimelineType { default = 'default', template = 'template', @@ -351,12 +333,10 @@ export enum FlowDirection { biDirectional = 'biDirectional', } -export type ToStringArray = string[] | string; - -export type Date = string; - export type ToAny = any; +export type ToStringArray = string[] | string; + export type ToStringArrayNoNullable = any; export type ToDateArray = string[] | string; @@ -365,6 +345,8 @@ export type ToNumberArray = number[] | number; export type ToBooleanArray = boolean[] | boolean; +export type Date = string; + export type ToIFieldSubTypeNonNullable = any; // ==================================================== @@ -454,12 +436,6 @@ export interface Source { configuration: SourceConfiguration; /** The status of the source */ status: SourceStatus; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts: HostsData; - - HostOverview: HostItem; - - HostFirstLastSeen: FirstLastSeenHost; } /** A set of configuration options for a security data source */ @@ -492,126 +468,6 @@ export interface SourceStatus { indexFields: string[]; } -export interface HostsData { - edges: HostsEdges[]; - - totalCount: number; - - pageInfo: PageInfoPaginated; - - inspect?: Maybe; -} - -export interface HostsEdges { - node: HostItem; - - cursor: CursorType; -} - -export interface HostItem { - _id?: Maybe; - - agent?: Maybe; - - cloud?: Maybe; - - endpoint?: Maybe; - - host?: Maybe; - - inspect?: Maybe; - - lastSeen?: Maybe; -} - -export interface AgentFields { - id?: Maybe; -} - -export interface CloudFields { - instance?: Maybe; - - machine?: Maybe; - - provider?: Maybe<(Maybe)[]>; - - region?: Maybe<(Maybe)[]>; -} - -export interface CloudInstance { - id?: Maybe<(Maybe)[]>; -} - -export interface CloudMachine { - type?: Maybe<(Maybe)[]>; -} - -export interface EndpointFields { - endpointPolicy?: Maybe; - - sensorVersion?: Maybe; - - policyStatus?: Maybe; -} - -export interface HostEcsFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe; - - mac?: Maybe; - - name?: Maybe; - - os?: Maybe; - - type?: Maybe; -} - -export interface OsEcsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface Inspect { - dsl: string[]; - - response: string[]; -} - -export interface CursorType { - value?: Maybe; - - tiebreaker?: Maybe; -} - -export interface PageInfoPaginated { - activePage: number; - - fakeTotalCount: number; - - showMorePagesIndicator: boolean; -} - -export interface FirstLastSeenHost { - inspect?: Maybe; - - firstSeen?: Maybe; - - lastSeen?: Maybe; -} - export interface TimelineResult { columns?: Maybe; @@ -987,6 +843,36 @@ export interface AuditdEcsFields { sequence?: Maybe; } +export interface OsEcsFields { + platform?: Maybe; + + name?: Maybe; + + full?: Maybe; + + family?: Maybe; + + version?: Maybe; + + kernel?: Maybe; +} + +export interface HostEcsFields { + architecture?: Maybe; + + id?: Maybe; + + ip?: Maybe; + + mac?: Maybe; + + name?: Maybe; + + os?: Maybe; + + type?: Maybe; +} + export interface Thread { id?: Maybe; @@ -1549,34 +1435,10 @@ export interface EcsEdges { cursor: CursorType; } -export interface OsFields { - platform?: Maybe; - - name?: Maybe; - - full?: Maybe; - - family?: Maybe; - - version?: Maybe; - - kernel?: Maybe; -} - -export interface HostFields { - architecture?: Maybe; - - id?: Maybe; - - ip?: Maybe<(Maybe)[]>; - - mac?: Maybe<(Maybe)[]>; - - name?: Maybe; - - os?: Maybe; +export interface CursorType { + value?: Maybe; - type?: Maybe; + tiebreaker?: Maybe; } /** A descriptor of a field in an index */ @@ -1611,6 +1473,20 @@ export interface PageInfo { hasNextPage?: Maybe; } +export interface Inspect { + dsl: string[]; + + response: string[]; +} + +export interface PageInfoPaginated { + activePage: number; + + fakeTotalCount: number; + + showMorePagesIndicator: boolean; +} + // ==================================================== // Arguments // ==================================================== @@ -1656,39 +1532,6 @@ export interface GetAllTimelineQueryArgs { status?: Maybe; } -export interface HostsSourceArgs { - id?: Maybe; - - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - sort: HostsSortField; - - filterQuery?: Maybe; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} -export interface HostOverviewSourceArgs { - id?: Maybe; - - hostName: string; - - timerange: TimerangeInput; - - defaultIndex: string[]; -} -export interface HostFirstLastSeenSourceArgs { - id?: Maybe; - - hostName: string; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; -} export interface IndicesExistSourceStatusArgs { defaultIndex: string[]; } @@ -2093,12 +1936,6 @@ export namespace SourceResolvers { configuration?: ConfigurationResolver; /** The status of the source */ status?: StatusResolver; - /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ - Hosts?: HostsResolver; - - HostOverview?: HostOverviewResolver; - - HostFirstLastSeen?: HostFirstLastSeenResolver; } export type IdResolver = Resolver< @@ -2116,57 +1953,6 @@ export namespace SourceResolvers { Parent, TContext >; - export type HostsResolver = Resolver< - R, - Parent, - TContext, - HostsArgs - >; - export interface HostsArgs { - id?: Maybe; - - timerange: TimerangeInput; - - pagination: PaginationInputPaginated; - - sort: HostsSortField; - - filterQuery?: Maybe; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; - } - - export type HostOverviewResolver< - R = HostItem, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface HostOverviewArgs { - id?: Maybe; - - hostName: string; - - timerange: TimerangeInput; - - defaultIndex: string[]; - } - - export type HostFirstLastSeenResolver< - R = FirstLastSeenHost, - Parent = Source, - TContext = SiemContext - > = Resolver; - export interface HostFirstLastSeenArgs { - id?: Maybe; - - hostName: string; - - defaultIndex: string[]; - - docValueFields: DocValueFieldsInput[]; - } } /** A set of configuration options for a security data source */ export namespace SourceConfigurationResolvers { @@ -2247,410 +2033,14 @@ export namespace SourceStatusResolvers { defaultIndex: string[]; } - export type IndexFieldsResolver< - R = string[], - Parent = SourceStatus, - TContext = SiemContext - > = Resolver; - export interface IndexFieldsArgs { - defaultIndex: string[]; - } -} - -export namespace HostsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - - totalCount?: TotalCountResolver; - - pageInfo?: PageInfoResolver; - - inspect?: InspectResolver, TypeParent, TContext>; - } - - export type EdgesResolver< - R = HostsEdges[], - Parent = HostsData, - TContext = SiemContext - > = Resolver; - export type TotalCountResolver = Resolver< - R, - Parent, - TContext - >; - export type PageInfoResolver< - R = PageInfoPaginated, - Parent = HostsData, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = HostsData, - TContext = SiemContext - > = Resolver; -} - -export namespace HostsEdgesResolvers { - export interface Resolvers { - node?: NodeResolver; - - cursor?: CursorResolver; - } - - export type NodeResolver = Resolver< - R, - Parent, - TContext - >; - export type CursorResolver< - R = CursorType, - Parent = HostsEdges, - TContext = SiemContext - > = Resolver; -} - -export namespace HostItemResolvers { - export interface Resolvers { - _id?: _IdResolver, TypeParent, TContext>; - - agent?: AgentResolver, TypeParent, TContext>; - - cloud?: CloudResolver, TypeParent, TContext>; - - endpoint?: EndpointResolver, TypeParent, TContext>; - - host?: HostResolver, TypeParent, TContext>; - - inspect?: InspectResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - } - - export type _IdResolver, Parent = HostItem, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type AgentResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type CloudResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type EndpointResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type HostResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type InspectResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = HostItem, - TContext = SiemContext - > = Resolver; -} - -export namespace AgentFieldsResolvers { - export interface Resolvers { - id?: IdResolver, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe, - Parent = AgentFields, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudFieldsResolvers { - export interface Resolvers { - instance?: InstanceResolver, TypeParent, TContext>; - - machine?: MachineResolver, TypeParent, TContext>; - - provider?: ProviderResolver)[]>, TypeParent, TContext>; - - region?: RegionResolver)[]>, TypeParent, TContext>; - } - - export type InstanceResolver< - R = Maybe, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type MachineResolver< - R = Maybe, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type ProviderResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; - export type RegionResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudFields, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudInstanceResolvers { - export interface Resolvers { - id?: IdResolver)[]>, TypeParent, TContext>; - } - - export type IdResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudInstance, - TContext = SiemContext - > = Resolver; -} - -export namespace CloudMachineResolvers { - export interface Resolvers { - type?: TypeResolver)[]>, TypeParent, TContext>; - } - - export type TypeResolver< - R = Maybe<(Maybe)[]>, - Parent = CloudMachine, - TContext = SiemContext - > = Resolver; -} - -export namespace EndpointFieldsResolvers { - export interface Resolvers { - endpointPolicy?: EndpointPolicyResolver, TypeParent, TContext>; - - sensorVersion?: SensorVersionResolver, TypeParent, TContext>; - - policyStatus?: PolicyStatusResolver< - Maybe, - TypeParent, - TContext - >; - } - - export type EndpointPolicyResolver< - R = Maybe, - Parent = EndpointFields, - TContext = SiemContext - > = Resolver; - export type SensorVersionResolver< - R = Maybe, - Parent = EndpointFields, - TContext = SiemContext - > = Resolver; - export type PolicyStatusResolver< - R = Maybe, - Parent = EndpointFields, - TContext = SiemContext - > = Resolver; -} - -export namespace HostEcsFieldsResolvers { - export interface Resolvers { - architecture?: ArchitectureResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - ip?: IpResolver, TypeParent, TContext>; - - mac?: MacResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - os?: OsResolver, TypeParent, TContext>; - - type?: TypeResolver, TypeParent, TContext>; - } - - export type ArchitectureResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type IdResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type IpResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type MacResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type OsResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; - export type TypeResolver< - R = Maybe, - Parent = HostEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace OsEcsFieldsResolvers { - export interface Resolvers { - platform?: PlatformResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - full?: FullResolver, TypeParent, TContext>; - - family?: FamilyResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - - kernel?: KernelResolver, TypeParent, TContext>; - } - - export type PlatformResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type FullResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type FamilyResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; - export type KernelResolver< - R = Maybe, - Parent = OsEcsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace InspectResolvers { - export interface Resolvers { - dsl?: DslResolver; - - response?: ResponseResolver; - } - - export type DslResolver = Resolver< - R, - Parent, - TContext - >; - export type ResponseResolver = Resolver< - R, - Parent, - TContext - >; -} - -export namespace CursorTypeResolvers { - export interface Resolvers { - value?: ValueResolver, TypeParent, TContext>; - - tiebreaker?: TiebreakerResolver, TypeParent, TContext>; - } - - export type ValueResolver< - R = Maybe, - Parent = CursorType, - TContext = SiemContext - > = Resolver; - export type TiebreakerResolver< - R = Maybe, - Parent = CursorType, - TContext = SiemContext - > = Resolver; -} - -export namespace PageInfoPaginatedResolvers { - export interface Resolvers { - activePage?: ActivePageResolver; - - fakeTotalCount?: FakeTotalCountResolver; - - showMorePagesIndicator?: ShowMorePagesIndicatorResolver; - } - - export type ActivePageResolver< - R = number, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; - export type FakeTotalCountResolver< - R = number, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; - export type ShowMorePagesIndicatorResolver< - R = boolean, - Parent = PageInfoPaginated, - TContext = SiemContext - > = Resolver; -} - -export namespace FirstLastSeenHostResolvers { - export interface Resolvers { - inspect?: InspectResolver, TypeParent, TContext>; - - firstSeen?: FirstSeenResolver, TypeParent, TContext>; - - lastSeen?: LastSeenResolver, TypeParent, TContext>; - } - - export type InspectResolver< - R = Maybe, - Parent = FirstLastSeenHost, - TContext = SiemContext - > = Resolver; - export type FirstSeenResolver< - R = Maybe, - Parent = FirstLastSeenHost, - TContext = SiemContext - > = Resolver; - export type LastSeenResolver< - R = Maybe, - Parent = FirstLastSeenHost, + export type IndexFieldsResolver< + R = string[], + Parent = SourceStatus, TContext = SiemContext - > = Resolver; + > = Resolver; + export interface IndexFieldsArgs { + defaultIndex: string[]; + } } export namespace TimelineResultResolvers { @@ -3998,6 +3388,107 @@ export namespace AuditdEcsFieldsResolvers { > = Resolver; } +export namespace OsEcsFieldsResolvers { + export interface Resolvers { + platform?: PlatformResolver, TypeParent, TContext>; + + name?: NameResolver, TypeParent, TContext>; + + full?: FullResolver, TypeParent, TContext>; + + family?: FamilyResolver, TypeParent, TContext>; + + version?: VersionResolver, TypeParent, TContext>; + + kernel?: KernelResolver, TypeParent, TContext>; + } + + export type PlatformResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; + export type NameResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; + export type FullResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; + export type FamilyResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; + export type VersionResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; + export type KernelResolver< + R = Maybe, + Parent = OsEcsFields, + TContext = SiemContext + > = Resolver; +} + +export namespace HostEcsFieldsResolvers { + export interface Resolvers { + architecture?: ArchitectureResolver, TypeParent, TContext>; + + id?: IdResolver, TypeParent, TContext>; + + ip?: IpResolver, TypeParent, TContext>; + + mac?: MacResolver, TypeParent, TContext>; + + name?: NameResolver, TypeParent, TContext>; + + os?: OsResolver, TypeParent, TContext>; + + type?: TypeResolver, TypeParent, TContext>; + } + + export type ArchitectureResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type IdResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type IpResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type MacResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type NameResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type OsResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; + export type TypeResolver< + R = Maybe, + Parent = HostEcsFields, + TContext = SiemContext + > = Resolver; +} + export namespace ThreadResolvers { export interface Resolvers { id?: IdResolver, TypeParent, TContext>; @@ -5887,103 +5378,21 @@ export namespace EcsEdgesResolvers { >; } -export namespace OsFieldsResolvers { - export interface Resolvers { - platform?: PlatformResolver, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - full?: FullResolver, TypeParent, TContext>; - - family?: FamilyResolver, TypeParent, TContext>; - - version?: VersionResolver, TypeParent, TContext>; - - kernel?: KernelResolver, TypeParent, TContext>; - } - - export type PlatformResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type NameResolver, Parent = OsFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type FullResolver, Parent = OsFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type FamilyResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type VersionResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; - export type KernelResolver< - R = Maybe, - Parent = OsFields, - TContext = SiemContext - > = Resolver; -} - -export namespace HostFieldsResolvers { - export interface Resolvers { - architecture?: ArchitectureResolver, TypeParent, TContext>; - - id?: IdResolver, TypeParent, TContext>; - - ip?: IpResolver)[]>, TypeParent, TContext>; - - mac?: MacResolver)[]>, TypeParent, TContext>; - - name?: NameResolver, TypeParent, TContext>; - - os?: OsResolver, TypeParent, TContext>; +export namespace CursorTypeResolvers { + export interface Resolvers { + value?: ValueResolver, TypeParent, TContext>; - type?: TypeResolver, TypeParent, TContext>; + tiebreaker?: TiebreakerResolver, TypeParent, TContext>; } - export type ArchitectureResolver< - R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type IdResolver, Parent = HostFields, TContext = SiemContext> = Resolver< - R, - Parent, - TContext - >; - export type IpResolver< - R = Maybe<(Maybe)[]>, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type MacResolver< - R = Maybe<(Maybe)[]>, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type NameResolver< + export type ValueResolver< R = Maybe, - Parent = HostFields, - TContext = SiemContext - > = Resolver; - export type OsResolver< - R = Maybe, - Parent = HostFields, + Parent = CursorType, TContext = SiemContext > = Resolver; - export type TypeResolver< + export type TiebreakerResolver< R = Maybe, - Parent = HostFields, + Parent = CursorType, TContext = SiemContext > = Resolver; } @@ -6090,6 +5499,51 @@ export namespace PageInfoResolvers { > = Resolver; } +export namespace InspectResolvers { + export interface Resolvers { + dsl?: DslResolver; + + response?: ResponseResolver; + } + + export type DslResolver = Resolver< + R, + Parent, + TContext + >; + export type ResponseResolver = Resolver< + R, + Parent, + TContext + >; +} + +export namespace PageInfoPaginatedResolvers { + export interface Resolvers { + activePage?: ActivePageResolver; + + fakeTotalCount?: FakeTotalCountResolver; + + showMorePagesIndicator?: ShowMorePagesIndicatorResolver; + } + + export type ActivePageResolver< + R = number, + Parent = PageInfoPaginated, + TContext = SiemContext + > = Resolver; + export type FakeTotalCountResolver< + R = number, + Parent = PageInfoPaginated, + TContext = SiemContext + > = Resolver; + export type ShowMorePagesIndicatorResolver< + R = boolean, + Parent = PageInfoPaginated, + TContext = SiemContext + > = Resolver; +} + /** Directs the executor to skip this field or fragment when the `if` argument is true. */ export type SkipDirectiveResolver = DirectiveResolverFn< Result, @@ -6123,15 +5577,12 @@ export interface DeprecatedDirectiveArgs { reason?: string; } -export interface ToStringArrayScalarConfig extends GraphQLScalarTypeConfig { - name: 'ToStringArray'; -} -export interface DateScalarConfig extends GraphQLScalarTypeConfig { - name: 'Date'; -} export interface ToAnyScalarConfig extends GraphQLScalarTypeConfig { name: 'ToAny'; } +export interface ToStringArrayScalarConfig extends GraphQLScalarTypeConfig { + name: 'ToStringArray'; +} export interface ToStringArrayNoNullableScalarConfig extends GraphQLScalarTypeConfig { name: 'ToStringArrayNoNullable'; @@ -6145,6 +5596,9 @@ export interface ToNumberArrayScalarConfig extends GraphQLScalarTypeConfig { name: 'ToBooleanArray'; } +export interface DateScalarConfig extends GraphQLScalarTypeConfig { + name: 'Date'; +} export interface ToIFieldSubTypeNonNullableScalarConfig extends GraphQLScalarTypeConfig { name: 'ToIFieldSubTypeNonNullable'; @@ -6159,20 +5613,6 @@ export type IResolvers = { SourceConfiguration?: SourceConfigurationResolvers.Resolvers; SourceFields?: SourceFieldsResolvers.Resolvers; SourceStatus?: SourceStatusResolvers.Resolvers; - HostsData?: HostsDataResolvers.Resolvers; - HostsEdges?: HostsEdgesResolvers.Resolvers; - HostItem?: HostItemResolvers.Resolvers; - AgentFields?: AgentFieldsResolvers.Resolvers; - CloudFields?: CloudFieldsResolvers.Resolvers; - CloudInstance?: CloudInstanceResolvers.Resolvers; - CloudMachine?: CloudMachineResolvers.Resolvers; - EndpointFields?: EndpointFieldsResolvers.Resolvers; - HostEcsFields?: HostEcsFieldsResolvers.Resolvers; - OsEcsFields?: OsEcsFieldsResolvers.Resolvers; - Inspect?: InspectResolvers.Resolvers; - CursorType?: CursorTypeResolvers.Resolvers; - PageInfoPaginated?: PageInfoPaginatedResolvers.Resolvers; - FirstLastSeenHost?: FirstLastSeenHostResolvers.Resolvers; TimelineResult?: TimelineResultResolvers.Resolvers; ColumnHeaderResult?: ColumnHeaderResultResolvers.Resolvers; DataProviderResult?: DataProviderResultResolvers.Resolvers; @@ -6198,6 +5638,8 @@ export type IResolvers = { AgentEcsField?: AgentEcsFieldResolvers.Resolvers; AuditdData?: AuditdDataResolvers.Resolvers; AuditdEcsFields?: AuditdEcsFieldsResolvers.Resolvers; + OsEcsFields?: OsEcsFieldsResolvers.Resolvers; + HostEcsFields?: HostEcsFieldsResolvers.Resolvers; Thread?: ThreadResolvers.Resolvers; ProcessHashData?: ProcessHashDataResolvers.Resolvers; ProcessEcsFields?: ProcessEcsFieldsResolvers.Resolvers; @@ -6241,17 +5683,18 @@ export type IResolvers = { RuleEcsField?: RuleEcsFieldResolvers.Resolvers; Ecs?: EcsResolvers.Resolvers; EcsEdges?: EcsEdgesResolvers.Resolvers; - OsFields?: OsFieldsResolvers.Resolvers; - HostFields?: HostFieldsResolvers.Resolvers; + CursorType?: CursorTypeResolvers.Resolvers; IndexField?: IndexFieldResolvers.Resolvers; PageInfo?: PageInfoResolvers.Resolvers; - ToStringArray?: GraphQLScalarType; - Date?: GraphQLScalarType; + Inspect?: InspectResolvers.Resolvers; + PageInfoPaginated?: PageInfoPaginatedResolvers.Resolvers; ToAny?: GraphQLScalarType; + ToStringArray?: GraphQLScalarType; ToStringArrayNoNullable?: GraphQLScalarType; ToDateArray?: GraphQLScalarType; ToNumberArray?: GraphQLScalarType; ToBooleanArray?: GraphQLScalarType; + Date?: GraphQLScalarType; ToIFieldSubTypeNonNullable?: GraphQLScalarType; } & { [typeName: string]: never }; diff --git a/x-pack/plugins/security_solution/server/init_server.ts b/x-pack/plugins/security_solution/server/init_server.ts index 1744d9b75ec110..d2810bf71f8aea 100644 --- a/x-pack/plugins/security_solution/server/init_server.ts +++ b/x-pack/plugins/security_solution/server/init_server.ts @@ -9,7 +9,6 @@ import { IResolvers, makeExecutableSchema } from 'graphql-tools'; import { schemas } from './graphql'; import { createScalarToStringArrayValueResolvers } from './graphql/ecs'; -import { createHostsResolvers } from './graphql/hosts'; import { createNoteResolvers } from './graphql/note'; import { createPinnedEventResolvers } from './graphql/pinned_event'; import { createScalarDateResolvers } from './graphql/scalar_date'; @@ -25,7 +24,6 @@ import { AppBackendLibs } from './lib/types'; export const initServer = (libs: AppBackendLibs) => { const schema = makeExecutableSchema({ resolvers: [ - createHostsResolvers(libs) as IResolvers, createNoteResolvers(libs) as IResolvers, createPinnedEventResolvers(libs) as IResolvers, createSourcesResolvers(libs) as IResolvers, diff --git a/x-pack/plugins/security_solution/server/lib/compose/kibana.ts b/x-pack/plugins/security_solution/server/lib/compose/kibana.ts index 5c83f70fdb10b4..01318c87f8b3f8 100644 --- a/x-pack/plugins/security_solution/server/lib/compose/kibana.ts +++ b/x-pack/plugins/security_solution/server/lib/compose/kibana.ts @@ -9,7 +9,6 @@ import { CoreSetup } from '../../../../../../src/core/server'; import { SetupPlugins } from '../../plugin'; import { KibanaBackendFrameworkAdapter } from '../framework/kibana_framework_adapter'; -import { ElasticsearchHostsAdapter, Hosts } from '../hosts'; import { ElasticsearchIndexFieldAdapter, IndexFields } from '../index_fields'; @@ -30,7 +29,6 @@ export function compose( const domainLibs: AppDomainLibs = { fields: new IndexFields(new ElasticsearchIndexFieldAdapter()), - hosts: new Hosts(new ElasticsearchHostsAdapter(framework, endpointContext)), }; const libs: AppBackendLibs = { diff --git a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts b/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts deleted file mode 100644 index 04d52a044e390c..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.test.ts +++ /dev/null @@ -1,252 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FirstLastSeenHost, HostItem, HostsData, HostsEdges } from '../../graphql/types'; -import { FrameworkAdapter, FrameworkRequest } from '../framework'; - -import { ElasticsearchHostsAdapter, formatHostEdgesData } from './elasticsearch_adapter'; -import { - mockEndpointMetadata, - mockGetHostOverviewOptions, - mockGetHostOverviewRequest, - mockGetHostOverviewResponse, - mockGetHostOverviewResult, - mockGetHostLastFirstSeenOptions, - mockGetHostLastFirstSeenRequest, - mockGetHostsOptions, - mockGetHostsRequest, - mockGetHostsResponse, - mockGetHostsResult, - mockGetHostLastFirstSeenResult, - mockGetHostLastFirstSeenResponse, - mockGetHostOverviewRequestDsl, - mockGetHostLastFirstSeenDsl, - mockGetHostsQueryDsl, -} from './mock'; -import { HostAggEsItem } from './types'; -import { EndpointAppContext } from '../../endpoint/types'; -import { mockLogger } from '../detection_engine/signals/__mocks__/es_results'; -import { EndpointAppContextService } from '../../endpoint/endpoint_app_context_services'; -import { - createMockEndpointAppContextServiceStartContract, - createMockPackageService, -} from '../../endpoint/mocks'; -import { PackageService } from '../../../../fleet/server/services'; -import { ElasticsearchAssetType } from '../../../../fleet/common/types/models'; -import { parseExperimentalConfigValue } from '../../../common/experimental_features'; - -jest.mock('./query.hosts.dsl', () => { - return { - buildHostsQuery: jest.fn(() => mockGetHostsQueryDsl), - }; -}); - -jest.mock('./query.detail_host.dsl', () => { - return { - buildHostOverviewQuery: jest.fn(() => mockGetHostOverviewRequestDsl), - }; -}); - -jest.mock('./query.last_first_seen_host.dsl', () => { - return { - buildLastFirstSeenHostQuery: jest.fn(() => mockGetHostLastFirstSeenDsl), - }; -}); -jest.mock('../../endpoint/routes/metadata/handlers', () => { - return { - getHostData: jest.fn(() => mockEndpointMetadata), - }; -}); - -describe('hosts elasticsearch_adapter', () => { - describe('#formatHostsData', () => { - const buckets: HostAggEsItem = { - key: 'zeek-london', - os: { - hits: { - total: { - value: 242338, - relation: 'eq', - }, - max_score: null, - hits: [ - { - _index: 'auditbeat-8.0.0-2019.09.06-000022', - _id: 'dl0T_m0BHe9nqdOiF2A8', - _score: null, - _source: { - host: { - os: { - kernel: '5.0.0-1013-gcp', - name: 'Ubuntu', - family: 'debian', - version: '18.04.2 LTS (Bionic Beaver)', - platform: 'ubuntu', - }, - }, - }, - sort: [1571925726017], - }, - ], - }, - }, - }; - - test('it formats a host with a source of name correctly', () => { - const fields: readonly string[] = ['host.name']; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { tiebreaker: null, value: 'zeek-london' }, - node: { host: { name: 'zeek-london' }, _id: 'zeek-london' }, - }; - - expect(data).toEqual(expected); - }); - - test('it formats a host with a source of os correctly', () => { - const fields: readonly string[] = ['host.os.name']; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { tiebreaker: null, value: 'zeek-london' }, - node: { host: { os: { name: 'Ubuntu' } }, _id: 'zeek-london' }, - }; - - expect(data).toEqual(expected); - }); - - test('it formats a host with a source of version correctly', () => { - const fields: readonly string[] = ['host.os.version']; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { tiebreaker: null, value: 'zeek-london' }, - node: { host: { os: { version: '18.04.2 LTS (Bionic Beaver)' } }, _id: 'zeek-london' }, - }; - - expect(data).toEqual(expected); - }); - - test('it formats a host with a source of id correctly', () => { - const fields: readonly string[] = ['host.name']; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { tiebreaker: null, value: 'zeek-london' }, - node: { _id: 'zeek-london', host: { name: 'zeek-london' } }, - }; - - expect(data).toEqual(expected); - }); - - test('it formats a host with a source of name, lastBeat, os, and version correctly', () => { - const fields: readonly string[] = ['host.name', 'host.os.name', 'host.os.version']; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { tiebreaker: null, value: 'zeek-london' }, - node: { - _id: 'zeek-london', - host: { - name: 'zeek-london', - os: { name: 'Ubuntu', version: '18.04.2 LTS (Bionic Beaver)' }, - }, - }, - }; - - expect(data).toEqual(expected); - }); - - test('it formats a host without any data if fields are empty', () => { - const fields: readonly string[] = []; - const data = formatHostEdgesData(fields, buckets); - const expected: HostsEdges = { - cursor: { - tiebreaker: null, - value: '', - }, - node: {}, - }; - - expect(data).toEqual(expected); - }); - }); - - const endpointAppContextService = new EndpointAppContextService(); - const startContract = createMockEndpointAppContextServiceStartContract(); - const mockPackageService: jest.Mocked = createMockPackageService(); - mockPackageService.getInstalledEsAssetReferences.mockReturnValue( - Promise.resolve([ - { - id: 'metrics-endpoint.metadata-current-default-0.16.0-dev.0', - type: ElasticsearchAssetType.transform, - }, - ]) - ); - endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); - const endpointContext: EndpointAppContext = { - logFactory: mockLogger, - service: endpointAppContextService, - config: jest.fn(), - experimentalFeatures: parseExperimentalConfigValue([]), - }; - describe('#getHosts', () => { - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockGetHostsResponse); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ callWithRequest: mockCallWithRequest })); - - test('Happy Path', async () => { - const EsHosts = new ElasticsearchHostsAdapter(mockFramework, endpointContext); - const data: HostsData = await EsHosts.getHosts( - mockGetHostsRequest as FrameworkRequest, - mockGetHostsOptions - ); - expect(data).toEqual(mockGetHostsResult); - }); - }); - - describe('#getHostOverview', () => { - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockGetHostOverviewResponse); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ callWithRequest: mockCallWithRequest })); - - test('Happy Path', async () => { - const EsHosts = new ElasticsearchHostsAdapter(mockFramework, endpointContext); - const data: HostItem = await EsHosts.getHostOverview( - mockGetHostOverviewRequest as FrameworkRequest, - mockGetHostOverviewOptions - ); - expect(data).toEqual(mockGetHostOverviewResult); - }); - }); - - describe('#getHostLastFirstSeen', () => { - const mockCallWithRequest = jest.fn(); - mockCallWithRequest.mockResolvedValue(mockGetHostLastFirstSeenResponse); - const mockFramework: FrameworkAdapter = { - callWithRequest: mockCallWithRequest, - registerGraphQLEndpoint: jest.fn(), - getIndexPatternsService: jest.fn(), - }; - jest.doMock('../framework', () => ({ callWithRequest: mockCallWithRequest })); - - test('Happy Path', async () => { - const EsHosts = new ElasticsearchHostsAdapter(mockFramework, endpointContext); - const data: FirstLastSeenHost = await EsHosts.getHostFirstLastSeen( - mockGetHostLastFirstSeenRequest as FrameworkRequest, - mockGetHostLastFirstSeenOptions - ); - expect(data).toEqual(mockGetHostLastFirstSeenResult); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.ts b/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.ts deleted file mode 100644 index 49066c099af380..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/elasticsearch_adapter.ts +++ /dev/null @@ -1,236 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { set } from '@elastic/safer-lodash-set/fp'; -import { get, getOr, has, head } from 'lodash/fp'; - -import { - EndpointFields, - FirstLastSeenHost, - HostItem, - HostsData, - HostsEdges, -} from '../../graphql/types'; -import { inspectStringifyObject } from '../../utils/build_query'; -import { hostFieldsMap } from '../ecs_fields'; -import { FrameworkAdapter, FrameworkRequest } from '../framework'; -import { TermAggregation } from '../types'; -import { buildHostOverviewQuery } from './query.detail_host.dsl'; -import { buildHostsQuery } from './query.hosts.dsl'; -import { buildLastFirstSeenHostQuery } from './query.last_first_seen_host.dsl'; -import { - HostAggEsData, - HostAggEsItem, - HostBuckets, - HostEsData, - HostLastFirstSeenRequestOptions, - HostOverviewRequestOptions, - HostsAdapter, - HostsRequestOptions, - HostValue, -} from './types'; -import { DEFAULT_MAX_TABLE_QUERY_SIZE } from '../../../common/constants'; -import { EndpointAppContext } from '../../endpoint/types'; -import { getHostData } from '../../endpoint/routes/metadata/handlers'; - -export class ElasticsearchHostsAdapter implements HostsAdapter { - constructor( - private readonly framework: FrameworkAdapter, - private readonly endpointContext: EndpointAppContext - ) {} - - public async getHosts( - request: FrameworkRequest, - options: HostsRequestOptions - ): Promise { - const dsl = buildHostsQuery(options); - if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { - throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); - } - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const { activePage, cursorStart, fakePossibleCount, querySize } = options.pagination; - const totalCount = getOr(0, 'aggregations.host_count.value', response); - const buckets: HostAggEsItem[] = getOr([], 'aggregations.host_data.buckets', response); - const hostsEdges = buckets.map((bucket) => formatHostEdgesData(options.fields, bucket)); - const fakeTotalCount = fakePossibleCount <= totalCount ? fakePossibleCount : totalCount; - const edges = hostsEdges.splice(cursorStart, querySize - cursorStart); - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - const showMorePagesIndicator = totalCount > fakeTotalCount; - - return { - inspect, - edges, - totalCount, - pageInfo: { - activePage: activePage ? activePage : 0, - fakeTotalCount, - showMorePagesIndicator, - }, - }; - } - - public async getHostOverview( - request: FrameworkRequest, - options: HostOverviewRequestOptions - ): Promise { - const dsl = buildHostOverviewQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const aggregations: HostAggEsItem = get('aggregations', response) || {}; - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - const formattedHostItem = formatHostItem(options.fields, aggregations); - const ident = // endpoint-generated ID, NOT elastic-agent-id - formattedHostItem.agent && formattedHostItem.agent.id - ? Array.isArray(formattedHostItem.agent.id) - ? formattedHostItem.agent.id[0] - : formattedHostItem.agent.id - : null; - const endpoint: EndpointFields | null = await this.getHostEndpoint(request, ident); - return { inspect, _id: options.hostName, ...formattedHostItem, endpoint }; - } - - public async getHostEndpoint( - request: FrameworkRequest, - id: string | null - ): Promise { - const logger = this.endpointContext.logFactory.get('metadata'); - try { - const agentService = this.endpointContext.service.getAgentService(); - if (agentService === undefined) { - throw new Error('agentService not available'); - } - const metadataRequestContext = { - endpointAppContextService: this.endpointContext.service, - logger, - requestHandlerContext: request.context, - }; - const endpointData = - id != null && metadataRequestContext.endpointAppContextService.getAgentService() != null - ? await getHostData(metadataRequestContext, id) - : null; - return endpointData != null && endpointData.metadata - ? { - endpointPolicy: endpointData.metadata.Endpoint.policy.applied.name, - policyStatus: endpointData.metadata.Endpoint.policy.applied.status, - sensorVersion: endpointData.metadata.agent.version, - } - : null; - } catch (err) { - logger.warn(JSON.stringify(err, null, 2)); - return null; - } - } - - public async getHostFirstLastSeen( - request: FrameworkRequest, - options: HostLastFirstSeenRequestOptions - ): Promise { - const dsl = buildLastFirstSeenHostQuery(options); - const response = await this.framework.callWithRequest( - request, - 'search', - dsl - ); - const aggregations: HostAggEsItem = get('aggregations', response) || {}; - const inspect = { - dsl: [inspectStringifyObject(dsl)], - response: [inspectStringifyObject(response)], - }; - - return { - inspect, - firstSeen: get('firstSeen.value_as_string', aggregations), - lastSeen: get('lastSeen.value_as_string', aggregations), - }; - } -} - -export const formatHostEdgesData = (fields: readonly string[], bucket: HostAggEsItem): HostsEdges => - fields.reduce( - (flattenedFields, fieldName) => { - const hostId = get('key', bucket); - flattenedFields.node._id = hostId || null; - flattenedFields.cursor.value = hostId || ''; - const fieldValue = getHostFieldValue(fieldName, bucket); - if (fieldValue != null) { - return set(`node.${fieldName}`, fieldValue, flattenedFields); - } - return flattenedFields; - }, - { - node: {}, - cursor: { - value: '', - tiebreaker: null, - }, - } - ); - -const formatHostItem = (fields: readonly string[], bucket: HostAggEsItem): HostItem => - fields.reduce((flattenedFields, fieldName) => { - const fieldValue = getHostFieldValue(fieldName, bucket); - if (fieldValue != null) { - return set(fieldName, fieldValue, flattenedFields); - } - return flattenedFields; - }, {}); - -const getHostFieldValue = (fieldName: string, bucket: HostAggEsItem): string | string[] | null => { - const aggField = hostFieldsMap[fieldName] - ? hostFieldsMap[fieldName].replace(/\./g, '_') - : fieldName.replace(/\./g, '_'); - if ( - [ - 'host.ip', - 'host.mac', - 'cloud.instance.id', - 'cloud.machine.type', - 'cloud.provider', - 'cloud.region', - ].includes(fieldName) && - has(aggField, bucket) - ) { - const data: HostBuckets = get(aggField, bucket); - return data.buckets.map((obj) => obj.key); - } else if (has(`${aggField}.buckets`, bucket)) { - return getFirstItem(get(`${aggField}`, bucket)); - } else if (has(aggField, bucket)) { - const valueObj: HostValue = get(aggField, bucket); - return valueObj.value_as_string; - } else if (['host.name', 'host.os.name', 'host.os.version'].includes(fieldName)) { - switch (fieldName) { - case 'host.name': - return get('key', bucket) || null; - case 'host.os.name': - return get('os.hits.hits[0]._source.host.os.name', bucket) || null; - case 'host.os.version': - return get('os.hits.hits[0]._source.host.os.version', bucket) || null; - } - } - return null; -}; - -const getFirstItem = (data: HostBuckets): string | null => { - const firstItem = head(data.buckets); - if (firstItem == null) { - return null; - } - return firstItem.key; -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/helpers.ts b/x-pack/plugins/security_solution/server/lib/hosts/helpers.ts deleted file mode 100644 index 23d798f5584037..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/helpers.ts +++ /dev/null @@ -1,62 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { AggregationRequest } from '../types'; - -export const buildFieldsTermAggregation = (esFields: readonly string[]): AggregationRequest => - esFields.reduce( - (res, field) => ({ - ...res, - ...getTermsAggregationTypeFromField(field), - }), - {} - ); - -const getTermsAggregationTypeFromField = (field: string): AggregationRequest => { - if (field === 'host.ip') { - return { - host_ip: { - terms: { - script: { - source: "doc['host.ip']", - lang: 'painless', - }, - size: 10, - order: { - timestamp: 'desc', - }, - }, - aggs: { - timestamp: { - max: { - field: '@timestamp', - }, - }, - }, - }, - }; - } - - return { - [field.replace(/\./g, '_')]: { - terms: { - field, - size: 10, - order: { - timestamp: 'desc', - }, - }, - aggs: { - timestamp: { - max: { - field: '@timestamp', - }, - }, - }, - }, - }; -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/index.ts b/x-pack/plugins/security_solution/server/lib/hosts/index.ts deleted file mode 100644 index 07c71815ddbcba..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/index.ts +++ /dev/null @@ -1,41 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FirstLastSeenHost, HostItem, HostsData } from '../../graphql/types'; -import { FrameworkRequest } from '../framework'; - -import { - HostOverviewRequestOptions, - HostLastFirstSeenRequestOptions, - HostsAdapter, - HostsRequestOptions, -} from './types'; - -export * from './elasticsearch_adapter'; -export * from './types'; - -export class Hosts { - constructor(private readonly adapter: HostsAdapter) {} - - public async getHosts(req: FrameworkRequest, options: HostsRequestOptions): Promise { - return this.adapter.getHosts(req, options); - } - - public async getHostOverview( - req: FrameworkRequest, - options: HostOverviewRequestOptions - ): Promise { - return this.adapter.getHostOverview(req, options); - } - - public async getHostFirstLastSeen( - req: FrameworkRequest, - options: HostLastFirstSeenRequestOptions - ): Promise { - return this.adapter.getHostFirstLastSeen(req, options); - } -} diff --git a/x-pack/plugins/security_solution/server/lib/hosts/mock.ts b/x-pack/plugins/security_solution/server/lib/hosts/mock.ts deleted file mode 100644 index 431a26d81254c9..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/mock.ts +++ /dev/null @@ -1,648 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DEFAULT_INDEX_PATTERN } from '../../../common/constants'; -import { Direction, HostsFields } from '../../graphql/types'; -import { - HostOverviewRequestOptions, - HostLastFirstSeenRequestOptions, - HostsRequestOptions, -} from '.'; - -export const mockGetHostsOptions: HostsRequestOptions = { - defaultIndex: DEFAULT_INDEX_PATTERN, - sourceConfiguration: { - fields: { - container: 'docker.container.name', - host: 'beat.hostname', - message: ['message', '@message'], - pod: 'kubernetes.pod.name', - tiebreaker: '_doc', - timestamp: '@timestamp', - }, - }, - timerange: { interval: '12h', to: '2019-04-09T15:37:54.610Z', from: '2019-04-08T15:37:54.610Z' }, - sort: { field: HostsFields.lastSeen, direction: Direction.asc }, - pagination: { - activePage: 0, - cursorStart: 0, - fakePossibleCount: 10, - querySize: 2, - }, - filterQuery: {}, - fields: [ - 'totalCount', - '_id', - 'host.id', - 'host.name', - 'host.os.name', - 'host.os.version', - 'edges.cursor.value', - 'pageInfo.activePage', - 'pageInfo.fakeTotalCount', - 'pageInfo.showMorePagesIndicator', - ], -}; - -export const mockGetHostsRequest = { - body: { - operationName: 'GetHostsTableQuery', - variables: { - sourceId: 'default', - timerange: { interval: '12h', from: 1554737729201, to: 1554824129202 }, - pagination: { - activePage: 0, - cursorStart: 0, - fakePossibleCount: 10, - querySize: 2, - }, - sort: { field: HostsFields.lastSeen, direction: Direction.asc }, - filterQuery: '', - }, - query: - 'query GetHostsTableQuery($sourceId: ID!, $timerange: TimerangeInput!, $pagination: PaginationInput!, $sort: HostsSortField!, $filterQuery: String) {\n source(id: $sourceId) {\n id\n Hosts(timerange: $timerange, pagination: $pagination, sort: $sort, filterQuery: $filterQuery) {\n totalCount\n edges {\n node {\n _id\n host {\n id\n name\n os {\n name\n version\n __typename\n }\n __typename\n }\n __typename\n }\n cursor {\n value\n __typename\n }\n __typename\n }\n pageInfo {\n endCursor {\n value\n __typename\n }\n hasNextPage\n __typename\n }\n __typename\n }\n __typename\n }\n}\n', - }, -}; - -export const mockGetHostsResponse = { - took: 1695, - timed_out: false, - _shards: { - total: 59, - successful: 59, - skipped: 0, - failed: 0, - }, - hits: { - total: { - value: 4018586, - relation: 'eq', - }, - max_score: null, - hits: [], - }, - aggregations: { - host_data: { - doc_count_error_upper_bound: -1, - sum_other_doc_count: 3082125, - buckets: [ - { - key: 'beats-ci-immutable-centos-7-1554823376629262884', - doc_count: 991, - lastSeen: { - value: 1554823916544, - value_as_string: '2019-04-09T15:31:56.544Z', - }, - host_os_version: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '7 (Core)', - doc_count: 991, - timestamp: { - value: 1554823916544, - value_as_string: '2019-04-09T15:31:56.544Z', - }, - }, - ], - }, - firstSeen: { - value: 1554823396740, - value_as_string: '2019-04-09T15:23:16.740Z', - }, - host_os_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'CentOS Linux', - doc_count: 991, - timestamp: { - value: 1554823916544, - value_as_string: '2019-04-09T15:31:56.544Z', - }, - }, - ], - }, - host_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'beats-ci-immutable-centos-7-1554823376629262884', - doc_count: 991, - timestamp: { - value: 1554823916544, - value_as_string: '2019-04-09T15:31:56.544Z', - }, - }, - ], - }, - host_id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'f85edea1973c34f862c376cac4ebc777', - doc_count: 991, - timestamp: { - value: 1554823916544, - value_as_string: '2019-04-09T15:31:56.544Z', - }, - }, - ], - }, - }, - { - key: 'beats-ci-immutable-centos-7-1554823376629299914', - doc_count: 571, - lastSeen: { - value: 1554823916302, - value_as_string: '2019-04-09T15:31:56.302Z', - }, - host_os_version: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '7 (Core)', - doc_count: 571, - timestamp: { - value: 1554823916302, - value_as_string: '2019-04-09T15:31:56.302Z', - }, - }, - ], - }, - firstSeen: { - value: 1554823398628, - value_as_string: '2019-04-09T15:23:18.628Z', - }, - host_os_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'CentOS Linux', - doc_count: 571, - timestamp: { - value: 1554823916302, - value_as_string: '2019-04-09T15:31:56.302Z', - }, - }, - ], - }, - host_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'beats-ci-immutable-centos-7-1554823376629299914', - doc_count: 571, - timestamp: { - value: 1554823916302, - value_as_string: '2019-04-09T15:31:56.302Z', - }, - }, - ], - }, - host_id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'f85edea1973c34f862c376cac4ebc777', - doc_count: 571, - timestamp: { - value: 1554823916302, - value_as_string: '2019-04-09T15:31:56.302Z', - }, - }, - ], - }, - }, - ], - }, - host_count: { - value: 1627, - }, - }, -}; - -export const mockGetHostsQueryDsl = { mockGetHostsQueryDsl: 'mockGetHostsQueryDsl' }; - -export const mockGetHostsResult = { - inspect: { - dsl: [JSON.stringify(mockGetHostsQueryDsl, null, 2)], - response: [JSON.stringify(mockGetHostsResponse, null, 2)], - }, - edges: [ - { - node: { - _id: 'beats-ci-immutable-centos-7-1554823376629262884', - host: { - id: 'f85edea1973c34f862c376cac4ebc777', - name: 'beats-ci-immutable-centos-7-1554823376629262884', - os: { - name: 'CentOS Linux', - version: '7 (Core)', - }, - }, - }, - cursor: { - value: 'beats-ci-immutable-centos-7-1554823376629262884', - tiebreaker: null, - }, - }, - { - node: { - _id: 'beats-ci-immutable-centos-7-1554823376629299914', - host: { - id: 'f85edea1973c34f862c376cac4ebc777', - name: 'beats-ci-immutable-centos-7-1554823376629299914', - os: { - name: 'CentOS Linux', - version: '7 (Core)', - }, - }, - }, - cursor: { - value: 'beats-ci-immutable-centos-7-1554823376629299914', - tiebreaker: null, - }, - }, - ], - totalCount: 1627, - pageInfo: { - activePage: 0, - fakeTotalCount: 10, - showMorePagesIndicator: true, - }, -}; - -export const mockGetHostOverviewOptions: HostOverviewRequestOptions = { - sourceConfiguration: { - fields: { - container: 'docker.container.name', - host: 'beat.hostname', - message: ['message', '@message'], - pod: 'kubernetes.pod.name', - tiebreaker: '_doc', - timestamp: '@timestamp', - }, - }, - timerange: { interval: '12h', to: '2019-04-09T15:37:54.610Z', from: '2019-04-08T15:37:54.610Z' }, - defaultIndex: DEFAULT_INDEX_PATTERN, - fields: [ - '_id', - 'agent.id', - 'host.architecture', - 'host.id', - 'host.ip', - 'host.mac', - 'host.name', - 'host.os.family', - 'host.os.name', - 'host.os.platform', - 'host.os.version', - 'host.os.__typename', - 'host.type', - 'host.__typename', - 'cloud.instance.id', - 'cloud.instance.__typename', - 'cloud.machine.type', - 'cloud.machine.__typename', - 'cloud.provider', - 'cloud.region', - 'cloud.__typename', - '__typename', - ], - hostName: 'siem-es', -}; - -export const mockGetHostOverviewRequest = { - body: { - operationName: 'GetHostOverviewQuery', - variables: { sourceId: 'default', hostName: 'siem-es' }, - query: - 'query GetHostOverviewQuery($sourceId: ID!, $hostName: String!, $timerange: TimerangeInput!) {\n source(id: $sourceId) {\n id\n HostOverview(hostName: $hostName, timerange: $timerange) {\n _id\n agent {\n id\n }\n host {\n architecture\n id\n ip\n mac\n name\n os {\n family\n name\n platform\n version\n __typename\n }\n type\n __typename\n }\n cloud {\n instance {\n id\n __typename\n }\n machine {\n type\n __typename\n }\n provider\n region\n __typename\n }\n __typename\n }\n __typename\n }\n}\n', - }, -}; - -export const mockGetHostOverviewResponse = { - took: 2205, - timed_out: false, - _shards: { total: 59, successful: 59, skipped: 0, failed: 0 }, - hits: { total: { value: 611894, relation: 'eq' }, max_score: null, hits: [] }, - aggregations: { - host_mac: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, - host_ip: { doc_count_error_upper_bound: 0, sum_other_doc_count: 0, buckets: [] }, - cloud_region: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'us-east-1', - doc_count: 4308, - timestamp: { value: 1556903543093, value_as_string: '2019-05-03T17:12:23.093Z' }, - }, - ], - }, - cloud_provider: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'gce', - doc_count: 432808, - timestamp: { value: 1556903543093, value_as_string: '2019-05-03T17:12:23.093Z' }, - }, - ], - }, - cloud_instance_id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '5412578377715150143', - doc_count: 432808, - timestamp: { value: 1556903543093, value_as_string: '2019-05-03T17:12:23.093Z' }, - }, - ], - }, - cloud_machine_type: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'n1-standard-1', - doc_count: 432808, - timestamp: { value: 1556903543093, value_as_string: '2019-05-03T17:12:23.093Z' }, - }, - ], - }, - host_os_version: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '9 (stretch)', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_architecture: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'x86_64', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_os_platform: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'debian', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_os_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'Debian GNU/Linux', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_os_family: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'debian', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_name: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'siem-es', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - host_id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'b6d5264e4b9c8880ad1053841067a4a6', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - agent_id: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: '9f48a9ab-749a-4ff0-b4e2-7e53910a985', - doc_count: 611894, - timestamp: { value: 1554826117972, value_as_string: '2019-04-09T16:08:37.972Z' }, - }, - ], - }, - }, -}; - -export const mockGetHostOverviewRequestDsl = { - mockGetHostOverviewRequestDsl: 'mockGetHostOverviewRequestDsl', -}; - -export const mockGetHostOverviewResult = { - inspect: { - dsl: [JSON.stringify(mockGetHostOverviewRequestDsl, null, 2)], - response: [JSON.stringify(mockGetHostOverviewResponse, null, 2)], - }, - _id: 'siem-es', - agent: { - id: '9f48a9ab-749a-4ff0-b4e2-7e53910a985', - }, - host: { - architecture: 'x86_64', - id: 'b6d5264e4b9c8880ad1053841067a4a6', - ip: [], - mac: [], - name: 'siem-es', - os: { - family: 'debian', - name: 'Debian GNU/Linux', - platform: 'debian', - version: '9 (stretch)', - }, - }, - cloud: { - instance: { - id: ['5412578377715150143'], - }, - machine: { - type: ['n1-standard-1'], - }, - provider: ['gce'], - region: ['us-east-1'], - }, - endpoint: { - endpointPolicy: 'demo', - policyStatus: 'success', - sensorVersion: '7.9.0-SNAPSHOT', - }, -}; - -export const mockGetHostLastFirstSeenOptions: HostLastFirstSeenRequestOptions = { - defaultIndex: DEFAULT_INDEX_PATTERN, - sourceConfiguration: { - fields: { - container: 'docker.container.name', - host: 'beat.hostname', - message: ['message', '@message'], - pod: 'kubernetes.pod.name', - tiebreaker: '_doc', - timestamp: '@timestamp', - }, - }, - hostName: 'siem-es', -}; - -export const mockGetHostLastFirstSeenRequest = { - body: { - operationName: 'GetHostLastFirstSeenQuery', - variables: { sourceId: 'default', hostName: 'siem-es' }, - query: - 'query GetHostLastFirstSeenQuery($sourceId: ID!, $hostName: String!) {\n source(id: $sourceId) {\n id\n HostLastFirstSeen(hostName: $hostName) {\n firstSeen\n lastSeen\n __typename\n }\n __typename\n }\n}\n', - }, -}; - -export const mockGetHostLastFirstSeenResponse = { - took: 60, - timed_out: false, - _shards: { - total: 59, - successful: 59, - skipped: 0, - failed: 0, - }, - hits: { - total: { - value: 612092, - relation: 'eq', - }, - max_score: null, - hits: [], - }, - aggregations: { - lastSeen: { - value: 1554826692178, - value_as_string: '2019-04-09T16:18:12.178Z', - }, - firstSeen: { - value: 1550806892826, - value_as_string: '2019-02-22T03:41:32.826Z', - }, - }, -}; - -export const mockGetHostLastFirstSeenDsl = { - mockGetHostLastFirstSeenDsl: 'mockGetHostLastFirstSeenDsl', -}; - -export const mockGetHostLastFirstSeenResult = { - inspect: { - dsl: [JSON.stringify(mockGetHostLastFirstSeenDsl, null, 2)], - response: [JSON.stringify(mockGetHostLastFirstSeenResponse, null, 2)], - }, - firstSeen: '2019-02-22T03:41:32.826Z', - lastSeen: '2019-04-09T16:18:12.178Z', -}; - -export const mockEndpointMetadata = { - metadata: { - '@timestamp': '2020-07-13T01:08:37.68896700Z', - Endpoint: { - policy: { - applied: { id: '3de86380-aa5a-11ea-b969-0bee1b260ab8', name: 'demo', status: 'success' }, - }, - status: 'enrolled', - }, - agent: { - build: { - original: - 'version: 7.9.0-SNAPSHOT, compiled: Thu Jul 09 07:56:12 2020, branch: 7.x, commit: 713a1071de475f15b3a1f0944d3602ed532597a5', - }, - id: 'c29e0de1-7476-480b-b242-38f0394bf6a1', - type: 'endpoint', - version: '7.9.0-SNAPSHOT', - }, - data_stream: { dataset: 'endpoint.metadata', namespace: 'default', type: 'metrics' }, - ecs: { version: '1.5.0' }, - elastic: { agent: { id: '' } }, - event: { - action: 'endpoint_metadata', - category: ['host'], - created: '2020-07-13T01:08:37.68896700Z', - dataset: 'endpoint.metadata', - id: 'Lkio+AHbZGSPFb7q++++++2E', - kind: 'metric', - module: 'endpoint', - sequence: 146, - type: ['info'], - }, - host: { - architecture: 'x86_64', - hostname: 'DESKTOP-4I1B23J', - id: 'a4148b63-1758-ab1f-a6d3-f95075cb1a9c', - ip: [ - '172.16.166.129', - 'fe80::c07e:eee9:3e8d:ea6d', - '169.254.205.96', - 'fe80::1027:b13d:a4a7:cd60', - '127.0.0.1', - '::1', - ], - mac: ['00:0c:29:89:ff:73', '3c:22:fb:3c:93:4c'], - name: 'DESKTOP-4I1B23J', - os: { - Ext: { variant: 'Windows 10 Pro' }, - family: 'windows', - full: 'Windows 10 Pro 2004 (10.0.19041.329)', - kernel: '2004 (10.0.19041.329)', - name: 'Windows', - platform: 'windows', - version: '2004 (10.0.19041.329)', - }, - }, - message: 'Endpoint metadata', - }, - host_status: 'error', -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/query.detail_host.dsl.ts b/x-pack/plugins/security_solution/server/lib/hosts/query.detail_host.dsl.ts deleted file mode 100644 index 4dd5a86e46bf61..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/query.detail_host.dsl.ts +++ /dev/null @@ -1,53 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { reduceFields } from '../../utils/build_query/reduce_fields'; -import { cloudFieldsMap, hostFieldsMap, agentFieldsMap } from '../ecs_fields'; - -import { buildFieldsTermAggregation } from './helpers'; -import { HostOverviewRequestOptions } from './types'; - -export const buildHostOverviewQuery = ({ - fields, - hostName, - defaultIndex, - sourceConfiguration: { - fields: { timestamp }, - }, - timerange: { from, to }, -}: HostOverviewRequestOptions) => { - const esFields = reduceFields(fields, { ...hostFieldsMap, ...cloudFieldsMap, ...agentFieldsMap }); - - const filter = [ - { term: { 'host.name': hostName } }, - { - range: { - [timestamp]: { - format: 'strict_date_optional_time', - gte: from, - lte: to, - }, - }, - }, - ]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - track_total_hits: false, - body: { - aggregations: { - ...buildFieldsTermAggregation(esFields.filter((field) => !['@timestamp'].includes(field))), - }, - query: { bool: { filter } }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/query.hosts.dsl.ts b/x-pack/plugins/security_solution/server/lib/hosts/query.hosts.dsl.ts deleted file mode 100644 index 16c53aa6a85eba..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/query.hosts.dsl.ts +++ /dev/null @@ -1,93 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isEmpty } from 'lodash/fp'; - -import { assertUnreachable } from '../../../common/utility_types'; -import { Direction, HostsFields, HostsSortField } from '../../graphql/types'; -import { createQueryFilterClauses } from '../../utils/build_query'; - -import { HostsRequestOptions } from '.'; - -export const buildHostsQuery = ({ - defaultIndex, - docValueFields, - fields, - filterQuery, - pagination: { querySize }, - sort, - sourceConfiguration: { - fields: { timestamp }, - }, - timerange: { from, to }, -}: HostsRequestOptions) => { - const filter = [ - ...createQueryFilterClauses(filterQuery), - { - range: { - [timestamp]: { - gte: from, - lte: to, - format: 'strict_date_optional_time', - }, - }, - }, - ]; - - const agg = { host_count: { cardinality: { field: 'host.name' } } }; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - track_total_hits: false, - body: { - ...(!isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}), - aggregations: { - ...agg, - host_data: { - terms: { size: querySize, field: 'host.name', order: getQueryOrder(sort) }, - aggs: { - lastSeen: { max: { field: '@timestamp' } }, - os: { - top_hits: { - size: 1, - sort: [ - { - '@timestamp': { - order: 'desc', - }, - }, - ], - _source: { - includes: ['host.os.*'], - }, - }, - }, - }, - }, - }, - query: { bool: { filter } }, - size: 0, - }, - }; - - return dslQuery; -}; - -type QueryOrder = { lastSeen: Direction } | { _key: Direction }; - -const getQueryOrder = (sort: HostsSortField): QueryOrder => { - switch (sort.field) { - case HostsFields.lastSeen: - return { lastSeen: sort.direction }; - case HostsFields.hostName: - return { _key: sort.direction }; - default: - return assertUnreachable(sort.field); - } -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/query.last_first_seen_host.dsl.ts b/x-pack/plugins/security_solution/server/lib/hosts/query.last_first_seen_host.dsl.ts deleted file mode 100644 index a047be8ed26745..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/query.last_first_seen_host.dsl.ts +++ /dev/null @@ -1,35 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { isEmpty } from 'lodash/fp'; -import { HostLastFirstSeenRequestOptions } from './types'; - -export const buildLastFirstSeenHostQuery = ({ - hostName, - defaultIndex, - docValueFields, -}: HostLastFirstSeenRequestOptions) => { - const filter = [{ term: { 'host.name': hostName } }]; - - const dslQuery = { - allowNoIndices: true, - index: defaultIndex, - ignoreUnavailable: true, - track_total_hits: false, - body: { - ...(!isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}), - aggregations: { - firstSeen: { min: { field: '@timestamp' } }, - lastSeen: { max: { field: '@timestamp' } }, - }, - query: { bool: { filter } }, - size: 0, - }, - }; - - return dslQuery; -}; diff --git a/x-pack/plugins/security_solution/server/lib/hosts/types.ts b/x-pack/plugins/security_solution/server/lib/hosts/types.ts deleted file mode 100644 index d18e42f606be7e..00000000000000 --- a/x-pack/plugins/security_solution/server/lib/hosts/types.ts +++ /dev/null @@ -1,129 +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 - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - FirstLastSeenHost, - HostEcsFields, - HostItem, - HostsData, - HostsSortField, - Maybe, - OsEcsFields, - SourceConfiguration, - TimerangeInput, - DocValueFieldsInput, -} from '../../graphql/types'; -import { FrameworkRequest, RequestOptionsPaginated } from '../framework'; -import { Hit, Hits, SearchHit } from '../types'; -import { TotalValue } from '../../../common/detection_engine/types'; - -export interface HostsAdapter { - getHosts(req: FrameworkRequest, options: HostsRequestOptions): Promise; - getHostOverview(req: FrameworkRequest, options: HostOverviewRequestOptions): Promise; - getHostFirstLastSeen( - req: FrameworkRequest, - options: HostLastFirstSeenRequestOptions - ): Promise; -} - -type StringOrNumber = string | number; - -export interface HostHit extends Hit { - _source: { - '@timestamp'?: string; - host: HostEcsFields; - }; - cursor?: string; - firstSeen?: string; - sort?: StringOrNumber[]; -} - -export type HostHits = Hits; - -export interface HostsRequestOptions extends RequestOptionsPaginated { - sort: HostsSortField; - defaultIndex: string[]; -} - -export interface HostLastFirstSeenRequestOptions { - hostName: string; - sourceConfiguration: SourceConfiguration; - defaultIndex: string[]; - docValueFields?: DocValueFieldsInput[]; -} - -export interface HostOverviewRequestOptions extends HostLastFirstSeenRequestOptions { - fields: string[]; - timerange: TimerangeInput; - defaultIndex: string[]; -} - -export interface HostValue { - value: number; - value_as_string: string; -} - -export interface HostBucketItem { - key: string; - doc_count: number; - timestamp: HostValue; -} - -export interface HostBuckets { - buckets: HostBucketItem[]; -} - -export interface HostOsHitsItem { - hits: { - total: TotalValue | number; - max_score: number | null; - hits: Array<{ - _source: { host: { os: Maybe } }; - sort?: [number]; - _index?: string; - _type?: string; - _id?: string; - _score?: number | null; - }>; - }; -} - -export interface HostAggEsItem { - cloud_instance_id?: HostBuckets; - cloud_machine_type?: HostBuckets; - cloud_provider?: HostBuckets; - cloud_region?: HostBuckets; - firstSeen?: HostValue; - host_architecture?: HostBuckets; - host_id?: HostBuckets; - host_ip?: HostBuckets; - host_mac?: HostBuckets; - host_name?: HostBuckets; - host_os_name?: HostBuckets; - host_os_version?: HostBuckets; - host_type?: HostBuckets; - key?: string; - lastSeen?: HostValue; - os?: HostOsHitsItem; -} - -export interface HostEsData extends SearchHit { - sort: string[]; - aggregations: { - host_count: { - value: number; - }; - host_data: { - buckets: HostAggEsItem[]; - }; - }; -} - -export interface HostAggEsData extends SearchHit { - sort: string[]; - aggregations: HostAggEsItem; -} diff --git a/x-pack/plugins/security_solution/server/lib/types.ts b/x-pack/plugins/security_solution/server/lib/types.ts index 8b2c1126e929fc..f1c7a275e162c1 100644 --- a/x-pack/plugins/security_solution/server/lib/types.ts +++ b/x-pack/plugins/security_solution/server/lib/types.ts @@ -10,7 +10,6 @@ export { ConfigType as Configuration } from '../config'; import type { SecuritySolutionRequestHandlerContext } from '../types'; import { FrameworkAdapter, FrameworkRequest } from './framework'; -import { Hosts } from './hosts'; import { IndexFields } from './index_fields'; import { SourceStatus } from './source_status'; import { Sources } from './sources'; @@ -19,11 +18,8 @@ import { PinnedEvent } from './timeline/saved_object/pinned_events'; import { Timeline } from './timeline/saved_object/timelines'; import { TotalValue, BaseHit, Explanation } from '../../common/detection_engine/types'; -export * from './hosts'; - export interface AppDomainLibs { fields: IndexFields; - hosts: Hosts; } export interface AppBackendLibs extends AppDomainLibs { @@ -142,54 +138,9 @@ export interface Hits { hits: U[]; }; } -export type SortRequestDirection = 'asc' | 'desc'; - -interface SortRequestField { - [field: string]: SortRequestDirection; -} - -export type SortRequest = SortRequestField[]; export interface MSearchHeader { index: string[] | string; allowNoIndices?: boolean; ignoreUnavailable?: boolean; } - -export interface AggregationRequest { - [aggField: string]: { - terms?: { - field?: string; - missing?: string; - size?: number; - script?: { - source: string; - lang: string; - }; - order?: { - [aggSortField: string]: SortRequestDirection; - }; - }; - max?: { - field: string; - }; - aggs?: { - [aggSortField: string]: { - [aggType: string]: { - field: string; - }; - }; - }; - top_hits?: { - size?: number; - sort?: Array<{ - [aggSortField: string]: { - order: SortRequestDirection; - }; - }>; - _source: { - includes: string[]; - }; - }; - }; -} diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts index 8b2397fd7fab07..3f4eb5721164b1 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/all/helpers.ts @@ -8,9 +8,13 @@ import { set } from '@elastic/safer-lodash-set/fp'; import { get, has, head } from 'lodash/fp'; import { hostFieldsMap } from '../../../../../../common/ecs/ecs_fields'; -import { HostsEdges } from '../../../../../../common/search_strategy/security_solution/hosts'; +import { + HostAggEsItem, + HostBuckets, + HostsEdges, + HostValue, +} from '../../../../../../common/search_strategy/security_solution/hosts'; -import { HostAggEsItem, HostBuckets, HostValue } from '../../../../../lib/hosts/types'; import { toObjectArrayOfStrings } from '../../../../helpers/to_array'; export const HOSTS_FIELDS: readonly string[] = [ diff --git a/x-pack/plugins/security_solution/server/lib/hosts/helpers.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helper.test.ts similarity index 85% rename from x-pack/plugins/security_solution/server/lib/hosts/helpers.test.ts rename to x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helper.test.ts index 90c4f195fcf083..6dd2dc3834ae80 100644 --- a/x-pack/plugins/security_solution/server/lib/hosts/helpers.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helper.test.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AggregationRequest } from '../types'; - +import { Direction } from '../../../../../../common/search_strategy/common'; +import { AggregationRequest } from '../../../../../../common/search_strategy/security_solution/hosts'; import { buildFieldsTermAggregation } from './helpers'; describe('#buildFieldsTermAggregation', () => { @@ -25,7 +25,7 @@ describe('#buildFieldsTermAggregation', () => { field: 'host.architecture', size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { @@ -41,7 +41,7 @@ describe('#buildFieldsTermAggregation', () => { field: 'host.id', size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { @@ -60,7 +60,7 @@ describe('#buildFieldsTermAggregation', () => { }, size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { @@ -76,7 +76,7 @@ describe('#buildFieldsTermAggregation', () => { field: 'host.name', size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { @@ -92,7 +92,7 @@ describe('#buildFieldsTermAggregation', () => { field: 'host.os.family', size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { @@ -108,7 +108,7 @@ describe('#buildFieldsTermAggregation', () => { field: 'host.os.name', size: 10, order: { - timestamp: 'desc', + timestamp: Direction.desc, }, }, aggs: { diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts index 2b35517d693d51..d36af619576905 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts @@ -8,11 +8,16 @@ import { set } from '@elastic/safer-lodash-set/fp'; import { get, has, head } from 'lodash/fp'; import { hostFieldsMap } from '../../../../../../common/ecs/ecs_fields'; -import { HostItem } from '../../../../../../common/search_strategy/security_solution/hosts'; +import { Direction } from '../../../../../../common/search_strategy/common'; +import { + AggregationRequest, + HostAggEsItem, + HostBuckets, + HostItem, + HostValue, +} from '../../../../../../common/search_strategy/security_solution/hosts'; import { toObjectArrayOfStrings } from '../../../../helpers/to_array'; -import { HostAggEsItem, HostBuckets, HostValue } from '../../../../../lib/hosts/types'; - export const HOST_FIELDS = [ '_id', 'host.architecture', @@ -35,6 +40,60 @@ export const HOST_FIELDS = [ 'endpoint.sensorVersion', ]; +export const buildFieldsTermAggregation = (esFields: readonly string[]): AggregationRequest => + esFields.reduce( + (res, field) => ({ + ...res, + ...getTermsAggregationTypeFromField(field), + }), + {} + ); + +const getTermsAggregationTypeFromField = (field: string): AggregationRequest => { + if (field === 'host.ip') { + return { + host_ip: { + terms: { + script: { + source: "doc['host.ip']", + lang: 'painless', + }, + size: 10, + order: { + timestamp: Direction.desc, + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, + }, + }; + } + + return { + [field.replace(/\./g, '_')]: { + terms: { + field, + size: 10, + order: { + timestamp: Direction.desc, + }, + }, + aggs: { + timestamp: { + max: { + field: '@timestamp', + }, + }, + }, + }, + }; +}; + export const formatHostItem = (bucket: HostAggEsItem): HostItem => HOST_FIELDS.reduce((flattenedFields, fieldName) => { const fieldValue = getHostFieldValue(fieldName, bucket); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.ts index f340e4d9056662..fb8296d6593b07 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/query.host_details.dsl.ts @@ -8,9 +8,8 @@ import { ISearchRequestParams } from '../../../../../../../../../src/plugins/data/common'; import { cloudFieldsMap, hostFieldsMap } from '../../../../../../common/ecs/ecs_fields'; import { HostDetailsRequestOptions } from '../../../../../../common/search_strategy/security_solution'; -import { buildFieldsTermAggregation } from '../../../../../lib/hosts/helpers'; import { reduceFields } from '../../../../../utils/build_query/reduce_fields'; -import { HOST_FIELDS } from './helpers'; +import { HOST_FIELDS, buildFieldsTermAggregation } from './helpers'; export const buildHostDetailsQuery = ({ hostName, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/__mocks__/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/__mocks__/index.ts index a6d5dcdf022b59..b492bf57f94a66 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/__mocks__/index.ts @@ -6,6 +6,7 @@ */ import { + Direction, HostFirstLastSeenRequestOptions, HostsQueries, } from '../../../../../../../common/search_strategy'; @@ -23,7 +24,7 @@ export const mockOptions: HostFirstLastSeenRequestOptions = { docValueFields: [], factoryQueryType: HostsQueries.firstOrLastSeen, hostName: 'siem-kibana', - order: 'asc', + order: Direction.asc, }; export const mockSearchStrategyFirstSeenResponse = { @@ -141,7 +142,7 @@ export const formattedSearchStrategyFirstResponse = { sort: [ { '@timestamp': { - order: 'asc', + order: Direction.asc, }, }, ], @@ -206,7 +207,7 @@ export const formattedSearchStrategyLastResponse = { sort: [ { '@timestamp': { - order: 'desc', + order: Direction.desc, }, }, ], @@ -237,6 +238,6 @@ export const expectedDsl = { _source: ['@timestamp'], query: { bool: { filter: [{ term: { 'host.name': 'siem-kibana' } }] } }, size: 1, - sort: [{ '@timestamp': { order: 'asc' } }], + sort: [{ '@timestamp': { order: Direction.asc } }], }, }; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/index.test.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/index.test.ts index d0405d829b83db..2c1100fed0f9e7 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/index.test.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/last_first_seen/index.test.ts @@ -14,7 +14,10 @@ import { formattedSearchStrategyLastResponse, formattedSearchStrategyFirstResponse, } from './__mocks__'; -import { HostFirstLastSeenRequestOptions } from '../../../../../../common/search_strategy'; +import { + Direction, + HostFirstLastSeenRequestOptions, +} from '../../../../../../common/search_strategy'; describe('firstLastSeenHost search strategy', () => { describe('first seen search strategy', () => { @@ -51,7 +54,7 @@ describe('firstLastSeenHost search strategy', () => { describe('buildDsl', () => { test('should build dsl query', () => { - const options: HostFirstLastSeenRequestOptions = { ...mockOptions, order: 'desc' }; + const options: HostFirstLastSeenRequestOptions = { ...mockOptions, order: Direction.desc }; firstOrLastSeenHost.buildDsl(options); expect(buildFirstLastSeenHostQuery).toHaveBeenCalledWith(options); }); @@ -60,7 +63,7 @@ describe('firstLastSeenHost search strategy', () => { describe('parse', () => { test('should parse data correctly', async () => { const result = await firstOrLastSeenHost.parse( - { ...mockOptions, order: 'desc' }, + { ...mockOptions, order: Direction.desc }, mockSearchStrategyLastSeenResponse ); expect(result).toMatchObject(formattedSearchStrategyLastResponse);