From 0f0a5840ddcc7103fc026594aa9e0ef30d9d49f7 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Fri, 21 Dec 2018 14:55:37 -0500 Subject: [PATCH 1/3] update type generation for graphql --- .../secops/common/graphql/typed_resolvers.ts | 81 -- x-pack/plugins/secops/common/graphql/types.ts | 1209 ----------------- .../public/components/basic_table/index.tsx | 2 +- .../components/load_more_table/index.mock.tsx | 2 +- .../page/hosts/events_table/index.tsx | 2 +- .../page/hosts/hosts_table/index.mock.ts | 2 +- .../page/hosts/hosts_table/index.tsx | 2 +- .../uncommon_process_table/index.mock.ts | 2 +- .../hosts/uncommon_process_table/index.tsx | 2 +- .../secops/public/containers/events/index.tsx | 2 +- .../secops/public/containers/hosts/index.tsx | 2 +- .../secops/public/containers/source/index.tsx | 2 +- .../containers/uncommon_processes/index.tsx | 6 +- .../public/containers/who_am_i/index.tsx | 2 +- .../graphql/introspection.json | 0 x-pack/plugins/secops/public/graphql/types.ts | 664 +++++++++ .../public/lib/compose/kibana_compose.ts | 2 +- .../secops/public/pages/hosts/index.tsx | 2 +- .../scripts/generate_types_from_graphql.js | 26 +- .../{gql_gen.json => gql_gen_client.json} | 0 .../secops/scripts/gql_gen_server.json | 23 + .../secops/server/graphql/events/resolvers.ts | 12 +- .../secops/server/graphql/hosts/hosts.mock.ts | 4 +- .../server/graphql/hosts/resolvers.test.ts | 4 +- .../secops/server/graphql/hosts/resolvers.ts | 12 +- x-pack/plugins/secops/server/graphql/index.ts | 2 +- .../server/graphql/source_status/resolvers.ts | 33 +- .../server/graphql/sources/resolvers.test.ts | 2 +- .../server/graphql/sources/resolvers.ts | 22 +- .../server/graphql/sources/source.mock.ts | 4 +- .../server/graphql/sources/sources.mock.ts | 4 +- x-pack/plugins/secops/server/graphql/types.ts | 1080 +++++++++++++++ .../uncommon_processes/resolvers.test.ts | 4 +- .../graphql/uncommon_processes/resolvers.ts | 12 +- .../uncommon_processes.mock.ts | 4 +- .../server/graphql/who_am_i/resolvers.ts | 12 +- .../lib/events/elasticsearch_adapter.ts | 2 +- .../plugins/secops/server/lib/events/index.ts | 2 +- .../plugins/secops/server/lib/events/types.ts | 2 +- .../lib/framework/kibana_framework_adapter.ts | 25 +- .../secops/server/lib/framework/types.ts | 2 +- .../server/lib/hosts/elasticsearch_adapter.ts | 2 +- .../plugins/secops/server/lib/hosts/index.ts | 2 +- .../plugins/secops/server/lib/hosts/types.ts | 2 +- .../lib/index_fields/elasticsearch_adapter.ts | 2 +- .../secops/server/lib/index_fields/index.ts | 2 +- .../secops/server/lib/index_fields/types.ts | 2 +- x-pack/plugins/secops/server/lib/types.ts | 2 +- .../elasticsearch_adapter.ts | 2 +- .../server/lib/uncommon_processes/index.ts | 2 +- .../server/lib/uncommon_processes/types.ts | 2 +- .../secops/server/utils/typed_resolvers.ts | 99 ++ .../test/api_integration/apis/secops/hosts.ts | 2 +- .../api_integration/apis/secops/sources.ts | 2 +- 54 files changed, 1985 insertions(+), 1417 deletions(-) delete mode 100644 x-pack/plugins/secops/common/graphql/typed_resolvers.ts delete mode 100644 x-pack/plugins/secops/common/graphql/types.ts rename x-pack/plugins/secops/{common => public}/graphql/introspection.json (100%) create mode 100644 x-pack/plugins/secops/public/graphql/types.ts rename x-pack/plugins/secops/scripts/{gql_gen.json => gql_gen_client.json} (100%) create mode 100644 x-pack/plugins/secops/scripts/gql_gen_server.json create mode 100644 x-pack/plugins/secops/server/graphql/types.ts create mode 100644 x-pack/plugins/secops/server/utils/typed_resolvers.ts diff --git a/x-pack/plugins/secops/common/graphql/typed_resolvers.ts b/x-pack/plugins/secops/common/graphql/typed_resolvers.ts deleted file mode 100644 index 7100801fc656..000000000000 --- a/x-pack/plugins/secops/common/graphql/typed_resolvers.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { GraphQLResolveInfo } from 'graphql'; - -// tslint:disable-next-line:no-any -type BasicResolver = ( - // tslint:disable-next-line:no-any - parent: any, - args: Args, - // tslint:disable-next-line:no-any - context: any, - info: GraphQLResolveInfo -) => Promise | Result; - -type AppResolverResult = - | Promise - | Promise<{ [P in keyof R]: () => Promise }> - | { [P in keyof R]: () => Promise } - | { [P in keyof R]: () => R[P] } - | R; - -// tslint:disable-next-line:no-any -export type AppResolvedResult = Resolver extends AppResolver - ? Result - : never; - -export type SubsetResolverWithFields = R extends BasicResolver< - Array, - infer ArgsInArray -> - ? BasicResolver< - Array>>, - ArgsInArray - > - : R extends BasicResolver - ? BasicResolver>, Args> - : never; - -export type SubsetResolverWithoutFields = R extends BasicResolver< - Array, - infer ArgsInArray -> - ? BasicResolver< - Array>>, - ArgsInArray - > - : R extends BasicResolver - ? BasicResolver>, Args> - : never; - -export type AppResolver = ( - parent: Parent, - args: Args, - context: Context, - info: GraphQLResolveInfo -) => AppResolverResult; - -export type AppResolverOf = Resolver extends BasicResolver< - infer Result, - infer Args -> - ? AppResolver - : never; - -export type AppResolverWithFields< - Resolver, - Parent, - Context, - IncludedFields extends string -> = AppResolverOf, Parent, Context>; - -export type AppResolverWithoutFields< - Resolver, - Parent, - Context, - ExcludedFields extends string -> = AppResolverOf, Parent, Context>; diff --git a/x-pack/plugins/secops/common/graphql/types.ts b/x-pack/plugins/secops/common/graphql/types.ts deleted file mode 100644 index 96dbb392b4df..000000000000 --- a/x-pack/plugins/secops/common/graphql/types.ts +++ /dev/null @@ -1,1209 +0,0 @@ -/* tslint:disable */ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { GraphQLResolveInfo } from 'graphql'; - -export type Resolver = ( - parent: Parent, - args: Args, - context: Context, - info: GraphQLResolveInfo -) => Promise | Result; - -export type SubscriptionResolver = { - subscribe( - parent: P, - args: Args, - context: Context, - info: GraphQLResolveInfo - ): AsyncIterator; - resolve?( - parent: P, - args: Args, - context: Context, - info: GraphQLResolveInfo - ): R | Result | Promise; -}; - -export interface Query { - source: Source /** Get a security data source by id */; - allSources: Source[] /** Get a list of all security data sources */; -} - -export interface Source { - id: string /** The id of the source */; - configuration: SourceConfiguration /** The raw configuration of the source */; - status: SourceStatus /** The status of the source */; - getEvents?: EventsData | null /** Gets Suricata events based on timerange and specified criteria, or all events in the timerange if no criteria is specified */; - Hosts: HostsData /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */; - UncommonProcesses: UncommonProcessesData /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */; - whoAmI?: SayMyName | null /** Just a simple example to get the app name */; -} -/** A set of configuration options for a security data source */ -export interface SourceConfiguration { - logAlias: string /** The alias to read file data from */; - auditbeatAlias: string /** The alias to read auditbeat data from */; - fields: SourceFields /** The field mapping to use for this source */; -} -/** A mapping of semantic fields to their document counterparts */ -export interface SourceFields { - container: string /** The field to identify a container by */; - host: string /** The fields to identify a host by */; - message: string[] /** The fields that may contain the log event message. The first field found win. */; - pod: string /** The field to identify a pod by */; - tiebreaker: string /** The field to use as a tiebreaker for log events that have identical timestamps */; - timestamp: string /** The field to use as a timestamp for metrics and logs */; -} -/** The status of an infrastructure data source */ -export interface SourceStatus { - auditbeatAliasExists: boolean /** Whether the configured auditbeat alias exists */; - auditbeatIndicesExist: boolean /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */; - auditbeatIndices: string[] /** The list of indices in the auditbeat alias */; - indexFields: IndexField[] /** The list of fields defined in the index mappings */; -} -/** A descriptor of a field in an index */ -export interface IndexField { - name: string /** The name of the field */; - type: string /** The type of the field's values as recognized by Kibana */; - searchable: boolean /** Whether the field's values can be efficiently searched for */; - aggregatable: boolean /** Whether the field's values can be aggregated */; -} - -export interface EventsData { - kpiEventType: KpiItem[]; - events: EventItem[]; -} - -export interface KpiItem { - value: string; - count: number; -} - -export interface EventItem { - _id?: string | null; - destination?: DestinationEcsFields | null; - event?: EventEcsFields | null; - geo?: GeoEcsFields | null; - host?: HostEcsFields | null; - source?: SourceEcsFields | null; - suricata?: SuricataEcsFields | null; - timestamp?: string | null; -} - -export interface DestinationEcsFields { - ip?: string | null; - port?: number | null; -} - -export interface EventEcsFields { - category?: string | null; - id?: number | null; - module?: string | null; - severity?: number | null; - type?: string | null; -} - -export interface GeoEcsFields { - country_iso_code?: string | null; - region_name?: string | null; -} - -export interface HostEcsFields { - hostname?: string | null; - ip?: string | null; -} - -export interface SourceEcsFields { - ip?: string | null; - port?: number | null; -} - -export interface SuricataEcsFields { - eve?: SuricataEveData | null; -} - -export interface SuricataEveData { - alert?: SuricataAlertData | null; - flow_id?: number | null; - proto?: string | null; -} - -export interface SuricataAlertData { - signature?: string | null; - signature_id?: number | null; -} - -export interface HostsData { - edges: HostsEdges[]; - totalCount: number; - pageInfo: PageInfo; -} - -export interface HostsEdges { - host: HostItem; - cursor: CursorType; -} - -export interface HostItem { - _id?: string | null; - name?: string | null; - firstSeen?: string | null; - version?: string | null; - os?: string | null; -} - -export interface CursorType { - value: string; - tiebreaker?: string | null; -} - -export interface PageInfo { - endCursor?: CursorType | null; - hasNextPage?: boolean | null; -} - -export interface UncommonProcessesData { - edges: UncommonProcessesEdges[]; - totalCount: number; - pageInfo: PageInfo; -} - -export interface UncommonProcessesEdges { - uncommonProcess: UncommonProcessItem; - cursor: CursorType; -} - -export interface UncommonProcessItem { - _id: string; - name: string; - title?: string | null; - instances: number; - hosts?: (string | null)[] | null; -} - -export interface SayMyName { - appName: string /** The id of the source */; -} - -export interface TimerangeInput { - interval: string /** 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. */; - to: number /** The end of the timerange */; - from: number /** The beginning of the timerange */; -} - -export interface PaginationInput { - limit: number /** The limit parameter allows you to configure the maximum amount of items to be returned */; - cursor?: string | null /** The cursor parameter defines the next result you want to fetch */; - tiebreaker?: - | string - | null /** The tiebreaker parameter allow to be more precise to fetch the next item */; -} -export interface SourceQueryArgs { - id: string /** The id of the source */; -} -export interface GetEventsSourceArgs { - timerange: TimerangeInput; - filterQuery?: string | null; -} -export interface HostsSourceArgs { - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; -} -export interface UncommonProcessesSourceArgs { - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; -} -export interface IndexFieldsSourceStatusArgs { - indexType?: IndexType | null; -} - -export enum IndexType { - ANY = 'ANY', - LOGS = 'LOGS', - AUDITBEAT = 'AUDITBEAT', -} - -export namespace QueryResolvers { - export interface Resolvers { - source?: SourceResolver /** Get a security data source by id */; - allSources?: AllSourcesResolver< - Source[], - any, - Context - > /** Get a list of all security data sources */; - } - - export type SourceResolver = Resolver< - R, - Parent, - Context, - SourceArgs - >; - export interface SourceArgs { - id: string /** The id of the source */; - } - - export type AllSourcesResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SourceResolvers { - export interface Resolvers { - id?: IdResolver /** The id of the source */; - configuration?: ConfigurationResolver< - SourceConfiguration, - any, - Context - > /** The raw configuration of the source */; - status?: StatusResolver /** The status of the source */; - getEvents?: GetEventsResolver< - EventsData | null, - any, - Context - > /** Gets Suricata events based on timerange and specified criteria, or all events in the timerange if no criteria is specified */; - Hosts?: HostsResolver< - HostsData, - any, - Context - > /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */; - UncommonProcesses?: UncommonProcessesResolver< - UncommonProcessesData, - any, - Context - > /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */; - whoAmI?: WhoAmIResolver< - SayMyName | null, - any, - Context - > /** Just a simple example to get the app name */; - } - - export type IdResolver = Resolver; - export type ConfigurationResolver< - R = SourceConfiguration, - Parent = any, - Context = any - > = Resolver; - export type StatusResolver = Resolver< - R, - Parent, - Context - >; - export type GetEventsResolver = Resolver< - R, - Parent, - Context, - GetEventsArgs - >; - export interface GetEventsArgs { - timerange: TimerangeInput; - filterQuery?: string | null; - } - - export type HostsResolver = Resolver< - R, - Parent, - Context, - HostsArgs - >; - export interface HostsArgs { - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; - } - - export type UncommonProcessesResolver< - R = UncommonProcessesData, - Parent = any, - Context = any - > = Resolver; - export interface UncommonProcessesArgs { - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; - } - - export type WhoAmIResolver = Resolver< - R, - Parent, - Context - >; -} -/** A set of configuration options for a security data source */ -export namespace SourceConfigurationResolvers { - export interface Resolvers { - logAlias?: LogAliasResolver /** The alias to read file data from */; - auditbeatAlias?: AuditbeatAliasResolver< - string, - any, - Context - > /** The alias to read auditbeat data from */; - fields?: FieldsResolver< - SourceFields, - any, - Context - > /** The field mapping to use for this source */; - } - - export type LogAliasResolver = Resolver< - R, - Parent, - Context - >; - export type AuditbeatAliasResolver = Resolver< - R, - Parent, - Context - >; - export type FieldsResolver = Resolver< - R, - Parent, - Context - >; -} -/** A mapping of semantic fields to their document counterparts */ -export namespace SourceFieldsResolvers { - export interface Resolvers { - container?: ContainerResolver /** The field to identify a container by */; - host?: HostResolver /** The fields to identify a host by */; - message?: MessageResolver< - string[], - any, - Context - > /** The fields that may contain the log event message. The first field found win. */; - pod?: PodResolver /** The field to identify a pod by */; - tiebreaker?: TiebreakerResolver< - string, - any, - Context - > /** The field to use as a tiebreaker for log events that have identical timestamps */; - timestamp?: TimestampResolver< - string, - any, - Context - > /** The field to use as a timestamp for metrics and logs */; - } - - export type ContainerResolver = Resolver< - R, - Parent, - Context - >; - export type HostResolver = Resolver; - export type MessageResolver = Resolver< - R, - Parent, - Context - >; - export type PodResolver = Resolver; - export type TiebreakerResolver = Resolver< - R, - Parent, - Context - >; - export type TimestampResolver = Resolver< - R, - Parent, - Context - >; -} -/** The status of an infrastructure data source */ -export namespace SourceStatusResolvers { - export interface Resolvers { - auditbeatAliasExists?: AuditbeatAliasExistsResolver< - boolean, - any, - Context - > /** Whether the configured auditbeat alias exists */; - auditbeatIndicesExist?: AuditbeatIndicesExistResolver< - boolean, - any, - Context - > /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */; - auditbeatIndices?: AuditbeatIndicesResolver< - string[], - any, - Context - > /** The list of indices in the auditbeat alias */; - indexFields?: IndexFieldsResolver< - IndexField[], - any, - Context - > /** The list of fields defined in the index mappings */; - } - - export type AuditbeatAliasExistsResolver = Resolver< - R, - Parent, - Context - >; - export type AuditbeatIndicesExistResolver = Resolver< - R, - Parent, - Context - >; - export type AuditbeatIndicesResolver = Resolver< - R, - Parent, - Context - >; - export type IndexFieldsResolver = Resolver< - R, - Parent, - Context, - IndexFieldsArgs - >; - export interface IndexFieldsArgs { - indexType?: IndexType | null; - } -} -/** A descriptor of a field in an index */ -export namespace IndexFieldResolvers { - export interface Resolvers { - name?: NameResolver /** The name of the field */; - type?: TypeResolver< - string, - any, - Context - > /** The type of the field's values as recognized by Kibana */; - searchable?: SearchableResolver< - boolean, - any, - Context - > /** Whether the field's values can be efficiently searched for */; - aggregatable?: AggregatableResolver< - boolean, - any, - Context - > /** Whether the field's values can be aggregated */; - } - - export type NameResolver = Resolver; - export type TypeResolver = Resolver; - export type SearchableResolver = Resolver< - R, - Parent, - Context - >; - export type AggregatableResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace EventsDataResolvers { - export interface Resolvers { - kpiEventType?: KpiEventTypeResolver; - events?: EventsResolver; - } - - export type KpiEventTypeResolver = Resolver< - R, - Parent, - Context - >; - export type EventsResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace KpiItemResolvers { - export interface Resolvers { - value?: ValueResolver; - count?: CountResolver; - } - - export type ValueResolver = Resolver; - export type CountResolver = Resolver; -} - -export namespace EventItemResolvers { - export interface Resolvers { - _id?: IdResolver; - destination?: DestinationResolver; - event?: EventResolver; - geo?: GeoResolver; - host?: HostResolver; - source?: SourceResolver; - suricata?: SuricataResolver; - timestamp?: TimestampResolver; - } - - export type IdResolver = Resolver< - R, - Parent, - Context - >; - export type DestinationResolver< - R = DestinationEcsFields | null, - Parent = any, - Context = any - > = Resolver; - export type EventResolver = Resolver< - R, - Parent, - Context - >; - export type GeoResolver = Resolver< - R, - Parent, - Context - >; - export type HostResolver = Resolver< - R, - Parent, - Context - >; - export type SourceResolver = Resolver< - R, - Parent, - Context - >; - export type SuricataResolver< - R = SuricataEcsFields | null, - Parent = any, - Context = any - > = Resolver; - export type TimestampResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace DestinationEcsFieldsResolvers { - export interface Resolvers { - ip?: IpResolver; - port?: PortResolver; - } - - export type IpResolver = Resolver< - R, - Parent, - Context - >; - export type PortResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace EventEcsFieldsResolvers { - export interface Resolvers { - category?: CategoryResolver; - id?: IdResolver; - module?: ModuleResolver; - severity?: SeverityResolver; - type?: TypeResolver; - } - - export type CategoryResolver = Resolver< - R, - Parent, - Context - >; - export type IdResolver = Resolver< - R, - Parent, - Context - >; - export type ModuleResolver = Resolver< - R, - Parent, - Context - >; - export type SeverityResolver = Resolver< - R, - Parent, - Context - >; - export type TypeResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace GeoEcsFieldsResolvers { - export interface Resolvers { - country_iso_code?: CountryIsoCodeResolver; - region_name?: RegionNameResolver; - } - - export type CountryIsoCodeResolver = Resolver< - R, - Parent, - Context - >; - export type RegionNameResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace HostEcsFieldsResolvers { - export interface Resolvers { - hostname?: HostnameResolver; - ip?: IpResolver; - } - - export type HostnameResolver = Resolver< - R, - Parent, - Context - >; - export type IpResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SourceEcsFieldsResolvers { - export interface Resolvers { - ip?: IpResolver; - port?: PortResolver; - } - - export type IpResolver = Resolver< - R, - Parent, - Context - >; - export type PortResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SuricataEcsFieldsResolvers { - export interface Resolvers { - eve?: EveResolver; - } - - export type EveResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SuricataEveDataResolvers { - export interface Resolvers { - alert?: AlertResolver; - flow_id?: FlowIdResolver; - proto?: ProtoResolver; - } - - export type AlertResolver = Resolver< - R, - Parent, - Context - >; - export type FlowIdResolver = Resolver< - R, - Parent, - Context - >; - export type ProtoResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SuricataAlertDataResolvers { - export interface Resolvers { - signature?: SignatureResolver; - signature_id?: SignatureIdResolver; - } - - export type SignatureResolver = Resolver< - R, - Parent, - Context - >; - export type SignatureIdResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace HostsDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - totalCount?: TotalCountResolver; - pageInfo?: PageInfoResolver; - } - - export type EdgesResolver = Resolver< - R, - Parent, - Context - >; - export type TotalCountResolver = Resolver< - R, - Parent, - Context - >; - export type PageInfoResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace HostsEdgesResolvers { - export interface Resolvers { - host?: HostResolver; - cursor?: CursorResolver; - } - - export type HostResolver = Resolver< - R, - Parent, - Context - >; - export type CursorResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace HostItemResolvers { - export interface Resolvers { - _id?: IdResolver; - name?: NameResolver; - firstSeen?: FirstSeenResolver; - version?: VersionResolver; - os?: OsResolver; - } - - export type IdResolver = Resolver< - R, - Parent, - Context - >; - export type NameResolver = Resolver< - R, - Parent, - Context - >; - export type FirstSeenResolver = Resolver< - R, - Parent, - Context - >; - export type VersionResolver = Resolver< - R, - Parent, - Context - >; - export type OsResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace CursorTypeResolvers { - export interface Resolvers { - value?: ValueResolver; - tiebreaker?: TiebreakerResolver; - } - - export type ValueResolver = Resolver; - export type TiebreakerResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace PageInfoResolvers { - export interface Resolvers { - endCursor?: EndCursorResolver; - hasNextPage?: HasNextPageResolver; - } - - export type EndCursorResolver = Resolver< - R, - Parent, - Context - >; - export type HasNextPageResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace UncommonProcessesDataResolvers { - export interface Resolvers { - edges?: EdgesResolver; - totalCount?: TotalCountResolver; - pageInfo?: PageInfoResolver; - } - - export type EdgesResolver = Resolver< - R, - Parent, - Context - >; - export type TotalCountResolver = Resolver< - R, - Parent, - Context - >; - export type PageInfoResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace UncommonProcessesEdgesResolvers { - export interface Resolvers { - uncommonProcess?: UncommonProcessResolver; - cursor?: CursorResolver; - } - - export type UncommonProcessResolver< - R = UncommonProcessItem, - Parent = any, - Context = any - > = Resolver; - export type CursorResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace UncommonProcessItemResolvers { - export interface Resolvers { - _id?: IdResolver; - name?: NameResolver; - title?: TitleResolver; - instances?: InstancesResolver; - hosts?: HostsResolver<(string | null)[] | null, any, Context>; - } - - export type IdResolver = Resolver; - export type NameResolver = Resolver; - export type TitleResolver = Resolver< - R, - Parent, - Context - >; - export type InstancesResolver = Resolver< - R, - Parent, - Context - >; - export type HostsResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace SayMyNameResolvers { - export interface Resolvers { - appName?: AppNameResolver /** The id of the source */; - } - - export type AppNameResolver = Resolver< - R, - Parent, - Context - >; -} - -export namespace GetEventsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - filterQuery?: string | null; - }; - - export type Query = { - __typename?: 'Query'; - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - id: string; - getEvents?: GetEvents | null; - }; - - export type GetEvents = { - __typename?: 'EventsData'; - events: Events[]; - kpiEventType: KpiEventType[]; - }; - - export type Events = { - __typename?: 'EventItem'; - _id?: string | null; - timestamp?: string | null; - event?: Event | null; - host?: Host | null; - source?: _Source | null; - destination?: Destination | null; - geo?: Geo | null; - suricata?: Suricata | null; - }; - - export type Event = { - __typename?: 'EventEcsFields'; - type?: string | null; - severity?: number | null; - module?: string | null; - category?: string | null; - id?: number | null; - }; - - export type Host = { - __typename?: 'HostEcsFields'; - hostname?: string | null; - ip?: string | null; - }; - - export type _Source = { - __typename?: 'SourceEcsFields'; - ip?: string | null; - port?: number | null; - }; - - export type Destination = { - __typename?: 'DestinationEcsFields'; - ip?: string | null; - port?: number | null; - }; - - export type Geo = { - __typename?: 'GeoEcsFields'; - region_name?: string | null; - country_iso_code?: string | null; - }; - - export type Suricata = { - __typename?: 'SuricataEcsFields'; - eve?: Eve | null; - }; - - export type Eve = { - __typename?: 'SuricataEveData'; - proto?: string | null; - flow_id?: number | null; - alert?: Alert | null; - }; - - export type Alert = { - __typename?: 'SuricataAlertData'; - signature?: string | null; - signature_id?: number | null; - }; - - export type KpiEventType = { - __typename?: 'KpiItem'; - value: string; - count: number; - }; -} - -export namespace GetHostsQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; - }; - - 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; - }; - - export type Edges = { - __typename?: 'HostsEdges'; - host: Host; - cursor: Cursor; - }; - - export type Host = { - __typename?: 'HostItem'; - _id?: string | null; - name?: string | null; - os?: string | null; - version?: string | null; - firstSeen?: string | null; - }; - - export type Cursor = { - __typename?: 'CursorType'; - value: string; - }; - - export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: EndCursor | null; - hasNextPage?: boolean | null; - }; - - export type EndCursor = { - __typename?: 'CursorType'; - value: string; - }; -} - -export namespace SourceQuery { - export type Variables = { - sourceId?: string | null; - }; - - export type Query = { - __typename?: 'Query'; - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - id: string; - configuration: Configuration; - status: Status; - }; - - export type Configuration = { - __typename?: 'SourceConfiguration'; - auditbeatAlias: string; - logAlias: string; - }; - - export type Status = { - __typename?: 'SourceStatus'; - auditbeatIndicesExist: boolean; - auditbeatAliasExists: boolean; - auditbeatIndices: string[]; - indexFields: IndexFields[]; - }; - - export type IndexFields = { - __typename?: 'IndexField'; - name: string; - searchable: boolean; - type: string; - aggregatable: boolean; - }; -} - -export namespace GetUncommonProcessesQuery { - export type Variables = { - sourceId: string; - timerange: TimerangeInput; - pagination: PaginationInput; - filterQuery?: string | null; - }; - - export type Query = { - __typename?: 'Query'; - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - id: string; - UncommonProcesses: UncommonProcesses; - }; - - export type UncommonProcesses = { - __typename?: 'UncommonProcessesData'; - totalCount: number; - edges: Edges[]; - pageInfo: PageInfo; - }; - - export type Edges = { - __typename?: 'UncommonProcessesEdges'; - uncommonProcess: UncommonProcess; - cursor: Cursor; - }; - - export type UncommonProcess = { - __typename?: 'UncommonProcessItem'; - _id: string; - name: string; - title?: string | null; - instances: number; - hosts?: (string | null)[] | null; - }; - - export type Cursor = { - __typename?: 'CursorType'; - value: string; - }; - - export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: EndCursor | null; - hasNextPage?: boolean | null; - }; - - export type EndCursor = { - __typename?: 'CursorType'; - value: string; - }; -} - -export namespace WhoAmIQuery { - export type Variables = { - sourceId: string; - }; - - export type Query = { - __typename?: 'Query'; - source: Source; - }; - - export type Source = { - __typename?: 'Source'; - whoAmI?: WhoAmI | null; - }; - - export type WhoAmI = { - __typename?: 'SayMyName'; - appName: string; - }; -} diff --git a/x-pack/plugins/secops/public/components/basic_table/index.tsx b/x-pack/plugins/secops/public/components/basic_table/index.tsx index 55d5332c3b84..60eb7286bc98 100644 --- a/x-pack/plugins/secops/public/components/basic_table/index.tsx +++ b/x-pack/plugins/secops/public/components/basic_table/index.tsx @@ -8,7 +8,7 @@ import { EuiBasicTable, EuiTitle } from '@elastic/eui'; import React from 'react'; import styled from 'styled-components'; -import { EventItem } from '../../../common/graphql/types'; +import { EventItem } from '../../graphql/types'; import { LoadingPanel } from '../loading'; interface BasicTableProps { diff --git a/x-pack/plugins/secops/public/components/load_more_table/index.mock.tsx b/x-pack/plugins/secops/public/components/load_more_table/index.mock.tsx index ae1ff90731c0..f3b7d78d8516 100644 --- a/x-pack/plugins/secops/public/components/load_more_table/index.mock.tsx +++ b/x-pack/plugins/secops/public/components/load_more_table/index.mock.tsx @@ -6,7 +6,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; -import { HostItem } from '../../../common/graphql/types'; +import { HostItem } from '../../graphql/types'; import { ItemsPerRow } from './index'; export const mockData = { diff --git a/x-pack/plugins/secops/public/components/page/hosts/events_table/index.tsx b/x-pack/plugins/secops/public/components/page/hosts/events_table/index.tsx index db6f79f02542..b1e11e14f79b 100644 --- a/x-pack/plugins/secops/public/components/page/hosts/events_table/index.tsx +++ b/x-pack/plugins/secops/public/components/page/hosts/events_table/index.tsx @@ -7,8 +7,8 @@ import { getOr, noop } from 'lodash/fp'; import React from 'react'; import { pure } from 'recompose'; -import { EventItem } from '../../../../../common/graphql/types'; import { EventsQuery } from '../../../../containers/events'; +import { EventItem } from '../../../../graphql/types'; import { BasicTable } from '../../../basic_table'; import { DragEffects, DraggableWrapper } from '../../../drag_and_drop/draggable_wrapper'; import { Provider } from '../../../timeline/data_providers/provider'; diff --git a/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.mock.ts b/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.mock.ts index 7b3465323599..42dfd64e0f05 100644 --- a/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.mock.ts +++ b/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.mock.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HostsData } from '../../../../../common/graphql/types'; +import { HostsData } from '../../../../graphql/types'; export const mockData: { Hosts: HostsData } = { Hosts: { diff --git a/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.tsx b/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.tsx index 20b7e10f4e4a..e0b4a86deebc 100644 --- a/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.tsx +++ b/x-pack/plugins/secops/public/components/page/hosts/hosts_table/index.tsx @@ -9,7 +9,7 @@ import { defaultTo } from 'lodash/fp'; import React from 'react'; import { connect } from 'react-redux'; import { pure } from 'recompose'; -import { HostItem, HostsEdges } from '../../../../../common/graphql/types'; +import { HostItem, HostsEdges } from '../../../../graphql/types'; import { hostsActions, hostsLimitSelector, State } from '../../../../store'; import { ItemsPerRow, LoadMoreTable } from '../../../load_more_table'; diff --git a/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.mock.ts b/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.mock.ts index 87dae8b5e329..6d4c4f5d4657 100644 --- a/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.mock.ts +++ b/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.mock.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UncommonProcessesData } from '../../../../../common/graphql/types'; +import { UncommonProcessesData } from '../../../../graphql/types'; export const mockData: { UncommonProcess: UncommonProcessesData } = { UncommonProcess: { diff --git a/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.tsx b/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.tsx index 374a7e3805a5..f44b438572d4 100644 --- a/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.tsx +++ b/x-pack/plugins/secops/public/components/page/hosts/uncommon_process_table/index.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { connect } from 'react-redux'; import { pure } from 'recompose'; -import { UncommonProcessesEdges, UncommonProcessItem } from '../../../../../common/graphql/types'; +import { UncommonProcessesEdges, UncommonProcessItem } from '../../../../graphql/types'; import { hostsActions, State, uncommonProcessesLimitSelector } from '../../../../store'; import { ItemsPerRow, LoadMoreTable } from '../../../load_more_table'; diff --git a/x-pack/plugins/secops/public/containers/events/index.tsx b/x-pack/plugins/secops/public/containers/events/index.tsx index c82fcd9dcca0..05fb734a168d 100644 --- a/x-pack/plugins/secops/public/containers/events/index.tsx +++ b/x-pack/plugins/secops/public/containers/events/index.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { Query } from 'react-apollo'; import { pure } from 'recompose'; -import { EventItem, GetEventsQuery, KpiItem } from '../../../common/graphql/types'; +import { EventItem, GetEventsQuery, KpiItem } from '../../graphql/types'; import { inputsModel } from '../../store'; import { eventsQuery } from './index.gql_query'; diff --git a/x-pack/plugins/secops/public/containers/hosts/index.tsx b/x-pack/plugins/secops/public/containers/hosts/index.tsx index 69c516290777..80fd1df1f51e 100644 --- a/x-pack/plugins/secops/public/containers/hosts/index.tsx +++ b/x-pack/plugins/secops/public/containers/hosts/index.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { Query } from 'react-apollo'; import { pure } from 'recompose'; -import { GetHostsQuery, HostsEdges, PageInfo } from '../../../common/graphql/types'; +import { GetHostsQuery, HostsEdges, PageInfo } from '../../graphql/types'; import { connect } from 'react-redux'; import { hostsLimitSelector, inputsModel, State } from '../../store'; diff --git a/x-pack/plugins/secops/public/containers/source/index.tsx b/x-pack/plugins/secops/public/containers/source/index.tsx index 6ad8cade7b86..f1aa64755a4f 100644 --- a/x-pack/plugins/secops/public/containers/source/index.tsx +++ b/x-pack/plugins/secops/public/containers/source/index.tsx @@ -8,7 +8,7 @@ import { get } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { SourceQuery } from '../../../common/graphql/types'; +import { SourceQuery } from '../../graphql/types'; import { sourceQuery } from './index.gql_query'; interface WithSourceArgs { diff --git a/x-pack/plugins/secops/public/containers/uncommon_processes/index.tsx b/x-pack/plugins/secops/public/containers/uncommon_processes/index.tsx index 429fe98c8b5c..c751f8ec9d49 100644 --- a/x-pack/plugins/secops/public/containers/uncommon_processes/index.tsx +++ b/x-pack/plugins/secops/public/containers/uncommon_processes/index.tsx @@ -9,11 +9,7 @@ import React from 'react'; import { Query } from 'react-apollo'; import { pure } from 'recompose'; -import { - GetUncommonProcessesQuery, - PageInfo, - UncommonProcessesEdges, -} from '../../../common/graphql/types'; +import { GetUncommonProcessesQuery, PageInfo, UncommonProcessesEdges } from '../../graphql/types'; import { connect } from 'react-redux'; import { inputsModel, State } from '../../store'; diff --git a/x-pack/plugins/secops/public/containers/who_am_i/index.tsx b/x-pack/plugins/secops/public/containers/who_am_i/index.tsx index c8553d7672a2..f8a67496adbc 100644 --- a/x-pack/plugins/secops/public/containers/who_am_i/index.tsx +++ b/x-pack/plugins/secops/public/containers/who_am_i/index.tsx @@ -8,7 +8,7 @@ import { getOr } from 'lodash/fp'; import React from 'react'; import { Query } from 'react-apollo'; -import { WhoAmIQuery } from '../../../common/graphql/types'; +import { WhoAmIQuery } from '../../graphql/types'; import { whoAmIQuery } from './index.gql_query'; diff --git a/x-pack/plugins/secops/common/graphql/introspection.json b/x-pack/plugins/secops/public/graphql/introspection.json similarity index 100% rename from x-pack/plugins/secops/common/graphql/introspection.json rename to x-pack/plugins/secops/public/graphql/introspection.json diff --git a/x-pack/plugins/secops/public/graphql/types.ts b/x-pack/plugins/secops/public/graphql/types.ts new file mode 100644 index 000000000000..da94d9724d9e --- /dev/null +++ b/x-pack/plugins/secops/public/graphql/types.ts @@ -0,0 +1,664 @@ +/* tslint:disable */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// ==================================================== +// START: Typescript template +// ==================================================== + +// ==================================================== +// Types +// ==================================================== + +export interface Query { + /** Get a security data source by id */ + source: Source; + /** Get a list of all security data sources */ + allSources: Source[]; +} + +export interface Source { + /** The id of the source */ + id: string; + /** The raw configuration of the source */ + configuration: SourceConfiguration; + /** The status of the source */ + status: SourceStatus; + /** Gets Suricata events based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + getEvents?: EventsData | null; + /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + Hosts: HostsData; + /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ + UncommonProcesses: UncommonProcessesData; + /** Just a simple example to get the app name */ + whoAmI?: SayMyName | null; +} +/** A set of configuration options for a security data source */ +export interface SourceConfiguration { + /** The alias to read file data from */ + logAlias: string; + /** The alias to read auditbeat data from */ + auditbeatAlias: string; + /** The field mapping to use for this source */ + fields: SourceFields; +} +/** A mapping of semantic fields to their document counterparts */ +export interface SourceFields { + /** The field to identify a container by */ + container: string; + /** The fields to identify a host by */ + host: string; + /** The fields that may contain the log event message. The first field found win. */ + message: string[]; + /** The field to identify a pod by */ + pod: string; + /** The field to use as a tiebreaker for log events that have identical timestamps */ + tiebreaker: string; + /** The field to use as a timestamp for metrics and logs */ + timestamp: string; +} +/** The status of an infrastructure data source */ +export interface SourceStatus { + /** Whether the configured auditbeat alias exists */ + auditbeatAliasExists: boolean; + /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ + auditbeatIndicesExist: boolean; + /** The list of indices in the auditbeat alias */ + auditbeatIndices: string[]; + /** The list of fields defined in the index mappings */ + indexFields: IndexField[]; +} +/** A descriptor of a field in an index */ +export interface IndexField { + /** The name of the field */ + name: string; + /** The type of the field's values as recognized by Kibana */ + type: string; + /** Whether the field's values can be efficiently searched for */ + searchable: boolean; + /** Whether the field's values can be aggregated */ + aggregatable: boolean; +} + +export interface EventsData { + kpiEventType: KpiItem[]; + + events: EventItem[]; +} + +export interface KpiItem { + value: string; + + count: number; +} + +export interface EventItem { + _id?: string | null; + + destination?: DestinationEcsFields | null; + + event?: EventEcsFields | null; + + geo?: GeoEcsFields | null; + + host?: HostEcsFields | null; + + source?: SourceEcsFields | null; + + suricata?: SuricataEcsFields | null; + + timestamp?: string | null; +} + +export interface DestinationEcsFields { + ip?: string | null; + + port?: number | null; +} + +export interface EventEcsFields { + category?: string | null; + + id?: number | null; + + module?: string | null; + + severity?: number | null; + + type?: string | null; +} + +export interface GeoEcsFields { + country_iso_code?: string | null; + + region_name?: string | null; +} + +export interface HostEcsFields { + hostname?: string | null; + + ip?: string | null; +} + +export interface SourceEcsFields { + ip?: string | null; + + port?: number | null; +} + +export interface SuricataEcsFields { + eve?: SuricataEveData | null; +} + +export interface SuricataEveData { + alert?: SuricataAlertData | null; + + flow_id?: number | null; + + proto?: string | null; +} + +export interface SuricataAlertData { + signature?: string | null; + + signature_id?: number | null; +} + +export interface HostsData { + edges: HostsEdges[]; + + totalCount: number; + + pageInfo: PageInfo; +} + +export interface HostsEdges { + host: HostItem; + + cursor: CursorType; +} + +export interface HostItem { + _id?: string | null; + + name?: string | null; + + firstSeen?: string | null; + + version?: string | null; + + os?: string | null; +} + +export interface CursorType { + value: string; + + tiebreaker?: string | null; +} + +export interface PageInfo { + endCursor?: CursorType | null; + + hasNextPage?: boolean | null; +} + +export interface UncommonProcessesData { + edges: UncommonProcessesEdges[]; + + totalCount: number; + + pageInfo: PageInfo; +} + +export interface UncommonProcessesEdges { + uncommonProcess: UncommonProcessItem; + + cursor: CursorType; +} + +export interface UncommonProcessItem { + _id: string; + + name: string; + + title?: string | null; + + instances: number; + + hosts?: (string | null)[] | null; +} + +export interface SayMyName { + /** The id of the source */ + appName: string; +} + +// ==================================================== +// InputTypes +// ==================================================== + +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: number; + /** The beginning of the timerange */ + from: number; +} + +export interface PaginationInput { + /** The limit parameter allows you to configure the maximum amount of items to be returned */ + limit: number; + /** The cursor parameter defines the next result you want to fetch */ + cursor?: string | null; + /** The tiebreaker parameter allow to be more precise to fetch the next item */ + tiebreaker?: string | null; +} + +// ==================================================== +// Arguments +// ==================================================== + +export interface SourceQueryArgs { + /** The id of the source */ + id: string; +} +export interface GetEventsSourceArgs { + timerange: TimerangeInput; + + filterQuery?: string | null; +} +export interface HostsSourceArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; +} +export interface UncommonProcessesSourceArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; +} +export interface IndexFieldsSourceStatusArgs { + indexType?: IndexType | null; +} + +// ==================================================== +// Enums +// ==================================================== + +export enum IndexType { + ANY = 'ANY', + LOGS = 'LOGS', + AUDITBEAT = 'AUDITBEAT', +} + +// ==================================================== +// END: Typescript template +// ==================================================== + +// ==================================================== +// Documents +// ==================================================== + +export namespace GetEventsQuery { + export type Variables = { + sourceId: string; + timerange: TimerangeInput; + filterQuery?: string | null; + }; + + export type Query = { + __typename?: 'Query'; + + source: Source; + }; + + export type Source = { + __typename?: 'Source'; + + id: string; + + getEvents?: GetEvents | null; + }; + + export type GetEvents = { + __typename?: 'EventsData'; + + events: Events[]; + + kpiEventType: KpiEventType[]; + }; + + export type Events = { + __typename?: 'EventItem'; + + _id?: string | null; + + timestamp?: string | null; + + event?: Event | null; + + host?: Host | null; + + source?: _Source | null; + + destination?: Destination | null; + + geo?: Geo | null; + + suricata?: Suricata | null; + }; + + export type Event = { + __typename?: 'EventEcsFields'; + + type?: string | null; + + severity?: number | null; + + module?: string | null; + + category?: string | null; + + id?: number | null; + }; + + export type Host = { + __typename?: 'HostEcsFields'; + + hostname?: string | null; + + ip?: string | null; + }; + + export type _Source = { + __typename?: 'SourceEcsFields'; + + ip?: string | null; + + port?: number | null; + }; + + export type Destination = { + __typename?: 'DestinationEcsFields'; + + ip?: string | null; + + port?: number | null; + }; + + export type Geo = { + __typename?: 'GeoEcsFields'; + + region_name?: string | null; + + country_iso_code?: string | null; + }; + + export type Suricata = { + __typename?: 'SuricataEcsFields'; + + eve?: Eve | null; + }; + + export type Eve = { + __typename?: 'SuricataEveData'; + + proto?: string | null; + + flow_id?: number | null; + + alert?: Alert | null; + }; + + export type Alert = { + __typename?: 'SuricataAlertData'; + + signature?: string | null; + + signature_id?: number | null; + }; + + export type KpiEventType = { + __typename?: 'KpiItem'; + + value: string; + + count: number; + }; +} + +export namespace GetHostsQuery { + export type Variables = { + sourceId: string; + timerange: TimerangeInput; + pagination: PaginationInput; + filterQuery?: string | null; + }; + + 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; + }; + + export type Edges = { + __typename?: 'HostsEdges'; + + host: Host; + + cursor: Cursor; + }; + + export type Host = { + __typename?: 'HostItem'; + + _id?: string | null; + + name?: string | null; + + os?: string | null; + + version?: string | null; + + firstSeen?: string | null; + }; + + export type Cursor = { + __typename?: 'CursorType'; + + value: string; + }; + + export type PageInfo = { + __typename?: 'PageInfo'; + + endCursor?: EndCursor | null; + + hasNextPage?: boolean | null; + }; + + export type EndCursor = { + __typename?: 'CursorType'; + + value: string; + }; +} + +export namespace SourceQuery { + export type Variables = { + sourceId?: string | null; + }; + + export type Query = { + __typename?: 'Query'; + + source: Source; + }; + + export type Source = { + __typename?: 'Source'; + + id: string; + + configuration: Configuration; + + status: Status; + }; + + export type Configuration = { + __typename?: 'SourceConfiguration'; + + auditbeatAlias: string; + + logAlias: string; + }; + + export type Status = { + __typename?: 'SourceStatus'; + + auditbeatIndicesExist: boolean; + + auditbeatAliasExists: boolean; + + auditbeatIndices: string[]; + + indexFields: IndexFields[]; + }; + + export type IndexFields = { + __typename?: 'IndexField'; + + name: string; + + searchable: boolean; + + type: string; + + aggregatable: boolean; + }; +} + +export namespace GetUncommonProcessesQuery { + export type Variables = { + sourceId: string; + timerange: TimerangeInput; + pagination: PaginationInput; + filterQuery?: string | null; + }; + + export type Query = { + __typename?: 'Query'; + + source: Source; + }; + + export type Source = { + __typename?: 'Source'; + + id: string; + + UncommonProcesses: UncommonProcesses; + }; + + export type UncommonProcesses = { + __typename?: 'UncommonProcessesData'; + + totalCount: number; + + edges: Edges[]; + + pageInfo: PageInfo; + }; + + export type Edges = { + __typename?: 'UncommonProcessesEdges'; + + uncommonProcess: UncommonProcess; + + cursor: Cursor; + }; + + export type UncommonProcess = { + __typename?: 'UncommonProcessItem'; + + _id: string; + + name: string; + + title?: string | null; + + instances: number; + + hosts?: (string | null)[] | null; + }; + + export type Cursor = { + __typename?: 'CursorType'; + + value: string; + }; + + export type PageInfo = { + __typename?: 'PageInfo'; + + endCursor?: EndCursor | null; + + hasNextPage?: boolean | null; + }; + + export type EndCursor = { + __typename?: 'CursorType'; + + value: string; + }; +} + +export namespace WhoAmIQuery { + export type Variables = { + sourceId: string; + }; + + export type Query = { + __typename?: 'Query'; + + source: Source; + }; + + export type Source = { + __typename?: 'Source'; + + whoAmI?: WhoAmI | null; + }; + + export type WhoAmI = { + __typename?: 'SayMyName'; + + appName: string; + }; +} diff --git a/x-pack/plugins/secops/public/lib/compose/kibana_compose.ts b/x-pack/plugins/secops/public/lib/compose/kibana_compose.ts index 5aa9c3c22066..15e95d8ebac6 100644 --- a/x-pack/plugins/secops/public/lib/compose/kibana_compose.ts +++ b/x-pack/plugins/secops/public/lib/compose/kibana_compose.ts @@ -15,7 +15,7 @@ import { timezoneProvider } from 'ui/vis/lib/timezone'; import { AppKibanaObservableApiAdapter } from '../adapters/observable_api/kibana_observable_api'; -import introspectionQueryResultData from '../../../common/graphql/introspection.json'; +import introspectionQueryResultData from '../../graphql/introspection.json'; import { AppKibanaFrameworkAdapter } from '../adapters/framework/kibana_framework_adapter'; import { AppFrontendLibs } from '../lib'; diff --git a/x-pack/plugins/secops/public/pages/hosts/index.tsx b/x-pack/plugins/secops/public/pages/hosts/index.tsx index 7fe2a0e9234d..0fcae8380449 100644 --- a/x-pack/plugins/secops/public/pages/hosts/index.tsx +++ b/x-pack/plugins/secops/public/pages/hosts/index.tsx @@ -9,7 +9,6 @@ import React from 'react'; import { pure } from 'recompose'; import chrome from 'ui/chrome'; -import { KpiItem } from '../../../common/graphql/types'; import { EmptyPage } from '../../components/empty_page'; import { EventsTable, @@ -17,6 +16,7 @@ import { TypesBar, UncommonProcessTable, } from '../../components/page/hosts'; +import { KpiItem } from '../../graphql/types'; import { manageQuery } from '../../components/page/manage_query'; import { EventsQuery } from '../../containers/events'; diff --git a/x-pack/plugins/secops/scripts/generate_types_from_graphql.js b/x-pack/plugins/secops/scripts/generate_types_from_graphql.js index f36979c15937..8466bd5d7ba7 100644 --- a/x-pack/plugins/secops/scripts/generate_types_from_graphql.js +++ b/x-pack/plugins/secops/scripts/generate_types_from_graphql.js @@ -10,19 +10,20 @@ const { generate } = require('graphql-code-generator'); const GRAPHQL_GLOBS = [ join('public', 'containers', '**', '*.gql_query.ts{,x}'), - join('public', 'store', '**', '*.gql_query.ts{,x}'), join('common', 'graphql', '**', '*.gql_query.ts{,x}'), ]; -const CONFIG_PATH = resolve(__dirname, 'gql_gen.json'); -const OUTPUT_INTROSPECTION_PATH = resolve('common', 'graphql', 'introspection.json'); -const OUTPUT_TYPES_PATH = resolve('common', 'graphql', 'types.ts'); +const CLIENT_CONFIG_PATH = resolve(__dirname, 'gql_gen_client.json'); +const SERVER_CONFIG_PATH = resolve(__dirname, 'gql_gen_server.json'); +const OUTPUT_INTROSPECTION_PATH = resolve('public', 'graphql', 'introspection.json'); +const OUTPUT_CLIENT_TYPES_PATH = resolve('public', 'graphql', 'types.ts'); +const OUTPUT_SERVER_TYPES_PATH = resolve('server', 'graphql', 'types.ts'); const SCHEMA_PATH = resolve(__dirname, 'combined_schema.ts'); async function main() { await generate( { args: GRAPHQL_GLOBS, - config: CONFIG_PATH, + config: SERVER_CONFIG_PATH, out: OUTPUT_INTROSPECTION_PATH, overwrite: true, require: ['ts-node/register'], @@ -34,14 +35,25 @@ async function main() { await generate( { args: GRAPHQL_GLOBS, - config: CONFIG_PATH, - out: OUTPUT_TYPES_PATH, + config: CLIENT_CONFIG_PATH, + out: OUTPUT_CLIENT_TYPES_PATH, overwrite: true, schema: SCHEMA_PATH, template: 'graphql-codegen-typescript-template', }, true ); + await generate( + { + args: [], + config: SERVER_CONFIG_PATH, + out: OUTPUT_SERVER_TYPES_PATH, + overwrite: true, + schema: SCHEMA_PATH, + template: 'graphql-codegen-typescript-resolvers-template', + }, + true + ); } if (require.main === module) { diff --git a/x-pack/plugins/secops/scripts/gql_gen.json b/x-pack/plugins/secops/scripts/gql_gen_client.json similarity index 100% rename from x-pack/plugins/secops/scripts/gql_gen.json rename to x-pack/plugins/secops/scripts/gql_gen_client.json diff --git a/x-pack/plugins/secops/scripts/gql_gen_server.json b/x-pack/plugins/secops/scripts/gql_gen_server.json new file mode 100644 index 000000000000..603b62ff5b37 --- /dev/null +++ b/x-pack/plugins/secops/scripts/gql_gen_server.json @@ -0,0 +1,23 @@ +{ + "flattenTypes": true, + "generatorConfig": { + "contextType": "SecOpsContext", + "prepend": [ + "/*", + " * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one", + " * or more contributor license agreements. Licensed under the Elastic License;", + " * you may not use this file except in compliance with the Elastic License.", + " */", + "", + "import { SecOpsContext } from '../lib/types';" + ] + }, + "primitives": { + "String": "string", + "Int": "number", + "Float": "number", + "Boolean": "boolean", + "ID": "string" + } +} + diff --git a/x-pack/plugins/secops/server/graphql/events/resolvers.ts b/x-pack/plugins/secops/server/graphql/events/resolvers.ts index 3f61fc406716..a0282c5c6121 100644 --- a/x-pack/plugins/secops/server/graphql/events/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/events/resolvers.ts @@ -4,19 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SourceResolvers } from '../../../common/graphql/types'; +import { SourceResolvers } from '../../graphql/types'; import { Events } from '../../lib/events'; import { EventsRequestOptions } from '../../lib/events/types'; -import { AppResolvedResult, AppResolverOf } from '../../lib/framework'; -import { Context } from '../../lib/types'; +import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { getFields } from '../../utils/build_query/fields'; import { parseFilterQuery } from '../../utils/serialized_query'; import { QuerySourceResolver } from '../sources/resolvers'; -type QueryEventsResolver = AppResolverOf< - SourceResolvers.GetEventsResolver, - AppResolvedResult, - Context +type QueryEventsResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; interface EventsResolversDeps { diff --git a/x-pack/plugins/secops/server/graphql/hosts/hosts.mock.ts b/x-pack/plugins/secops/server/graphql/hosts/hosts.mock.ts index d7d3a2eae4f8..aa42b682755c 100644 --- a/x-pack/plugins/secops/server/graphql/hosts/hosts.mock.ts +++ b/x-pack/plugins/secops/server/graphql/hosts/hosts.mock.ts @@ -6,7 +6,7 @@ import { FieldNode } from 'graphql'; import { Logger } from '../../utils/logger'; -import { Context } from '../index'; +import { SecOpsContext } from '../index'; /* tslint:disable */ export const mockHostsData = { @@ -49,7 +49,7 @@ export const mockHostsData = { /* tslint:enable */ export const getHostsQueryMock = (logger: Logger) => ({ - source: (root: unknown, args: unknown, context: Context) => { + source: (root: unknown, args: unknown, context: SecOpsContext) => { logger.info('Mock source'); const operationName = context.req.payload.operationName.toLowerCase(); switch (operationName) { diff --git a/x-pack/plugins/secops/server/graphql/hosts/resolvers.test.ts b/x-pack/plugins/secops/server/graphql/hosts/resolvers.test.ts index eaed24c91bc3..899266b01a2a 100644 --- a/x-pack/plugins/secops/server/graphql/hosts/resolvers.test.ts +++ b/x-pack/plugins/secops/server/graphql/hosts/resolvers.test.ts @@ -6,7 +6,7 @@ import { GraphQLResolveInfo } from 'graphql'; import { omit } from 'lodash/fp'; -import { Source } from '.../../../common/graphql/types'; +import { Source } from '../../graphql/types'; import { FrameworkRequest, internalFrameworkRequest } from '../../lib/framework'; import { Hosts } from '../../lib/hosts'; import { HostsAdapter } from '../../lib/hosts/types'; @@ -63,7 +63,7 @@ const context = { req }; describe('Test Source Resolvers', () => { test('Make sure that getHosts have been called', async () => { const source = await createSourcesResolvers(mockSrcLibs).Query.source( - null, + {}, { id: 'default' }, context, {} as GraphQLResolveInfo diff --git a/x-pack/plugins/secops/server/graphql/hosts/resolvers.ts b/x-pack/plugins/secops/server/graphql/hosts/resolvers.ts index dccac0bdcd0e..97d83c8cd514 100644 --- a/x-pack/plugins/secops/server/graphql/hosts/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/hosts/resolvers.ts @@ -5,19 +5,17 @@ */ import { getOr } from 'lodash/fp'; -import { SourceResolvers } from '../../../common/graphql/types'; -import { AppResolvedResult, AppResolverOf } from '../../lib/framework'; +import { SourceResolvers } from '../../graphql/types'; +import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { Hosts } from '../../lib/hosts'; import { HostsRequestOptions } from '../../lib/hosts/types'; -import { Context } from '../../lib/types'; import { getFields } from '../../utils/build_query/fields'; import { parseFilterQuery } from '../../utils/serialized_query'; import { QuerySourceResolver } from '../sources/resolvers'; -type QueryHostsResolver = AppResolverOf< - SourceResolvers.HostsResolver, - AppResolvedResult, - Context +type QueryHostsResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; export interface HostsResolversDeps { diff --git a/x-pack/plugins/secops/server/graphql/index.ts b/x-pack/plugins/secops/server/graphql/index.ts index f88552d44b44..5f8ba6dd3166 100644 --- a/x-pack/plugins/secops/server/graphql/index.ts +++ b/x-pack/plugins/secops/server/graphql/index.ts @@ -31,7 +31,7 @@ export const schemas = [ // stricter types here, but these should go away when graphql-tools using something // other than "any" in the future for its types. // https://github.com/apollographql/graphql-tools/blob/master/src/mock.ts#L406 -export interface Context { +export interface SecOpsContext { req: { payload: { operationName: string; diff --git a/x-pack/plugins/secops/server/graphql/source_status/resolvers.ts b/x-pack/plugins/secops/server/graphql/source_status/resolvers.ts index 8cebac111595..307a1b1a05ea 100644 --- a/x-pack/plugins/secops/server/graphql/source_status/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/source_status/resolvers.ts @@ -4,35 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexType, SourceStatusResolvers } from '../../../common/graphql/types'; -import { AppResolvedResult, AppResolverOf } from '../../lib/framework'; +import { IndexType, SourceStatusResolvers } from '../../graphql/types'; +import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { IndexFields } from '../../lib/index_fields'; import { SourceStatus } from '../../lib/source_status'; -import { Context } from '../../lib/types'; import { QuerySourceResolver } from '../sources/resolvers'; -export type SourceStatusAuditbeatAliasExistsResolver = AppResolverOf< - SourceStatusResolvers.AuditbeatAliasExistsResolver, - AppResolvedResult, - Context +export type SourceStatusAuditbeatAliasExistsResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; -export type SourceStatusAuditbeatIndicesExistResolver = AppResolverOf< - SourceStatusResolvers.AuditbeatIndicesExistResolver, - AppResolvedResult, - Context +export type SourceStatusAuditbeatIndicesExistResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; -export type SourceStatusAuditbeatIndicesResolver = AppResolverOf< - SourceStatusResolvers.AuditbeatIndicesResolver, - AppResolvedResult, - Context +export type SourceStatusAuditbeatIndicesResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; -export type SourceStatusIndexFieldsResolver = AppResolverOf< - SourceStatusResolvers.IndexFieldsResolver, - AppResolvedResult, - Context +export type SourceStatusIndexFieldsResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; export const createSourceStatusResolvers = (libs: { diff --git a/x-pack/plugins/secops/server/graphql/sources/resolvers.test.ts b/x-pack/plugins/secops/server/graphql/sources/resolvers.test.ts index 3420d831db2d..01d3f9b19b5f 100644 --- a/x-pack/plugins/secops/server/graphql/sources/resolvers.test.ts +++ b/x-pack/plugins/secops/server/graphql/sources/resolvers.test.ts @@ -58,7 +58,7 @@ const context = { req }; describe('Test Source Resolvers', () => { test('Make sure that getConfiguration have been called', async () => { const data = await createSourcesResolvers(mockLibs).Query.source( - null, + {}, { id: 'default' }, context, {} as GraphQLResolveInfo diff --git a/x-pack/plugins/secops/server/graphql/sources/resolvers.ts b/x-pack/plugins/secops/server/graphql/sources/resolvers.ts index 7d62c210dcd2..f3cccfa15b56 100644 --- a/x-pack/plugins/secops/server/graphql/sources/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/sources/resolvers.ts @@ -4,31 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import { QueryResolvers, SourceResolvers } from '../../../common/graphql/types'; -import { AppResolvedResult, AppResolverWithFields } from '../../lib/framework'; +import { QueryResolvers, SourceResolvers } from '../../graphql/types'; +import { + AppResolverOf, + AppResolverWithFields, + ChildResolverOf, + ResultOf, +} from '../../lib/framework'; import { SourceStatus } from '../../lib/source_status'; import { Sources } from '../../lib/sources'; -import { Context } from '../../lib/types'; export type QuerySourceResolver = AppResolverWithFields< QueryResolvers.SourceResolver, - null, - Context, 'id' | 'configuration' >; export type QueryAllSourcesResolver = AppResolverWithFields< QueryResolvers.AllSourcesResolver, - null, - Context, 'id' | 'configuration' >; -export type SourceStatusResolver = AppResolverWithFields< - SourceResolvers.StatusResolver, - AppResolvedResult, - Context, - never +export type SourceStatusResolver = ChildResolverOf< + AppResolverOf>>, + QuerySourceResolver >; export interface SourcesResolversDeps { diff --git a/x-pack/plugins/secops/server/graphql/sources/source.mock.ts b/x-pack/plugins/secops/server/graphql/sources/source.mock.ts index cdee12160763..3c0190c94b6a 100644 --- a/x-pack/plugins/secops/server/graphql/sources/source.mock.ts +++ b/x-pack/plugins/secops/server/graphql/sources/source.mock.ts @@ -5,7 +5,7 @@ */ import { Logger } from '../../utils/logger'; -import { Context } from '../index'; +import { SecOpsContext } from '../index'; /* tslint:disable */ export const mockSourceData = { @@ -41,7 +41,7 @@ export const mockSourceData = { /* tslint:enable */ export const getSourceQueryMock = (logger: Logger) => ({ - source: (root: unknown, args: unknown, context: Context) => { + source: (root: unknown, args: unknown, context: SecOpsContext) => { logger.info('Mock source'); const operationName = context.req.payload.operationName.toLowerCase(); switch (operationName) { diff --git a/x-pack/plugins/secops/server/graphql/sources/sources.mock.ts b/x-pack/plugins/secops/server/graphql/sources/sources.mock.ts index e761b298d49a..8f4f771e7cf8 100644 --- a/x-pack/plugins/secops/server/graphql/sources/sources.mock.ts +++ b/x-pack/plugins/secops/server/graphql/sources/sources.mock.ts @@ -5,7 +5,7 @@ */ import { Logger } from '../../utils/logger'; -import { Context } from '../index'; +import { SecOpsContext } from '../index'; import { mockSourceData } from './source.mock'; /* tslint:disable */ @@ -16,7 +16,7 @@ export const sourcesDataMock = /* tslint:enable */ export const getAllSourcesQueryMock = (logger: Logger) => ({ - allSources: (root: unknown, args: unknown, context: Context) => { + allSources: (root: unknown, args: unknown, context: SecOpsContext) => { logger.info('Mock allSources'); const operationName = context.req.payload.operationName.toLowerCase(); switch (operationName) { diff --git a/x-pack/plugins/secops/server/graphql/types.ts b/x-pack/plugins/secops/server/graphql/types.ts new file mode 100644 index 000000000000..992e99895cb4 --- /dev/null +++ b/x-pack/plugins/secops/server/graphql/types.ts @@ -0,0 +1,1080 @@ +/* tslint:disable */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { SecOpsContext } from '../lib/types'; +import { GraphQLResolveInfo } from 'graphql'; + +export type Resolver = ( + parent: Parent, + args: Args, + context: Context, + info: GraphQLResolveInfo +) => Promise | Result; + +export interface ISubscriptionResolverObject { + subscribe( + parent: P, + args: Args, + context: Context, + info: GraphQLResolveInfo + ): AsyncIterator; + resolve?( + parent: P, + args: Args, + context: Context, + info: GraphQLResolveInfo + ): R | Result | Promise; +} + +export type SubscriptionResolver = + | ((...args: any[]) => ISubscriptionResolverObject) + | ISubscriptionResolverObject; + +// ==================================================== +// START: Typescript template +// ==================================================== + +// ==================================================== +// Types +// ==================================================== + +export interface Query { + /** Get a security data source by id */ + source: Source; + /** Get a list of all security data sources */ + allSources: Source[]; +} + +export interface Source { + /** The id of the source */ + id: string; + /** The raw configuration of the source */ + configuration: SourceConfiguration; + /** The status of the source */ + status: SourceStatus; + /** Gets Suricata events based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + getEvents?: EventsData | null; + /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + Hosts: HostsData; + /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ + UncommonProcesses: UncommonProcessesData; + /** Just a simple example to get the app name */ + whoAmI?: SayMyName | null; +} +/** A set of configuration options for a security data source */ +export interface SourceConfiguration { + /** The alias to read file data from */ + logAlias: string; + /** The alias to read auditbeat data from */ + auditbeatAlias: string; + /** The field mapping to use for this source */ + fields: SourceFields; +} +/** A mapping of semantic fields to their document counterparts */ +export interface SourceFields { + /** The field to identify a container by */ + container: string; + /** The fields to identify a host by */ + host: string; + /** The fields that may contain the log event message. The first field found win. */ + message: string[]; + /** The field to identify a pod by */ + pod: string; + /** The field to use as a tiebreaker for log events that have identical timestamps */ + tiebreaker: string; + /** The field to use as a timestamp for metrics and logs */ + timestamp: string; +} +/** The status of an infrastructure data source */ +export interface SourceStatus { + /** Whether the configured auditbeat alias exists */ + auditbeatAliasExists: boolean; + /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ + auditbeatIndicesExist: boolean; + /** The list of indices in the auditbeat alias */ + auditbeatIndices: string[]; + /** The list of fields defined in the index mappings */ + indexFields: IndexField[]; +} +/** A descriptor of a field in an index */ +export interface IndexField { + /** The name of the field */ + name: string; + /** The type of the field's values as recognized by Kibana */ + type: string; + /** Whether the field's values can be efficiently searched for */ + searchable: boolean; + /** Whether the field's values can be aggregated */ + aggregatable: boolean; +} + +export interface EventsData { + kpiEventType: KpiItem[]; + + events: EventItem[]; +} + +export interface KpiItem { + value: string; + + count: number; +} + +export interface EventItem { + _id?: string | null; + + destination?: DestinationEcsFields | null; + + event?: EventEcsFields | null; + + geo?: GeoEcsFields | null; + + host?: HostEcsFields | null; + + source?: SourceEcsFields | null; + + suricata?: SuricataEcsFields | null; + + timestamp?: string | null; +} + +export interface DestinationEcsFields { + ip?: string | null; + + port?: number | null; +} + +export interface EventEcsFields { + category?: string | null; + + id?: number | null; + + module?: string | null; + + severity?: number | null; + + type?: string | null; +} + +export interface GeoEcsFields { + country_iso_code?: string | null; + + region_name?: string | null; +} + +export interface HostEcsFields { + hostname?: string | null; + + ip?: string | null; +} + +export interface SourceEcsFields { + ip?: string | null; + + port?: number | null; +} + +export interface SuricataEcsFields { + eve?: SuricataEveData | null; +} + +export interface SuricataEveData { + alert?: SuricataAlertData | null; + + flow_id?: number | null; + + proto?: string | null; +} + +export interface SuricataAlertData { + signature?: string | null; + + signature_id?: number | null; +} + +export interface HostsData { + edges: HostsEdges[]; + + totalCount: number; + + pageInfo: PageInfo; +} + +export interface HostsEdges { + host: HostItem; + + cursor: CursorType; +} + +export interface HostItem { + _id?: string | null; + + name?: string | null; + + firstSeen?: string | null; + + version?: string | null; + + os?: string | null; +} + +export interface CursorType { + value: string; + + tiebreaker?: string | null; +} + +export interface PageInfo { + endCursor?: CursorType | null; + + hasNextPage?: boolean | null; +} + +export interface UncommonProcessesData { + edges: UncommonProcessesEdges[]; + + totalCount: number; + + pageInfo: PageInfo; +} + +export interface UncommonProcessesEdges { + uncommonProcess: UncommonProcessItem; + + cursor: CursorType; +} + +export interface UncommonProcessItem { + _id: string; + + name: string; + + title?: string | null; + + instances: number; + + hosts?: (string | null)[] | null; +} + +export interface SayMyName { + /** The id of the source */ + appName: string; +} + +// ==================================================== +// InputTypes +// ==================================================== + +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: number; + /** The beginning of the timerange */ + from: number; +} + +export interface PaginationInput { + /** The limit parameter allows you to configure the maximum amount of items to be returned */ + limit: number; + /** The cursor parameter defines the next result you want to fetch */ + cursor?: string | null; + /** The tiebreaker parameter allow to be more precise to fetch the next item */ + tiebreaker?: string | null; +} + +// ==================================================== +// Arguments +// ==================================================== + +export interface SourceQueryArgs { + /** The id of the source */ + id: string; +} +export interface GetEventsSourceArgs { + timerange: TimerangeInput; + + filterQuery?: string | null; +} +export interface HostsSourceArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; +} +export interface UncommonProcessesSourceArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; +} +export interface IndexFieldsSourceStatusArgs { + indexType?: IndexType | null; +} + +// ==================================================== +// Enums +// ==================================================== + +export enum IndexType { + ANY = 'ANY', + LOGS = 'LOGS', + AUDITBEAT = 'AUDITBEAT', +} + +// ==================================================== +// END: Typescript template +// ==================================================== + +// ==================================================== +// Resolvers +// ==================================================== + +export namespace QueryResolvers { + export interface Resolvers { + /** Get a security data source by id */ + source?: SourceResolver; + /** Get a list of all security data sources */ + allSources?: AllSourcesResolver; + } + + export type SourceResolver = Resolver< + R, + Parent, + Context, + SourceArgs + >; + export interface SourceArgs { + /** The id of the source */ + id: string; + } + + export type AllSourcesResolver = Resolver< + R, + Parent, + Context + >; +} + +export namespace SourceResolvers { + export interface Resolvers { + /** The id of the source */ + id?: IdResolver; + /** The raw configuration of the source */ + configuration?: ConfigurationResolver; + /** The status of the source */ + status?: StatusResolver; + /** Gets Suricata events based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + getEvents?: GetEventsResolver; + /** Gets Hosts based on timerange and specified criteria, or all events in the timerange if no criteria is specified */ + Hosts?: HostsResolver; + /** Gets UncommonProcesses based on a timerange, or all UncommonProcesses if no criteria is specified */ + UncommonProcesses?: UncommonProcessesResolver; + /** Just a simple example to get the app name */ + whoAmI?: WhoAmIResolver; + } + + export type IdResolver = Resolver< + R, + Parent, + Context + >; + export type ConfigurationResolver< + R = SourceConfiguration, + Parent = Source, + Context = SecOpsContext + > = Resolver; + export type StatusResolver = Resolver< + R, + Parent, + Context + >; + export type GetEventsResolver< + R = EventsData | null, + Parent = Source, + Context = SecOpsContext + > = Resolver; + export interface GetEventsArgs { + timerange: TimerangeInput; + + filterQuery?: string | null; + } + + export type HostsResolver = Resolver< + R, + Parent, + Context, + HostsArgs + >; + export interface HostsArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; + } + + export type UncommonProcessesResolver< + R = UncommonProcessesData, + Parent = Source, + Context = SecOpsContext + > = Resolver; + export interface UncommonProcessesArgs { + timerange: TimerangeInput; + + pagination: PaginationInput; + + filterQuery?: string | null; + } + + export type WhoAmIResolver< + R = SayMyName | null, + Parent = Source, + Context = SecOpsContext + > = Resolver; +} +/** A set of configuration options for a security data source */ +export namespace SourceConfigurationResolvers { + export interface Resolvers { + /** The alias to read file data from */ + logAlias?: LogAliasResolver; + /** The alias to read auditbeat data from */ + auditbeatAlias?: AuditbeatAliasResolver; + /** The field mapping to use for this source */ + fields?: FieldsResolver; + } + + export type LogAliasResolver< + R = string, + Parent = SourceConfiguration, + Context = SecOpsContext + > = Resolver; + export type AuditbeatAliasResolver< + R = string, + Parent = SourceConfiguration, + Context = SecOpsContext + > = Resolver; + export type FieldsResolver< + R = SourceFields, + Parent = SourceConfiguration, + Context = SecOpsContext + > = Resolver; +} +/** A mapping of semantic fields to their document counterparts */ +export namespace SourceFieldsResolvers { + export interface Resolvers { + /** The field to identify a container by */ + container?: ContainerResolver; + /** The fields to identify a host by */ + host?: HostResolver; + /** The fields that may contain the log event message. The first field found win. */ + message?: MessageResolver; + /** The field to identify a pod by */ + pod?: PodResolver; + /** The field to use as a tiebreaker for log events that have identical timestamps */ + tiebreaker?: TiebreakerResolver; + /** The field to use as a timestamp for metrics and logs */ + timestamp?: TimestampResolver; + } + + export type ContainerResolver< + R = string, + Parent = SourceFields, + Context = SecOpsContext + > = Resolver; + export type HostResolver = Resolver< + R, + Parent, + Context + >; + export type MessageResolver< + R = string[], + Parent = SourceFields, + Context = SecOpsContext + > = Resolver; + export type PodResolver = Resolver< + R, + Parent, + Context + >; + export type TiebreakerResolver< + R = string, + Parent = SourceFields, + Context = SecOpsContext + > = Resolver; + export type TimestampResolver< + R = string, + Parent = SourceFields, + Context = SecOpsContext + > = Resolver; +} +/** The status of an infrastructure data source */ +export namespace SourceStatusResolvers { + export interface Resolvers { + /** Whether the configured auditbeat alias exists */ + auditbeatAliasExists?: AuditbeatAliasExistsResolver; + /** Whether the configured alias or wildcard pattern resolve to any auditbeat indices */ + auditbeatIndicesExist?: AuditbeatIndicesExistResolver; + /** The list of indices in the auditbeat alias */ + auditbeatIndices?: AuditbeatIndicesResolver; + /** The list of fields defined in the index mappings */ + indexFields?: IndexFieldsResolver; + } + + export type AuditbeatAliasExistsResolver< + R = boolean, + Parent = SourceStatus, + Context = SecOpsContext + > = Resolver; + export type AuditbeatIndicesExistResolver< + R = boolean, + Parent = SourceStatus, + Context = SecOpsContext + > = Resolver; + export type AuditbeatIndicesResolver< + R = string[], + Parent = SourceStatus, + Context = SecOpsContext + > = Resolver; + export type IndexFieldsResolver< + R = IndexField[], + Parent = SourceStatus, + Context = SecOpsContext + > = Resolver; + export interface IndexFieldsArgs { + indexType?: IndexType | null; + } +} +/** A descriptor of a field in an index */ +export namespace IndexFieldResolvers { + export interface Resolvers { + /** The name of the field */ + name?: NameResolver; + /** The type of the field's values as recognized by Kibana */ + type?: TypeResolver; + /** Whether the field's values can be efficiently searched for */ + searchable?: SearchableResolver; + /** Whether the field's values can be aggregated */ + aggregatable?: AggregatableResolver; + } + + export type NameResolver = Resolver< + R, + Parent, + Context + >; + export type TypeResolver = Resolver< + R, + Parent, + Context + >; + export type SearchableResolver< + R = boolean, + Parent = IndexField, + Context = SecOpsContext + > = Resolver; + export type AggregatableResolver< + R = boolean, + Parent = IndexField, + Context = SecOpsContext + > = Resolver; +} + +export namespace EventsDataResolvers { + export interface Resolvers { + kpiEventType?: KpiEventTypeResolver; + + events?: EventsResolver; + } + + export type KpiEventTypeResolver< + R = KpiItem[], + Parent = EventsData, + Context = SecOpsContext + > = Resolver; + export type EventsResolver< + R = EventItem[], + Parent = EventsData, + Context = SecOpsContext + > = Resolver; +} + +export namespace KpiItemResolvers { + export interface Resolvers { + value?: ValueResolver; + + count?: CountResolver; + } + + export type ValueResolver = Resolver< + R, + Parent, + Context + >; + export type CountResolver = Resolver< + R, + Parent, + Context + >; +} + +export namespace EventItemResolvers { + export interface Resolvers { + _id?: IdResolver; + + destination?: DestinationResolver; + + event?: EventResolver; + + geo?: GeoResolver; + + host?: HostResolver; + + source?: SourceResolver; + + suricata?: SuricataResolver; + + timestamp?: TimestampResolver; + } + + export type IdResolver = Resolver< + R, + Parent, + Context + >; + export type DestinationResolver< + R = DestinationEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type EventResolver< + R = EventEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type GeoResolver< + R = GeoEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type HostResolver< + R = HostEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type SourceResolver< + R = SourceEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type SuricataResolver< + R = SuricataEcsFields | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; + export type TimestampResolver< + R = string | null, + Parent = EventItem, + Context = SecOpsContext + > = Resolver; +} + +export namespace DestinationEcsFieldsResolvers { + export interface Resolvers { + ip?: IpResolver; + + port?: PortResolver; + } + + export type IpResolver< + R = string | null, + Parent = DestinationEcsFields, + Context = SecOpsContext + > = Resolver; + export type PortResolver< + R = number | null, + Parent = DestinationEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace EventEcsFieldsResolvers { + export interface Resolvers { + category?: CategoryResolver; + + id?: IdResolver; + + module?: ModuleResolver; + + severity?: SeverityResolver; + + type?: TypeResolver; + } + + export type CategoryResolver< + R = string | null, + Parent = EventEcsFields, + Context = SecOpsContext + > = Resolver; + export type IdResolver< + R = number | null, + Parent = EventEcsFields, + Context = SecOpsContext + > = Resolver; + export type ModuleResolver< + R = string | null, + Parent = EventEcsFields, + Context = SecOpsContext + > = Resolver; + export type SeverityResolver< + R = number | null, + Parent = EventEcsFields, + Context = SecOpsContext + > = Resolver; + export type TypeResolver< + R = string | null, + Parent = EventEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace GeoEcsFieldsResolvers { + export interface Resolvers { + country_iso_code?: CountryIsoCodeResolver; + + region_name?: RegionNameResolver; + } + + export type CountryIsoCodeResolver< + R = string | null, + Parent = GeoEcsFields, + Context = SecOpsContext + > = Resolver; + export type RegionNameResolver< + R = string | null, + Parent = GeoEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace HostEcsFieldsResolvers { + export interface Resolvers { + hostname?: HostnameResolver; + + ip?: IpResolver; + } + + export type HostnameResolver< + R = string | null, + Parent = HostEcsFields, + Context = SecOpsContext + > = Resolver; + export type IpResolver< + R = string | null, + Parent = HostEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace SourceEcsFieldsResolvers { + export interface Resolvers { + ip?: IpResolver; + + port?: PortResolver; + } + + export type IpResolver< + R = string | null, + Parent = SourceEcsFields, + Context = SecOpsContext + > = Resolver; + export type PortResolver< + R = number | null, + Parent = SourceEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace SuricataEcsFieldsResolvers { + export interface Resolvers { + eve?: EveResolver; + } + + export type EveResolver< + R = SuricataEveData | null, + Parent = SuricataEcsFields, + Context = SecOpsContext + > = Resolver; +} + +export namespace SuricataEveDataResolvers { + export interface Resolvers { + alert?: AlertResolver; + + flow_id?: FlowIdResolver; + + proto?: ProtoResolver; + } + + export type AlertResolver< + R = SuricataAlertData | null, + Parent = SuricataEveData, + Context = SecOpsContext + > = Resolver; + export type FlowIdResolver< + R = number | null, + Parent = SuricataEveData, + Context = SecOpsContext + > = Resolver; + export type ProtoResolver< + R = string | null, + Parent = SuricataEveData, + Context = SecOpsContext + > = Resolver; +} + +export namespace SuricataAlertDataResolvers { + export interface Resolvers { + signature?: SignatureResolver; + + signature_id?: SignatureIdResolver; + } + + export type SignatureResolver< + R = string | null, + Parent = SuricataAlertData, + Context = SecOpsContext + > = Resolver; + export type SignatureIdResolver< + R = number | null, + Parent = SuricataAlertData, + Context = SecOpsContext + > = Resolver; +} + +export namespace HostsDataResolvers { + export interface Resolvers { + edges?: EdgesResolver; + + totalCount?: TotalCountResolver; + + pageInfo?: PageInfoResolver; + } + + export type EdgesResolver< + R = HostsEdges[], + Parent = HostsData, + Context = SecOpsContext + > = Resolver; + export type TotalCountResolver< + R = number, + Parent = HostsData, + Context = SecOpsContext + > = Resolver; + export type PageInfoResolver< + R = PageInfo, + Parent = HostsData, + Context = SecOpsContext + > = Resolver; +} + +export namespace HostsEdgesResolvers { + export interface Resolvers { + host?: HostResolver; + + cursor?: CursorResolver; + } + + export type HostResolver = Resolver< + R, + Parent, + Context + >; + export type CursorResolver< + R = CursorType, + Parent = HostsEdges, + Context = SecOpsContext + > = Resolver; +} + +export namespace HostItemResolvers { + export interface Resolvers { + _id?: IdResolver; + + name?: NameResolver; + + firstSeen?: FirstSeenResolver; + + version?: VersionResolver; + + os?: OsResolver; + } + + export type IdResolver = Resolver< + R, + Parent, + Context + >; + export type NameResolver< + R = string | null, + Parent = HostItem, + Context = SecOpsContext + > = Resolver; + export type FirstSeenResolver< + R = string | null, + Parent = HostItem, + Context = SecOpsContext + > = Resolver; + export type VersionResolver< + R = string | null, + Parent = HostItem, + Context = SecOpsContext + > = Resolver; + export type OsResolver = Resolver< + R, + Parent, + Context + >; +} + +export namespace CursorTypeResolvers { + export interface Resolvers { + value?: ValueResolver; + + tiebreaker?: TiebreakerResolver; + } + + export type ValueResolver = Resolver< + R, + Parent, + Context + >; + export type TiebreakerResolver< + R = string | null, + Parent = CursorType, + Context = SecOpsContext + > = Resolver; +} + +export namespace PageInfoResolvers { + export interface Resolvers { + endCursor?: EndCursorResolver; + + hasNextPage?: HasNextPageResolver; + } + + export type EndCursorResolver< + R = CursorType | null, + Parent = PageInfo, + Context = SecOpsContext + > = Resolver; + export type HasNextPageResolver< + R = boolean | null, + Parent = PageInfo, + Context = SecOpsContext + > = Resolver; +} + +export namespace UncommonProcessesDataResolvers { + export interface Resolvers { + edges?: EdgesResolver; + + totalCount?: TotalCountResolver; + + pageInfo?: PageInfoResolver; + } + + export type EdgesResolver< + R = UncommonProcessesEdges[], + Parent = UncommonProcessesData, + Context = SecOpsContext + > = Resolver; + export type TotalCountResolver< + R = number, + Parent = UncommonProcessesData, + Context = SecOpsContext + > = Resolver; + export type PageInfoResolver< + R = PageInfo, + Parent = UncommonProcessesData, + Context = SecOpsContext + > = Resolver; +} + +export namespace UncommonProcessesEdgesResolvers { + export interface Resolvers { + uncommonProcess?: UncommonProcessResolver; + + cursor?: CursorResolver; + } + + export type UncommonProcessResolver< + R = UncommonProcessItem, + Parent = UncommonProcessesEdges, + Context = SecOpsContext + > = Resolver; + export type CursorResolver< + R = CursorType, + Parent = UncommonProcessesEdges, + Context = SecOpsContext + > = Resolver; +} + +export namespace UncommonProcessItemResolvers { + export interface Resolvers { + _id?: IdResolver; + + name?: NameResolver; + + title?: TitleResolver; + + instances?: InstancesResolver; + + hosts?: HostsResolver<(string | null)[] | null, TypeParent, Context>; + } + + export type IdResolver< + R = string, + Parent = UncommonProcessItem, + Context = SecOpsContext + > = Resolver; + export type NameResolver< + R = string, + Parent = UncommonProcessItem, + Context = SecOpsContext + > = Resolver; + export type TitleResolver< + R = string | null, + Parent = UncommonProcessItem, + Context = SecOpsContext + > = Resolver; + export type InstancesResolver< + R = number, + Parent = UncommonProcessItem, + Context = SecOpsContext + > = Resolver; + export type HostsResolver< + R = (string | null)[] | null, + Parent = UncommonProcessItem, + Context = SecOpsContext + > = Resolver; +} + +export namespace SayMyNameResolvers { + export interface Resolvers { + /** The id of the source */ + appName?: AppNameResolver; + } + + export type AppNameResolver = Resolver< + R, + Parent, + Context + >; +} diff --git a/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.test.ts b/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.test.ts index 8d6aa19431fc..7dec747df6a6 100644 --- a/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.test.ts +++ b/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.test.ts @@ -6,7 +6,7 @@ import { GraphQLResolveInfo } from 'graphql'; import { omit } from 'lodash/fp'; -import { Source } from '.../../../common/graphql/types'; +import { Source } from '../../graphql/types'; import { FrameworkRequest, internalFrameworkRequest } from '../../lib/framework'; import { SourceStatus } from '../../lib/source_status'; import { Sources } from '../../lib/sources'; @@ -63,7 +63,7 @@ const context = { req }; describe('Test Source Resolvers', () => { test('Make sure that getUncommonProcesses have been called', async () => { const source = await createSourcesResolvers(mockSrcLibs).Query.source( - null, + {}, { id: 'default' }, context, {} as GraphQLResolveInfo diff --git a/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.ts b/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.ts index b9584360d954..7b22ac4f6449 100644 --- a/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/uncommon_processes/resolvers.ts @@ -5,19 +5,17 @@ */ import { getOr } from 'lodash/fp'; -import { SourceResolvers } from '../../../common/graphql/types'; -import { AppResolvedResult, AppResolverOf } from '../../lib/framework'; -import { Context } from '../../lib/types'; +import { SourceResolvers } from '../../graphql/types'; +import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { UncommonProcesses } from '../../lib/uncommon_processes'; import { UncommonProcessesRequestOptions } from '../../lib/uncommon_processes/types'; import { getFields } from '../../utils/build_query/fields'; import { parseFilterQuery } from '../../utils/serialized_query'; import { QuerySourceResolver } from '../sources/resolvers'; -type QueryUncommonProcessesResolver = AppResolverOf< - SourceResolvers.UncommonProcessesResolver, - AppResolvedResult, - Context +type QueryUncommonProcessesResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; export interface UncommonProcessesResolversDeps { diff --git a/x-pack/plugins/secops/server/graphql/uncommon_processes/uncommon_processes.mock.ts b/x-pack/plugins/secops/server/graphql/uncommon_processes/uncommon_processes.mock.ts index cb38bd63c75c..b814542088f2 100644 --- a/x-pack/plugins/secops/server/graphql/uncommon_processes/uncommon_processes.mock.ts +++ b/x-pack/plugins/secops/server/graphql/uncommon_processes/uncommon_processes.mock.ts @@ -6,7 +6,7 @@ import { FieldNode } from 'graphql'; import { Logger } from '../../utils/logger'; -import { Context } from '../index'; +import { SecOpsContext } from '../index'; /* tslint:disable */ export const mockUncommonProcessesData = { @@ -49,7 +49,7 @@ export const mockUncommonProcessesData = { /* tslint:enable */ export const getUncommonProcessesQueryMock = (logger: Logger) => ({ - source: (root: unknown, args: unknown, context: Context) => { + source: (root: unknown, args: unknown, context: SecOpsContext) => { logger.info('Mock source'); const operationName = context.req.payload.operationName.toLowerCase(); switch (operationName) { diff --git a/x-pack/plugins/secops/server/graphql/who_am_i/resolvers.ts b/x-pack/plugins/secops/server/graphql/who_am_i/resolvers.ts index a1718cd1d212..904daa5dc304 100644 --- a/x-pack/plugins/secops/server/graphql/who_am_i/resolvers.ts +++ b/x-pack/plugins/secops/server/graphql/who_am_i/resolvers.ts @@ -4,15 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SourceResolvers } from '../../../common/graphql/types'; -import { AppResolvedResult, AppResolverOf } from '../../lib/framework'; -import { Context } from '../../lib/types'; +import { SourceResolvers } from '../../graphql/types'; +import { AppResolverOf, ChildResolverOf } from '../../lib/framework'; import { QuerySourceResolver } from '../sources/resolvers'; -export type QueryWhoAmIResolver = AppResolverOf< - SourceResolvers.WhoAmIResolver, - AppResolvedResult, - Context +export type QueryWhoAmIResolver = ChildResolverOf< + AppResolverOf, + QuerySourceResolver >; export const createWhoAmIResolvers = (): { diff --git a/x-pack/plugins/secops/server/lib/events/elasticsearch_adapter.ts b/x-pack/plugins/secops/server/lib/events/elasticsearch_adapter.ts index a332493a136f..351a6c1c2d36 100644 --- a/x-pack/plugins/secops/server/lib/events/elasticsearch_adapter.ts +++ b/x-pack/plugins/secops/server/lib/events/elasticsearch_adapter.ts @@ -5,7 +5,7 @@ */ import { get, has, merge } from 'lodash/fp'; -import { EventItem, EventsData, KpiItem } from '../../../common/graphql/types'; +import { EventItem, EventsData, KpiItem } from '../../graphql/types'; import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { TermAggregation } from '../types'; import { buildQuery, eventFieldsMap } from './query.dsl'; diff --git a/x-pack/plugins/secops/server/lib/events/index.ts b/x-pack/plugins/secops/server/lib/events/index.ts index dca586f99b08..d6c5ca32b08e 100644 --- a/x-pack/plugins/secops/server/lib/events/index.ts +++ b/x-pack/plugins/secops/server/lib/events/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EventsData } from '../../../common/graphql/types'; +import { EventsData } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; export * from './elasticsearch_adapter'; import { EventsAdapter, EventsRequestOptions } from './types'; diff --git a/x-pack/plugins/secops/server/lib/events/types.ts b/x-pack/plugins/secops/server/lib/events/types.ts index 542ff5a7ce72..5a7572aa767e 100644 --- a/x-pack/plugins/secops/server/lib/events/types.ts +++ b/x-pack/plugins/secops/server/lib/events/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { EventsData, SourceConfiguration, TimerangeInput } from '../../../common/graphql/types'; +import { EventsData, SourceConfiguration, TimerangeInput } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; import { ESQuery, SearchHit } from '../types'; diff --git a/x-pack/plugins/secops/server/lib/framework/kibana_framework_adapter.ts b/x-pack/plugins/secops/server/lib/framework/kibana_framework_adapter.ts index aa67be898586..61b18b316377 100644 --- a/x-pack/plugins/secops/server/lib/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/secops/server/lib/framework/kibana_framework_adapter.ts @@ -7,6 +7,8 @@ import { GraphQLSchema } from 'graphql'; import { Request, Server } from 'hapi'; +import { GenericParams } from 'elasticsearch'; +import { Legacy } from 'kibana'; import { graphiqlHapi, graphqlHapi, @@ -21,15 +23,6 @@ import { WrappableRequest, } from './types'; -declare module 'hapi' { - interface PluginProperties { - // tslint:disable-next-line:no-any - elasticsearch: any; - // tslint:disable-next-line:no-any - kibana: any; - } -} - export class KibanaBackendFrameworkAdapter implements FrameworkAdapter { public version: string; private server: Server; @@ -40,11 +33,17 @@ export class KibanaBackendFrameworkAdapter implements FrameworkAdapter { } // tslint:disable-next-line:no-any - public async callWithRequest(req: FrameworkRequest, ...rest: any[]) { + public async callWithRequest( + req: FrameworkRequest, + endpoint: string, + params: GenericParams, + // tslint:disable-next-line:no-any + ...rest: any[] + ) { const internalRequest = req[internalFrameworkRequest]; const { elasticsearch } = internalRequest.server.plugins; const { callWithRequest } = elasticsearch.getCluster('data'); - const fields = await callWithRequest(internalRequest, ...rest); + const fields = await callWithRequest(internalRequest, endpoint, params, ...rest); return fields; } @@ -92,11 +91,11 @@ export class KibanaBackendFrameworkAdapter implements FrameworkAdapter { } return this.server.indexPatternsServiceFactory({ // tslint:disable-next-line:no-any - callCluster: async (method: string, args: [object], ...rest: any[]) => { + callCluster: async (method: string, args: [GenericParams], ...rest: any[]) => { const fieldCaps = await this.callWithRequest( request, method, - { ...args, allowNoIndices: true }, + { ...args, allowNoIndices: true } as GenericParams, ...rest ); return fieldCaps; diff --git a/x-pack/plugins/secops/server/lib/framework/types.ts b/x-pack/plugins/secops/server/lib/framework/types.ts index 98be0563b4b7..464bcbe883b1 100644 --- a/x-pack/plugins/secops/server/lib/framework/types.ts +++ b/x-pack/plugins/secops/server/lib/framework/types.ts @@ -6,7 +6,7 @@ import { GraphQLSchema } from 'graphql'; -export * from '../../../common/graphql/typed_resolvers'; +export * from '../../utils/typed_resolvers'; export const internalFrameworkRequest = Symbol('internalFrameworkRequest'); diff --git a/x-pack/plugins/secops/server/lib/hosts/elasticsearch_adapter.ts b/x-pack/plugins/secops/server/lib/hosts/elasticsearch_adapter.ts index ad94b73ebcec..06adc4e0a1c8 100644 --- a/x-pack/plugins/secops/server/lib/hosts/elasticsearch_adapter.ts +++ b/x-pack/plugins/secops/server/lib/hosts/elasticsearch_adapter.ts @@ -5,7 +5,7 @@ */ import { get, getOr, head } from 'lodash/fp'; -import { HostsData, HostsEdges } from '../../../common/graphql/types'; +import { HostsData, HostsEdges } from '../../graphql/types'; import { mergeFieldsWithHit } from '../../utils/build_query'; import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { TermAggregation } from '../types'; diff --git a/x-pack/plugins/secops/server/lib/hosts/index.ts b/x-pack/plugins/secops/server/lib/hosts/index.ts index 0adeccda4551..587b4d508df4 100644 --- a/x-pack/plugins/secops/server/lib/hosts/index.ts +++ b/x-pack/plugins/secops/server/lib/hosts/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { HostsData } from '../../../common/graphql/types'; +import { HostsData } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; export * from './elasticsearch_adapter'; import { HostsAdapter, HostsRequestOptions } from './types'; diff --git a/x-pack/plugins/secops/server/lib/hosts/types.ts b/x-pack/plugins/secops/server/lib/hosts/types.ts index 70f8a1eed692..6b50debcb92e 100644 --- a/x-pack/plugins/secops/server/lib/hosts/types.ts +++ b/x-pack/plugins/secops/server/lib/hosts/types.ts @@ -9,7 +9,7 @@ import { PaginationInput, SourceConfiguration, TimerangeInput, -} from '../../../common/graphql/types'; +} from '../../graphql/types'; import { FrameworkRequest } from '../framework'; import { ESQuery, SearchHit } from '../types'; diff --git a/x-pack/plugins/secops/server/lib/index_fields/elasticsearch_adapter.ts b/x-pack/plugins/secops/server/lib/index_fields/elasticsearch_adapter.ts index 543826c3916f..9cf01b4e1438 100644 --- a/x-pack/plugins/secops/server/lib/index_fields/elasticsearch_adapter.ts +++ b/x-pack/plugins/secops/server/lib/index_fields/elasticsearch_adapter.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexField } from '../../../common/graphql/types'; +import { IndexField } from '../../graphql/types'; import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { FieldsAdapter } from './types'; diff --git a/x-pack/plugins/secops/server/lib/index_fields/index.ts b/x-pack/plugins/secops/server/lib/index_fields/index.ts index b52a58988923..38cc1a30ee1b 100644 --- a/x-pack/plugins/secops/server/lib/index_fields/index.ts +++ b/x-pack/plugins/secops/server/lib/index_fields/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexField, IndexType } from '../../../common/graphql/types'; +import { IndexField, IndexType } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; import { Sources } from '../sources'; import { FieldsAdapter } from './types'; diff --git a/x-pack/plugins/secops/server/lib/index_fields/types.ts b/x-pack/plugins/secops/server/lib/index_fields/types.ts index e0b89027d64c..d8bc4c388055 100644 --- a/x-pack/plugins/secops/server/lib/index_fields/types.ts +++ b/x-pack/plugins/secops/server/lib/index_fields/types.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IndexField, IndexType } from '../../../common/graphql/types'; +import { IndexField, IndexType } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; export interface FieldsAdapter { diff --git a/x-pack/plugins/secops/server/lib/types.ts b/x-pack/plugins/secops/server/lib/types.ts index 21cdcd9ea763..0fea858b4fc1 100644 --- a/x-pack/plugins/secops/server/lib/types.ts +++ b/x-pack/plugins/secops/server/lib/types.ts @@ -37,7 +37,7 @@ export interface Configuration { sources: SourceConfigurations; } -export interface Context { +export interface SecOpsContext { req: FrameworkRequest; } diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts index fb74fca4babf..2ffc29866a05 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts @@ -5,7 +5,7 @@ */ import { getOr } from 'lodash/fp'; -import { UncommonProcessesData, UncommonProcessesEdges } from '../../../common/graphql/types'; +import { UncommonProcessesData, UncommonProcessesEdges } from '../../graphql/types'; import { mergeFieldsWithHit } from '../../utils/build_query'; import { FrameworkAdapter, FrameworkRequest } from '../framework'; import { TermAggregation } from '../types'; diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/index.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/index.ts index dcad00d33cd7..bf3871cd5a26 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/index.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { UncommonProcessesData } from '../../../common/graphql/types'; +import { UncommonProcessesData } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; export * from './elasticsearch_adapter'; import { UncommonProcessesAdapter, UncommonProcessesRequestOptions } from './types'; diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts index 1477915d17cb..d85801324d2c 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts @@ -9,7 +9,7 @@ import { SourceConfiguration, TimerangeInput, UncommonProcessesData, -} from '../../../common/graphql/types'; +} from '../../graphql/types'; import { FrameworkRequest } from '../framework'; import { ESQuery, SearchHit } from '../types'; diff --git a/x-pack/plugins/secops/server/utils/typed_resolvers.ts b/x-pack/plugins/secops/server/utils/typed_resolvers.ts new file mode 100644 index 000000000000..e3fcbd7d2140 --- /dev/null +++ b/x-pack/plugins/secops/server/utils/typed_resolvers.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { Resolver } from '../graphql/types'; + +type ResolverResult = R | Promise; + +type AppResolverResult = + | Promise + | Promise<{ [P in keyof R]: () => Promise }> + | { [P in keyof R]: () => Promise } + | { [P in keyof R]: () => R[P] } + | R; + +export type ResultOf = Resolver_ extends Resolver> + ? Result + : never; + +export type SubsetResolverWithFields = R extends Resolver< + Array, + infer ParentInArray, + infer ContextInArray, + infer ArgsInArray +> + ? Resolver< + Array>>, + ParentInArray, + ContextInArray, + ArgsInArray + > + : R extends Resolver + ? Resolver>, Parent, Context, Args> + : never; + +export type SubsetResolverWithoutFields = R extends Resolver< + Array, + infer ParentInArray, + infer ContextInArray, + infer ArgsInArray +> + ? Resolver< + Array>>, + ParentInArray, + ContextInArray, + ArgsInArray + > + : R extends Resolver + ? Resolver>, Parent, Context, Args> + : never; + +export type ResolverWithParent = Resolver_ extends Resolver< + infer Result, + // tslint:disable-next-line:no-any + any, + infer Context, + infer Args +> + ? Resolver + : never; + +// tslint:disable-next-line:no-any +export type AppResolver = Resolver< + AppResolverResult, + Parent, + Context, + Args +>; + +export type AppResolverOf = Resolver_ extends Resolver< + ResolverResult, + never, + infer ContextWithNeverParent, + infer ArgsWithNeverParent +> + ? AppResolver + : Resolver_ extends Resolver< + ResolverResult, + infer Parent, + infer Context, + infer Args + > + ? AppResolver + : never; + +export type AppResolverWithFields = AppResolverOf< + SubsetResolverWithFields +>; + +export type AppResolverWithoutFields = AppResolverOf< + SubsetResolverWithoutFields +>; + +export type ChildResolverOf = ResolverWithParent< + Resolver_, + ResultOf +>; diff --git a/x-pack/test/api_integration/apis/secops/hosts.ts b/x-pack/test/api_integration/apis/secops/hosts.ts index 473b3dba9216..85edbce6de4e 100644 --- a/x-pack/test/api_integration/apis/secops/hosts.ts +++ b/x-pack/test/api_integration/apis/secops/hosts.ts @@ -5,8 +5,8 @@ */ import expect from 'expect.js'; -import { GetHostsQuery } from '../../../../plugins/secops/common/graphql/types'; import { hostsQuery } from '../../../../plugins/secops/public/containers/hosts/index.gql_query'; +import { GetHostsQuery } from '../../../../plugins/secops/public/graphql/types'; import { KbnTestProvider } from './types'; diff --git a/x-pack/test/api_integration/apis/secops/sources.ts b/x-pack/test/api_integration/apis/secops/sources.ts index 7c63cec007a1..ab494702cbb3 100644 --- a/x-pack/test/api_integration/apis/secops/sources.ts +++ b/x-pack/test/api_integration/apis/secops/sources.ts @@ -5,8 +5,8 @@ */ import expect from 'expect.js'; -import { SourceQuery } from '../../../../plugins/secops/common/graphql/types'; import { sourceQuery } from '../../../../plugins/secops/public/containers/source/index.gql_query'; +import { SourceQuery } from '../../../../plugins/secops/public/graphql/types'; import { KbnTestProvider } from './types'; From f0e2ea33d2fc3b0bff0935fa50ee5bf459e8613b Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Sun, 23 Dec 2018 09:20:01 -0500 Subject: [PATCH 2/3] fix uncommonProcess because elasticsearch change the total attribute to an object and not just the value --- .../server/lib/uncommon_processes/elasticsearch_adapter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts index 2ffc29866a05..795beefa8754 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/elasticsearch_adapter.ts @@ -39,7 +39,6 @@ export class ElasticsearchUncommonProcessesAdapter implements UncommonProcessesA formatUncommonProcessesData(options.fields, hit, processFieldsMap) ); const edges = uncommonProcessesEdges.splice(0, limit); - return { edges, totalCount, @@ -77,7 +76,7 @@ export const formatUncommonProcessesData = ( fields.reduce( (flattenedFields, fieldName) => { flattenedFields.uncommonProcess._id = hit._id; - flattenedFields.uncommonProcess.instances = hit.total; + flattenedFields.uncommonProcess.instances = getOr(0, 'total.value', hit); flattenedFields.uncommonProcess.hosts = hit.hosts; if (hit.cursor) { flattenedFields.cursor.value = hit.cursor; From 48642147f04b4748ead873353e2a3633a195787a Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Sun, 23 Dec 2018 17:18:14 -0500 Subject: [PATCH 3/3] fix unit test by adding the new interface for total hit --- x-pack/plugins/secops/server/lib/types.ts | 5 +++++ .../uncommon_processes/elastic_adapter.test.ts | 15 ++++++++++++--- .../secops/server/lib/uncommon_processes/types.ts | 6 +++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/secops/server/lib/types.ts b/x-pack/plugins/secops/server/lib/types.ts index 0fea858b4fc1..d8c4a9211e55 100644 --- a/x-pack/plugins/secops/server/lib/types.ts +++ b/x-pack/plugins/secops/server/lib/types.ts @@ -123,3 +123,8 @@ export interface TermAggregation { }>; }; } + +export interface TotalHit { + value: number; + relation: string; +} diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/elastic_adapter.test.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/elastic_adapter.test.ts index aab334091d73..af828190143f 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/elastic_adapter.test.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/elastic_adapter.test.ts @@ -16,7 +16,10 @@ describe('elasticsearch_adapter', () => { }, process: { hits: { - total: 1, + total: { + value: 1, + relation: 'eq', + }, max_score: 5, hits: [], }, @@ -29,7 +32,10 @@ describe('elasticsearch_adapter', () => { }, process: { hits: { - total: 1, + total: { + value: 1, + relation: 'eq', + }, max_score: 5, hits: [], }, @@ -58,7 +64,10 @@ describe('elasticsearch_adapter', () => { _type: 'type-123', _id: 'id-123', _score: 10, - total: 100, + total: { + value: 100, + relation: 'eq', + }, hosts: ['host-1', 'host-2'], _source: { '@timestamp': 'time', diff --git a/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts b/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts index d85801324d2c..ac4ce17235ba 100644 --- a/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts +++ b/x-pack/plugins/secops/server/lib/uncommon_processes/types.ts @@ -11,7 +11,7 @@ import { UncommonProcessesData, } from '../../graphql/types'; import { FrameworkRequest } from '../framework'; -import { ESQuery, SearchHit } from '../types'; +import { ESQuery, SearchHit, TotalHit } from '../types'; export interface UncommonProcessesAdapter { getUncommonProcesses( @@ -34,7 +34,7 @@ export interface UncommonProcessHit { _type: string; _id: string; _score: number | null; - total: number; + total: TotalHit; hosts: string[]; _source: { '@timestamp': string; @@ -57,7 +57,7 @@ export interface UncommonProcessBucket { }; process: { hits: { - total: number; + total: TotalHit; max_score: number | null; hits: UncommonProcessHit[]; };